feat(5.8): reguli mapare pe text (substring/cont) + UX tabel trimiteri (detaliu inline, fara scroll, cod RAR)

Reguli text per cont (operation_text_rules), resolve_prestatii cu param aditiv
text_rules + precedenta stricta, threadat pe toate cele 6 callsite-uri + valid_codes
+ seam classify_prezentare. UI Mapari: sectiune reguli + preview pre-salvare + overlap
+ telemetrie text_rule_hit. UX tabel: cod_rar sub operatie, pill eticheta scurta, fara
scroll orizontal (scopat .tabel-trimiteri + carduri <768px), detaliu inline expandabil
(a11y + pauza poll). code-review: reparat regula auto_send=0 care trimitea automat la RAR
in loc sa tina randul pentru review. 814 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-06-24 12:47:37 +00:00
parent c80c79462c
commit 51dc504f1d
28 changed files with 3023 additions and 61 deletions

View File

@@ -44,9 +44,12 @@ from ...import_parse import (
parse_file,
)
from ...mapping import (
_emite_text_rule_hits,
account_or_default,
has_no_auto_send,
load_mapping_meta,
load_nomenclator_codes,
load_text_rules,
normalize_for_match,
resolve_prestatii,
)
@@ -126,6 +129,8 @@ def _resolve_row_for_preview(
mapping_meta: dict[str, dict],
formula_columns: list[str],
override: dict[str, Any] | None = None,
valid_codes: set[str] | None = None,
text_rules: list[dict] | None = None,
) -> dict[str, Any]:
"""Rezolva un rand din import pentru preview: aplica mapare coloane + validare.
@@ -201,7 +206,7 @@ def _resolve_row_for_preview(
# Rezolvare prestatii
prestatii = mapped.get("prestatii") or []
resolved, unmapped = resolve_prestatii(prestatii, mapping)
resolved, unmapped = resolve_prestatii(prestatii, mapping, valid_codes, text_rules)
mapped["prestatii"] = resolved
# Determinare stare
@@ -745,6 +750,9 @@ def preview_import(
# Incarca maparea de operatii o singura data (Eng#5: load_mapping o singura data)
mapping_meta = load_mapping_meta(conn, acct)
mapping = {op: meta["cod_prestatie"] for op, meta in mapping_meta.items()}
# T2: validare nomenclator + reguli text incarcate O DATA, inainte de bucla pe randuri.
valid_codes = load_nomenclator_codes(conn) or None
text_rules = load_text_rules(conn, acct)
# Reconstruieste parsed info (coercion_flags si date_col_format) din datele stocate
# Nota: import_rows stocheaza raw_json dupa coercion (din parse_file)
@@ -797,6 +805,8 @@ def preview_import(
mapping_meta=mapping_meta,
formula_columns=formula_columns,
override=overrides[i] or None,
valid_codes=valid_codes,
text_rules=text_rules,
)
# Calculeaza cheia de idempotenta pentru randurile ok/needs_review
@@ -1030,6 +1040,9 @@ def commit_import(
# Incarca maparea de operatii
mapping_meta = load_mapping_meta(conn, acct)
mapping = {op: meta["cod_prestatie"] for op, meta in mapping_meta.items()}
# T2: validare nomenclator + reguli text incarcate O DATA, inainte de bucla pe randuri.
valid_codes = load_nomenclator_codes(conn) or None
text_rules = load_text_rules(conn, acct)
# Construieste payload-urile submissions
enqueued: list[dict] = []
@@ -1076,7 +1089,7 @@ 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)
resolved, _ = resolve_prestatii(prestatii, mapping, valid_codes, text_rules)
mapped["prestatii"] = resolved
# Canonicalizare (dupa rezolvare prestatii -> cod_prestatie inclus in cheie)
@@ -1127,6 +1140,8 @@ def commit_import(
toctou_collisions.append(row_index)
else:
sub_id = cur.lastrowid
# US-010: telemetrie pentru itemii rezolvati prin regula text.
_emite_text_rule_hits(conn, acct, int(sub_id), resolved)
enqueued.append({
"submission_id": sub_id,
"row_index": row_index,