feat(errors): erori pe 3 niveluri (problema+cauza+fix) pe API si UI (PRD 5.4)

Catalog central pur app/errors.py ca sursa unica cod->{problema,fix},
consumat de API+UI+worker. Aditiv (field/message pastrate la octet) +
rar_error stocat superset. Scope: fluxul de declarare; login/signup/CSRF
neatinse. labels.parse_erori degradeaza gratios; UI progresiv AA light+dark.
631 teste.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-06-23 10:28:09 +00:00
parent b48501d8e4
commit 14e1c463f0
25 changed files with 2440 additions and 44 deletions

View File

@@ -161,3 +161,89 @@ def test_op_mapat_declanseaza_regula_odometru(client):
def test_item_fara_cod_si_fara_op_e_422(client):
r = client.post("/v1/prezentari", json=_body([{"denumire": "doar text"}]))
assert r.status_code == 422
# --------------------------------------------------------------------------- #
# US-003: 3 niveluri in classify_prezentare (needs_mapping) #
# --------------------------------------------------------------------------- #
def test_unmapped_are_3niveluri(client):
"""cod_op_service necunoscut -> needs_mapping; rar_error are cheie 'unmapped'
PASTRATA + campurile COD_NEMAPAT (cod/problema/cauza/fix)."""
import json
from app.mapping import classify_prezentare
content = {
"vin": "WVWZZZ1KZAW000123",
"nr_inmatriculare": "B999TST",
"data_prestatie": "2026-06-15",
"odometru_final": "123456",
"prestatii": [{"cod_op_service": "OP_NECUNOSCUT", "denumire": "Reparatie necunoscuta"}],
}
mapping = {}
mapping_meta = {}
res = classify_prezentare(content, mapping, mapping_meta)
assert res["status"] == "needs_mapping"
err = json.loads(res["rar_error"])
# Cheia originala pastrata
assert "unmapped" in err
assert len(err["unmapped"]) == 1
assert err["unmapped"][0]["cod_op_service"] == "OP_NECUNOSCUT"
# 3 niveluri prezente
assert err["cod"] == "COD_NEMAPAT"
assert err["problema"]
assert err["cauza"]
assert err["fix"]
def test_auto_send_oprit_3niveluri(client):
"""Mapare cu auto_send=0 -> needs_mapping; rar_error are cheie 'auto_send'
PASTRATA + campurile AUTO_SEND_OPRIT (cod/problema/cauza/fix)."""
import json
from app.mapping import classify_prezentare
content = {
"vin": "WVWZZZ1KZAW000123",
"nr_inmatriculare": "B999TST",
"data_prestatie": "2026-06-15",
"odometru_final": "123456",
"prestatii": [{"cod_op_service": "OP_REVIEW", "denumire": "Operatie cu review"}],
}
mapping = {"OP_REVIEW": "OE-1"}
mapping_meta = {"OP_REVIEW": {"cod_prestatie": "OE-1", "auto_send": False}}
res = classify_prezentare(content, mapping, mapping_meta)
assert res["status"] == "needs_mapping"
err = json.loads(res["rar_error"])
# Cheia originala pastrata
assert "auto_send" in err
# 3 niveluri prezente
assert err["cod"] == "AUTO_SEND_OPRIT"
assert err["problema"]
assert err["cauza"]
assert err["fix"]
def test_needs_data_pass_through(client):
"""VIN invalid -> needs_data; rar_error = array cu erori care au cod/problema/fix (US-002)."""
import json
from app.mapping import classify_prezentare
content = {
"vin": "VIN_INVALID_XXXXXXXXX", # nu trece regex
"nr_inmatriculare": "B999TST",
"data_prestatie": "2026-06-15",
"odometru_final": "123456",
"prestatii": [{"cod_prestatie": "OE-1"}],
}
mapping = {}
mapping_meta = {}
res = classify_prezentare(content, mapping, mapping_meta)
assert res["status"] == "needs_data"
erori = json.loads(res["rar_error"])
assert isinstance(erori, list)
assert len(erori) >= 1
# Fiecare eroare are cele 3 niveluri (pass-through US-002)
for e in erori:
assert "cod" in e, f"lipseste 'cod' in {e}"
assert "problema" in e, f"lipseste 'problema' in {e}"
assert "fix" in e, f"lipseste 'fix' in {e}"