diff --git a/fusion_clock/__manifest__.py b/fusion_clock/__manifest__.py index 0ffbfc64..77de44f8 100644 --- a/fusion_clock/__manifest__.py +++ b/fusion_clock/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Fusion Clock', - 'version': '19.0.3.12.2', + 'version': '19.0.3.12.3', 'category': 'Human Resources/Attendances', 'summary': 'Complete Employee T&A with Geofencing, Shifts, Penalties, Overtime, Kiosk, Dashboard & Payroll Export', 'description': """ diff --git a/fusion_clock/models/hr_employee.py b/fusion_clock/models/hr_employee.py index 0b55524f..f8a73e0e 100644 --- a/fusion_clock/models/hr_employee.py +++ b/fusion_clock/models/hr_employee.py @@ -58,13 +58,15 @@ class HrEmployee(models.Model): "Same card the employee uses for door access.", ) - _sql_constraints = [ - ( - 'fclk_nfc_card_uid_unique', - 'UNIQUE(x_fclk_nfc_card_uid)', - 'This NFC card is already assigned to another employee.', - ), - ] + # Enforce NFC card-UID uniqueness ONLY when a UID is set. Odoo 19 silently ignores + # the legacy `_sql_constraints` list (see repo-root CLAUDE.md rule 9), so this never + # created a DB constraint. Use the declarative UniqueIndex with a partial WHERE so the + # many employees without a card can share a blank/NULL value, while two employees can + # never be assigned the same physical card. + _fclk_nfc_card_uid_unique = models.UniqueIndex( + "(x_fclk_nfc_card_uid) WHERE x_fclk_nfc_card_uid IS NOT NULL AND x_fclk_nfc_card_uid != ''", + 'This NFC card is already assigned to another employee.', + ) # On-time streak x_fclk_ontime_streak = fields.Integer(