feat(web): paritate editor mapare import-preview cu pagina /mapari

Panoul inline "Operatii de mapat la cod RAR" din preview-ul de import folosea
doar sugestii fuzzy si nu arata sursa sugestiei. Acum are paritate 1:1 cu pagina
/mapari: aceeasi sugestie_principala (GOLD partajat > SILVER > embeddings k-NN)
si acelasi badge sursa (confirmat / similar / non-operatie).

- _collect_unmapped_ops primeste `conn`: ataseaza sugestie_principala +
  surse_sugestie via enrich_suggestions, cu ensure_embeddings_corpus o data
  inainte de bucla (replica pattern-ul din pending_unmapped). Init default pe
  fiecare entry (inclusiv conn=None) -> contract template identic.
  SUGGESTION-ONLY: nu atinge resolve_prestatii/load_mapping (#13).
- _web_compute_preview paseaza conn=conn la _collect_unmapped_ops.
- _preview_import.html: preselect din sugestie_principala > fuzzy>=60 + badge
  sursa (clase .sugg-sursa--{confirmat,similar,nul} deja existente in base.html).
- Test de paritate TARE: seed embeddings + GOLD/SILVER/NUL, batch import cu
  needs_mapping, verifica _web_compute_preview()["unmapped_ops"] ==
  pending_unmapped(conn, account) pe sugestie_principala + surse_sugestie, cate
  un caz per sursa (gold/silver/embedding/nul).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-07-03 13:23:28 +00:00
parent d3ebf4762d
commit e11a5efa0f
3 changed files with 261 additions and 6 deletions

View File

@@ -2694,12 +2694,21 @@ def post_sterge_format_coloane(
# Toate rutele /_import/* returneaza fragmente HTML (target #import-section). #
# =========================================================================== #
def _collect_unmapped_ops(preview_rows: list[dict], nomenclator: list[dict]) -> list[dict]:
"""Operatii distincte nemapate dintr-un preview de import (staging), cu sugestii fuzzy.
def _collect_unmapped_ops(preview_rows: list[dict], nomenclator: list[dict], conn=None) -> list[dict]:
"""Operatii distincte nemapate dintr-un preview de import (staging), cu sugestii fuzzy + enriched.
Echivalentul lui pending_unmapped() dar pe randuri de PREVIEW (import in staging,
Echivalentul lui `pending_unmapped()` dar pe randuri de PREVIEW (import in staging,
inca neexistente ca submissions). Aduna doar prestatiile fara cod_prestatie
(cele cu auto_send=0 au deja cod -> nu apar aici). Sortare: cele mai blocate intai.
L14-S6 / paritate editor: cand `conn` e dat, ataseaza `sugestie_principala`
(GOLD partajat > SILVER > embeddings k-NN) si `surse_sugestie` din `enrich_suggestions`,
exact ca `pending_unmapped` — asa panoul inline al preview-ului are aceeasi sugestie
principala + badge sursa ca pagina /mapari. SUGGESTION-ONLY: nu atinge
`resolve_prestatii`/`load_mapping` (#13). Degradare gratioasa pe embeddings (#16b).
`sugestie_principala`/`surse_sugestie` se initializeaza pe FIECARE entry (chiar cand
conn=None) ca contractul catre template sa fie identic indiferent de call-site.
"""
agg: dict[str, dict[str, Any]] = {}
for row in preview_rows:
@@ -2715,9 +2724,22 @@ def _collect_unmapped_ops(preview_rows: list[dict], nomenclator: list[dict]) ->
if not entry["denumire"] and item.get("denumire"):
entry["denumire"] = item.get("denumire")
entry["blocked"] += 1
# Indexeaza corpusul embeddings o data inainte de bucla (no-op cand flagul e off).
if conn is not None:
ensure_embeddings_corpus(conn, nomenclator)
out: list[dict] = []
for entry in agg.values():
entry["suggestions"] = suggest_codes(entry["denumire"], nomenclator, limit=5)
# Init default pe FIECARE entry -> contract template identic (conn=None inclus).
entry["sugestie_principala"] = None
entry["surse_sugestie"] = {"gold_partajat": None, "silver": None, "embedding": None, "nul": False}
# L14-S6: imbogatire cu GOLD partajat > SILVER > embeddings (SUGGESTION-ONLY, #13)
if conn is not None:
enriched = enrich_suggestions(conn, entry["denumire"])
entry["sugestie_principala"] = enriched["sugestie_principala"]
entry["surse_sugestie"] = enriched["surse"]
out.append(entry)
out.sort(key=lambda e: (-e["blocked"], e["cod_op_service"]))
return out
@@ -2940,7 +2962,7 @@ def _web_compute_preview(
"summary": summary,
"total": len(preview_rows),
"filename": batch["filename"],
"unmapped_ops": _collect_unmapped_ops(preview_rows, nomenclator),
"unmapped_ops": _collect_unmapped_ops(preview_rows, nomenclator, conn=conn),
"nomenclator": nomenclator,
}