feat(editor): editor prestatii unificat in modal - un select, un rand de chips (PRD 5.23)
Inlocuieste cele 3 controale de asociere cod RAR cu un singur rand de chips + un singur select care adauga instant la change. Stare = un hidden chips_state JSON versionat; post_form_chips redus la 2 actiuni (add/remove). Optgroup Sugestii (fuzzy/k-NN) + optiune "Nu se declara la RAR" in select, cu tinta implicita evidentiata si placeholder care o numeste. exclus persistat prin payload_json (treapta noua de precedenta in resolve_prestatii, round-trip complet). Siguranta: itemii exclusi sunt scosi din payload la momentul trimiterii (worker split_prestatii_excluse inainte de build_rar_payload + filtru defensiv), ca sa nu ajunga NICIODATA la RAR ca codPrestatie:null. Suita: 1680 passed, 1 skipped. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -233,8 +233,10 @@ def _resolve_row_for_preview(
|
||||
"flags": all_flags,
|
||||
}
|
||||
|
||||
# Operatii excluse de la declarare: ies din prestatiile trimise (si din cheia
|
||||
# de idempotenta). Toate excluse -> rand 'excluded' (nu se trimite, nu blocheaza).
|
||||
# Operatii excluse de la declarare: ies DOAR din payload-ul trimis la RAR (si din
|
||||
# cheia de idempotenta), NU din `mapped["prestatii"]` persistat/afisat — editorul
|
||||
# (chips modal) trebuie sa arate chip-ul Nedeclarat la redeschidere (round-trip).
|
||||
# Toate excluse -> rand 'excluded' (nu se trimite, nu blocheaza).
|
||||
declarabile, excluse = split_prestatii_excluse(resolved)
|
||||
if excluse and not declarabile:
|
||||
return {
|
||||
@@ -243,11 +245,10 @@ def _resolve_row_for_preview(
|
||||
"errors": [],
|
||||
"flags": all_flags,
|
||||
}
|
||||
if excluse:
|
||||
mapped["prestatii"] = declarabile
|
||||
|
||||
# Validare continut
|
||||
errors = validate_prezentare(mapped)
|
||||
# Validare continut: doar partea declarabila conteaza (validate_prezentare
|
||||
# ignora oricum itemii fara cod_prestatie, dar `mapped` ramane intact pentru afisare).
|
||||
errors = validate_prezentare({**mapped, "prestatii": declarabile} if excluse else mapped)
|
||||
|
||||
if all_flags and not reviewed:
|
||||
# needs_review: validarea a trecut, dar flagurile (date ambigue, formule) cer confirmare manuala.
|
||||
@@ -852,7 +853,15 @@ def preview_import(
|
||||
key = None
|
||||
if resolved_info["resolved_status"] in ("ok", "needs_review", "needs_data"):
|
||||
try:
|
||||
key = _build_idempotency_key(account_id, resolved_info["resolved"], preview_env)
|
||||
# Cheia foloseste DOAR partea declarabila (itemii exclusi nu intra in
|
||||
# hash) — identic cu cheia calculata la commit (linia cu
|
||||
# split_prestatii_excluse din commit_import), altfel preview-ul
|
||||
# arata alt duplicat decat cel real.
|
||||
_key_resolved = resolved_info["resolved"]
|
||||
_decl_key, _exc_key = split_prestatii_excluse(_key_resolved.get("prestatii"))
|
||||
if _exc_key:
|
||||
_key_resolved = {**_key_resolved, "prestatii": _decl_key}
|
||||
key = _build_idempotency_key(account_id, _key_resolved, preview_env)
|
||||
keys_for_lookup.append(key)
|
||||
if key not in key_to_index:
|
||||
key_to_index[key] = []
|
||||
@@ -1204,16 +1213,19 @@ def commit_import(
|
||||
# Rezolva prestatii INAINTE de canonicalizare (altfel cheia difera de cea din preview)
|
||||
prestatii = mapped.get("prestatii") or []
|
||||
resolved, _ = resolve_prestatii(prestatii, mapping, valid_codes, text_rules, excluded_ops)
|
||||
# Prestatiile excluse de la declarare NU pleaca la RAR (ca in preview);
|
||||
# Prestatiile excluse de la declarare NU pleaca la RAR si nu intra in
|
||||
# cheia de idempotenta, dar RAMAN in payload_json persistat (round-trip
|
||||
# in editor, ca in preview) — ingustarea la declarabile se face doar
|
||||
# local, pentru canon/cheie, si la worker, la momentul trimiterii.
|
||||
declarabile, _excluse = split_prestatii_excluse(resolved)
|
||||
# rand fara nicio prestatie declarabila = 'excluded' in preview -> defensiv skip.
|
||||
resolved, _excluse = split_prestatii_excluse(resolved)
|
||||
if not resolved:
|
||||
if not declarabile:
|
||||
continue
|
||||
mapped["prestatii"] = resolved
|
||||
|
||||
# Canonicalizare (dupa rezolvare prestatii -> cod_prestatie inclus in cheie;
|
||||
# cheia IDENTICA cu preview: _build_idempotency_key = canonicalize_row + build_key).
|
||||
canon = canonicalize_row(mapped)
|
||||
canon = canonicalize_row({**mapped, "prestatii": declarabile})
|
||||
mapped.update({
|
||||
"vin": canon["vin"],
|
||||
"nr_inmatriculare": canon["nr_inmatriculare"],
|
||||
@@ -1223,13 +1235,13 @@ def commit_import(
|
||||
# Cheia de idempotenta (identica cu cheia din preview — aceeasi ordine + env)
|
||||
key = build_key(account_id, canon, env)
|
||||
|
||||
# Hash row pentru atestare (valori rezolvate)
|
||||
# Hash row pentru atestare (valori rezolvate, doar partea declarabila)
|
||||
rows_for_hash.append(json.dumps({
|
||||
"row_index": row_index,
|
||||
"vin": mapped.get("vin"),
|
||||
"data_prestatie": mapped.get("data_prestatie"),
|
||||
"odometru_final": mapped.get("odometru_final"),
|
||||
"prestatii": [str(p.get("cod_prestatie") or p.get("cod_op_service") or "") for p in resolved],
|
||||
"prestatii": [str(p.get("cod_prestatie") or p.get("cod_op_service") or "") for p in declarabile],
|
||||
}, sort_keys=True, ensure_ascii=False))
|
||||
|
||||
payload_json = json.dumps(mapped, ensure_ascii=False)
|
||||
|
||||
Reference in New Issue
Block a user