feat(fusion_login_audit): nightly retention GC cron

Adds _fc_retention_gc() that deletes rows older than the configured
horizon (default 365 days; 0 = keep forever). Registered as a daily
ir.cron. Tests verify both the delete path and the "keep forever"
short-circuit.

Also documents the Odoo 19 gotcha that ir.cron dropped the numbercall
field (the legacy "-1 = run forever" pattern now raises ValueError at
install time; just omit the field).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-05-26 21:46:23 -04:00
parent a2d13cf83b
commit 1b8038d8e8
5 changed files with 88 additions and 1 deletions

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from odoo import fields, models
from odoo import api, fields, models
class FusionLoginAudit(models.Model):
@@ -83,3 +83,23 @@ class FusionLoginAudit(models.Model):
_user_time_idx = models.Index('(user_id, event_time DESC)')
_login_time_idx = models.Index('(attempted_login, event_time DESC)')
_geo_state_idx = models.Index('(geo_lookup_state, event_time)')
@api.model
def _fc_retention_gc(self):
"""Delete audit rows older than `fusion_login_audit.retention_days`.
Called daily by ir.cron. retention_days=0 means keep forever."""
from datetime import timedelta
ICP = self.env['ir.config_parameter'].sudo()
try:
days = int(ICP.get_param(
'fusion_login_audit.retention_days', 365))
except (TypeError, ValueError):
days = 365
if days <= 0:
return 0
cutoff = fields.Datetime.now() - timedelta(days=days)
old = self.sudo().search([('event_time', '<', cutoff)])
count = len(old)
if old:
old.unlink()
return count