fix(fusion_clock): enforce NFC card-UID uniqueness via declarative UniqueIndex

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) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-05-30 22:34:14 -04:00
parent a479052b72
commit 136a64ea21
2 changed files with 10 additions and 8 deletions

View File

@@ -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': """

View File

@@ -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(