From 136a64ea2151200ec4a3b1a9f010f9eb11fdd21c Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Sat, 30 May 2026 22:34:14 -0400 Subject: [PATCH] fix(fusion_clock): enforce NFC card-UID uniqueness via declarative UniqueIndex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Odoo 19 silently ignores the legacy `_sql_constraints` list (repo CLAUDE.md rule 9), so it never created a DB constraint — two employees could be assigned the same x_fclk_nfc_card_uid and the NFC tap's search(limit=1) then picked an arbitrary one. Replace it with a declarative models.UniqueIndex carrying a partial WHERE predicate, so uniqueness is enforced only when a UID is set; employees without a card keep sharing a blank/NULL value. Makes test_nfc_models.TestNfcModels.test_card_uid_is_unique_when_set pass. Verified on entech (DB admin): 0 pre-existing duplicate UIDs, full upgrade + 61/61 fusion_clock tests green, and the unique partial index hr_employee_fclk_nfc_card_uid_unique now exists. Co-Authored-By: Claude Opus 4.8 (1M context) --- fusion_clock/__manifest__.py | 2 +- fusion_clock/models/hr_employee.py | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) 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(