Files
Odoo-Modules/fusion_clock/controllers/clock_nfc_kiosk.py
gsinghpal a24a1ddf1a feat(fusion_clock): NFC card UID normalization helper
Add _normalize_uid static method to FusionClockNfcKiosk that strips
whitespace, uppercases, removes separators, validates hex-only content,
and reformats to canonical colon-separated pairs; returns None for
empty/invalid input. Covered by 7 new TransactionCase unit tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 00:56:02 -04:00

54 lines
2.0 KiB
Python

# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
import logging
import re
from odoo import http
from odoo.http import request
_logger = logging.getLogger(__name__)
_UID_HEX_PATTERN = re.compile(r'^[0-9A-F]+$')
class FusionClockNfcKiosk(http.Controller):
"""NFC tap-to-clock kiosk controller. Reuses FusionClockAPI helpers."""
@staticmethod
def _normalize_uid(uid):
"""Normalize an NFC card UID to canonical hex (uppercase, colon-separated).
Returns None if the input is empty or not valid hex.
"""
if not uid:
return None
cleaned = uid.strip().upper().replace('-', '').replace(':', '').replace(' ', '')
if not cleaned or not _UID_HEX_PATTERN.match(cleaned):
return None
if len(cleaned) % 2 != 0:
return None
return ':'.join(cleaned[i:i+2] for i in range(0, len(cleaned), 2))
@http.route('/fusion_clock/kiosk/nfc', type='http', auth='user', website=True)
def nfc_kiosk_page(self, **kw):
"""Render the NFC kiosk page for a wall-mounted tablet."""
user = request.env.user
if not user.has_group('fusion_clock.group_fusion_clock_manager'):
return request.redirect('/my')
ICP = request.env['ir.config_parameter'].sudo()
if ICP.get_param('fusion_clock.enable_nfc_kiosk', 'False') != 'True':
return request.redirect('/my')
company = request.env.company
location = company.x_fclk_nfc_kiosk_location_id
values = {
'page_name': 'nfc_kiosk',
'company_name': company.name,
'location_name': location.name if location else 'No location configured',
'location_configured': bool(location),
'photo_required': ICP.get_param('fusion_clock.nfc_photo_required', 'True') == 'True',
'debug_enabled': ICP.get_param('fusion_clock.nfc_kiosk_debug', 'False') == 'True',
}
return request.render('fusion_clock.nfc_kiosk_page', values)