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,4 +1,5 @@
# -*- coding: utf-8 -*-
from odoo import fields
from odoo.tests.common import TransactionCase, tagged
@@ -392,3 +393,50 @@ class TestFusionLoginAuditModel(TransactionCase):
pass
after = Mail.search_count([('subject', 'ilike', 'disabled@example.com')])
self.assertEqual(after, before, "Disabled alerts should queue nothing")
def test_retention_gc_deletes_old_rows(self):
"""The GC method deletes rows older than retention_days."""
from datetime import timedelta
ICP = self.env['ir.config_parameter'].sudo()
ICP.set_param('fusion_login_audit.retention_days', '30')
now = fields.Datetime.now()
Audit = self.env['fusion.login.audit'].sudo()
old = Audit.create({
'attempted_login': 'gc-old@example.com',
'result': 'success',
'event_time': now - timedelta(days=45),
})
recent = Audit.create({
'attempted_login': 'gc-recent@example.com',
'result': 'success',
'event_time': now - timedelta(days=5),
})
old_id, recent_id = old.id, recent.id
Audit._fc_retention_gc()
self.assertFalse(Audit.browse(old_id).exists(),
"Row older than retention_days should be gone")
self.assertTrue(Audit.browse(recent_id).exists(),
"Row inside retention_days should survive")
def test_retention_zero_keeps_forever(self):
"""retention_days=0 keeps all rows."""
from datetime import timedelta
ICP = self.env['ir.config_parameter'].sudo()
ICP.set_param('fusion_login_audit.retention_days', '0')
now = fields.Datetime.now()
Audit = self.env['fusion.login.audit'].sudo()
ancient = Audit.create({
'attempted_login': 'forever@example.com',
'result': 'success',
'event_time': now - timedelta(days=3650),
})
ancient_id = ancient.id
Audit._fc_retention_gc()
self.assertTrue(Audit.browse(ancient_id).exists(),
"retention_days=0 must keep everything")