"""Badge resolution for the printedparts plugin. Same input contract as the USB plugin (deliberately copied, not imported - cross-plugin imports break the shopdb.api-only contract): - all digits -> an SSO typed or scanned directly - 0BZ -> a physical badge wrapping a PayNo (keyboard-wedge scanners emit this shape) - anything else -> unresolvable Names come from the employees plugin's self-hosted directory, looked up by SSO. The directory carries no PayNo column, so PayNo badges resolve only when the wrapped digits are themselves the SSO (true at sites whose badges encode the SSO); otherwise they fall to the unknown-badge policy. Policy (Setting printedparts_unknown_badge): 'deny' (default) rejects a badge with no directory match; 'allow' records the SSO with an empty name. """ import re from shopdb.api import Setting _PAYNO_BADGE = re.compile(r'^0(\d+)BZ$', re.IGNORECASE) class BadgeError(ValueError): """Raised when a badge cannot be accepted under the site policy.""" def _directory_name(sso): """Best-effort display name from the employees plugin directory.""" try: from plugins.employees.models import DirectoryEmployee from shopdb.api import db if sso and str(sso).isdigit(): employee = db.session.get(DirectoryEmployee, int(sso)) if employee: return f'{employee.firstname} {employee.lastname}'.strip() except Exception: pass return None def resolve_badge(badge): """Return (sso, name) for a scanned badge, enforcing the site policy. Raises BadgeError with a kiosk-displayable message when the badge shape is unrecognized or the policy denies an unmatched badge. """ badge = (badge or '').strip() if not badge: raise BadgeError('Scan or enter a badge') if badge.isdigit(): sso = badge else: match = _PAYNO_BADGE.match(badge) if not match: raise BadgeError('Unrecognized badge format') sso = match.group(1) name = _directory_name(sso) if name is None: policy = (Setting.get('printedparts_unknown_badge') or 'deny').lower() if policy != 'allow': raise BadgeError('Badge not recognized - see the parts team') return sso, '' return sso, name