"""Cheie de idempotenta = hash de continut canonic. RAR nu are camp nr. comanda si accepta duplicate -> dedup-ul e in sarcina noastra (plan.md sect. 14). Hash stabil peste o reprezentare canonica a prezentarii. """ from __future__ import annotations import hashlib import json from typing import Any def idempotency_key(account_id: int | None, prezentare: dict[str, Any]) -> str: """SHA-256 peste (account_id + campurile semnificative ale prezentarii). Exclude obs si b64Image (cosmetice, nu definesc unicitatea declaratiei). """ canonic = { "account_id": account_id, "vin": (prezentare.get("vin") or "").strip().upper(), "nr_inmatriculare": (prezentare.get("nr_inmatriculare") or "").strip().upper(), "data_prestatie": prezentare.get("data_prestatie"), "odometru_final": str(prezentare.get("odometru_final") or "").strip(), "prestatii": sorted( str(p.get("cod_prestatie") if isinstance(p, dict) else getattr(p, "cod_prestatie", "")) for p in (prezentare.get("prestatii") or []) ), } blob = json.dumps(canonic, sort_keys=True, ensure_ascii=False, separators=(",", ":")) return hashlib.sha256(blob.encode("utf-8")).hexdigest()