import hashlib from datetime import date from app.core.config import settings ALPHABET = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ" def _to_base32ish(value: int, length: int) -> str: chars: list[str] = [] base = len(ALPHABET) while value: value, remainder = divmod(value, base) chars.append(ALPHABET[remainder]) encoded = "".join(reversed(chars)) or ALPHABET[0] return encoded[-length:].rjust(length, ALPHABET[0]) def _digest_int(payload: str) -> int: digest = hashlib.sha256(payload.encode("utf-8")).digest() return int.from_bytes(digest[:8], "big") def build_certificate_no(sequence_id: int, project_code: str, issue_date: date | None = None) -> str: year = (issue_date or date.today()).year normalized_project = project_code.strip().upper() seed = f"{settings.certificate_no_secret}:{year}:{normalized_project}:{sequence_id}" short_code = _to_base32ish(_digest_int(seed), 7) check_code = _to_base32ish(_digest_int(f"check:{seed}:{short_code}"), 2) return f"PX{year}-{normalized_project}-{short_code}-{check_code}"