feat(api): validare cod_prestatie la nomenclator + optiune on_unmapped_error

Cod_prestatie necunoscut in nomenclator nu se mai trimite raw la RAR (HTTP 500
ORA-12899 + record partial FINALIZATA pe care reconcilierea il marca fals sent):
e promovat la cod_op_service si tratat ca operatie de mapat.

Optiune top-level boolean on_unmapped_error pe POST /v1/prezentari + /valideaza:
  - false (default) -> submission needs_mapping (intra in editor)
  - true            -> respinge fara enqueue (status error, submission_id=null, erori)
  - None            -> default per-cont accounts.on_unmapped_error_default (implicit 0)
Inlocuieste enum-ul anterior on_unmapped (needs_mapping/error) cu un boolean mai
simplu; coloana de cont migrata aditiv la INTEGER on_unmapped_error_default.

Izolare teste de .env-ul de dezvoltare: tests/conftest.py fixeaza default sigur
pe AUTOPASS_REQUIRE_API_KEY / AUTOPASS_WORKER_USE_TEST_CREDS (precedenta peste
.env in pydantic-settings) + fixturile env din test_creds_delivery/test_t1 pineaza
explicit aceste flag-uri, ca fallback-ul creds pe cont sa fie atins.

Teste: 752 passed (fara flag pe CLI).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-06-23 19:35:47 +00:00
parent c842e3352a
commit 6bad6bc01e
17 changed files with 376 additions and 23 deletions

View File

@@ -138,6 +138,51 @@ def test_raspuns_pierdut_reconciliere_fara_duplicat(env):
assert rar.finalizate_calls == 1 # a reconciliat
def test_rar_500_definitiv_devine_error_fara_reconciliere(env):
"""RAR 500 cu mesaj (ex. ORA-12899) = esec DEFINITIV: NU reconcilia, NU reincerca.
Bug-ul real: 500 era tratat ca tranzitoriu -> reconciliere -> marca fals 'sent'
pe un record PARTIAL creat de RAR (ne-tranzactional). Aici, chiar daca exista un
record care s-ar potrivi, NU trebuie marcat sent.
"""
from app.worker.__main__ import process_one
conn, settings = env
sid = _insert(conn)
rar = FakeRar(
finalizate=[{"id": 99999, "vin": "WVWZZZ1KZAW000123",
"dataPrestatie": "2026-06-15", "odometruFinal": 123456}],
post_exc=RarError(
"postPrezentare esuat (HTTP 500)", status_code=500,
rar_message="Eroare la adaugarea prezentarii : ORA-12899: value too large for column COD_PRESTATIE",
),
)
out = process_one(conn, settings, rar, "tok", {"id": sid, "content": _CONTENT})
assert out == "error"
row = _status(conn, sid)
assert row["status"] == "error"
assert row["id_prezentare"] is None # NU fals sent
assert rar.post_calls == 1 # nu re-trimite
assert rar.finalizate_calls == 0 # NU reconciliaza
err = json.loads(row["rar_error"])
assert err["cod"] == "RAR_EROARE_SERVER" and "ORA-12899" in err["cauza"]
def test_rar_503_ramane_tranzitoriu(env):
"""Boundary: doar 500-cu-mesaj e permanent; 503 (infra) ramane ambiguu -> reconciliere."""
from app.worker.__main__ import process_one
conn, settings = env
sid = _insert(conn)
rar = FakeRar(
finalizate=[{"id": 68514, "vin": "WVWZZZ1KZAW000123",
"dataPrestatie": "2026-06-15", "odometruFinal": 123456}],
post_exc=RarError("service unavailable", status_code=503, rar_message="temporar indisponibil"),
)
out = process_one(conn, settings, rar, "tok", {"id": sid, "content": _CONTENT})
assert out == "sent"
assert _status(conn, sid)["id_prezentare"] == 68514
assert rar.finalizate_calls == 1
def test_tranzitoriu_neinregistrat_requeue(env):
from app.worker.__main__ import process_one
conn, settings = env