# -*- coding: utf-8 -*- # Copyright 2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) import base64 from datetime import timedelta from odoo import fields from odoo.tests import tagged from odoo.tests.common import TransactionCase @tagged('-at_install', 'post_install', 'fusion_clock') class TestPhotoRetention(TransactionCase): """The daily wipe cron must delete verification photos older than the retention window while keeping the attendance records (and recent photos).""" def setUp(self): super().setUp() self.Attendance = self.env['hr.attendance'] self.ICP = self.env['ir.config_parameter'].sudo() self.emp = self.env['hr.employee'].create({'name': 'Retention Test Emp'}) # x_fclk_check_*_photo are plain Binary fields (no image validation), # so arbitrary base64 bytes are fine for the test. self.photo = base64.b64encode(b'pretend-jpeg-bytes') self.ICP.set_param('fusion_clock.photo_retention_days', '60') def _make_attendance(self, days_ago): start = fields.Datetime.now() - timedelta(days=days_ago) att = self.Attendance.create({ 'employee_id': self.emp.id, 'check_in': start, 'check_out': start + timedelta(hours=8), }) att.x_fclk_check_in_photo = self.photo att.x_fclk_check_out_photo = self.photo return att def test_old_photos_wiped_recent_kept(self): old = self._make_attendance(days_ago=70) recent = self._make_attendance(days_ago=5) self.assertTrue(old.x_fclk_check_in_photo) self.assertTrue(recent.x_fclk_check_in_photo) self.Attendance._cron_fusion_wipe_old_photos() self.env.invalidate_all() # binary fields are cached; re-read from DB # Old shift: both photos gone, but the record + hours survive. self.assertFalse(old.x_fclk_check_in_photo, "Old check-in photo should be wiped") self.assertFalse(old.x_fclk_check_out_photo, "Old check-out photo should be wiped") self.assertTrue(old.exists(), "Attendance record itself must be kept") self.assertGreater(old.worked_hours, 0.0, "Worked hours must be preserved") # Recent shift: photo untouched. self.assertTrue(recent.x_fclk_check_in_photo, "Recent photo should be kept") def test_zero_retention_disables_wipe(self): self.ICP.set_param('fusion_clock.photo_retention_days', '0') old = self._make_attendance(days_ago=200) self.Attendance._cron_fusion_wipe_old_photos() self.env.invalidate_all() self.assertTrue(old.x_fclk_check_in_photo, "Retention=0 must disable the wipe")