"""Teste mapare op ROAAUTO -> cod RAR: fuzzy, rezolvare pura, flux on-demand. Contract hibrid (decis 2026-06-15): item de prestatie cu cod_prestatie (RAR direct) SAU cod_op_service+denumire (mapat de gateway). Op nemapata -> needs_mapping, apare in editor; la salvarea maparii submission-ul se re-rezolva automat. """ from __future__ import annotations import os import tempfile import pytest from fastapi.testclient import TestClient from app.mapping import normalize_for_match, resolve_prestatii, suggest_codes # --------------------------------------------------------------------------- # # Pur # # --------------------------------------------------------------------------- # def test_normalize_scoate_diacritice_si_colapseaza(): assert normalize_for_match("Reparație motor") == "REPARATIE MOTOR" assert normalize_for_match(" întreținere ") == "INTRETINERE" assert normalize_for_match(None) == "" _NOM = [ {"cod_prestatie": "OE-1", "nume_prestatie": "REPARATIE"}, {"cod_prestatie": "OE-2", "nume_prestatie": "INTRETINERE"}, {"cod_prestatie": "OE-3", "nume_prestatie": "REVIZIE PERIODICA"}, {"cod_prestatie": "R-ODO", "nume_prestatie": "REPARATIE ODOMETRU"}, ] def test_suggest_pune_potrivirea_evidenta_prima(): s = suggest_codes("Reparatie odometru electronic", _NOM, limit=4) assert s[0]["cod_prestatie"] == "R-ODO" assert s[0]["score"] >= 60 def test_suggest_denumire_goala_intoarce_nomenclator_scor_zero(): s = suggest_codes("", _NOM, limit=2) assert len(s) == 2 assert all(x["score"] == 0 for x in s) def test_resolve_cod_direct_trece_neatins(): resolved, unmapped = resolve_prestatii([{"cod_prestatie": "oe-1"}], {}) assert resolved[0]["cod_prestatie"] == "OE-1" # normalizat upper assert unmapped == [] def test_resolve_op_mapata(): resolved, unmapped = resolve_prestatii( [{"cod_op_service": "1234", "denumire": "Schimb ulei"}], {"1234": "OE-2"} ) assert resolved[0]["cod_prestatie"] == "OE-2" assert unmapped == [] def test_resolve_op_nemapata_iese_in_unmapped(): resolved, unmapped = resolve_prestatii( [{"cod_op_service": "9999", "denumire": "Operatie noua"}], {} ) assert resolved[0]["cod_prestatie"] is None assert unmapped == [{"cod_op_service": "9999", "denumire": "Operatie noua"}] # --------------------------------------------------------------------------- # # Flux complet (API) # # --------------------------------------------------------------------------- # @pytest.fixture() def client(monkeypatch): tmp = tempfile.mkdtemp() monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "t.db")) from app.config import get_settings get_settings.cache_clear() from app.main import app with TestClient(app) as c: yield c get_settings.cache_clear() def _body(prestatii, **over): prez = { "vin": "WVWZZZ1KZAW000123", "nr_inmatriculare": "B999TST", "data_prestatie": "2026-06-15", "odometru_final": "123456", "prestatii": prestatii, } prez.update(over) return {"rar_credentials": {"email": "x@y.ro", "password": "s"}, "prezentari": [prez]} def test_nomenclator_seed_la_boot(client): r = client.get("/v1/nomenclator") coduri = {n["cod_prestatie"] for n in r.json()["nomenclator"]} assert {"OE-1", "R-ODO", "I-ODO"} <= coduri def test_cod_op_nemapat_da_needs_mapping(client): r = client.post("/v1/prezentari", json=_body([{"cod_op_service": "OP100", "denumire": "Reparatie generala"}])) assert r.status_code == 200 assert r.json()["results"][0]["status"] == "needs_mapping" def test_pending_arata_op_cu_sugestii(client): client.post("/v1/prezentari", json=_body([{"cod_op_service": "OP100", "denumire": "Reparatie generala"}])) pend = client.get("/v1/mapari/pending").json()["pending"] assert len(pend) == 1 e = pend[0] assert e["cod_op_service"] == "OP100" assert e["blocked"] == 1 assert e["suggestions"] and e["suggestions"][0]["cod_prestatie"] def test_salvare_mapare_deblocheaza_submission(client): client.post("/v1/prezentari", json=_body([{"cod_op_service": "OP100", "denumire": "Reparatie"}])) r = client.post("/v1/mapari", json={"cod_op_service": "OP100", "cod_prestatie": "OE-1", "auto_send": True}) assert r.status_code == 200 assert r.json()["reresolve"]["requeued"] == 1 # submission-ul e acum queued subs = client.get("/v1/prezentari", params={"status": "queued"}).json()["submissions"] assert len(subs) == 1 # nu mai e nimic in pending assert client.get("/v1/mapari/pending").json()["pending"] == [] def test_mapare_cod_inexistent_respinsa(client): client.post("/v1/prezentari", json=_body([{"cod_op_service": "OP100", "denumire": "x"}])) r = client.post("/v1/mapari", json={"cod_op_service": "OP100", "cod_prestatie": "ZZZ", "auto_send": True}) assert r.status_code == 422 def test_mapare_apoi_re_ingestie_e_directa(client): """Dupa ce maparea exista, o noua comanda cu acelasi op intra direct queued.""" client.post("/v1/prezentari", json=_body([{"cod_op_service": "OP100", "denumire": "x"}])) client.post("/v1/mapari", json={"cod_op_service": "OP100", "cod_prestatie": "OE-1", "auto_send": True}) r = client.post("/v1/prezentari", json=_body([{"cod_op_service": "OP100", "denumire": "x"}], vin="WVWZZZ1KZAW000999")) assert r.json()["results"][0]["status"] == "queued" def test_cod_prestatie_direct_inca_merge(client): """Back-compat: trimiterea codului RAR direct se comporta ca inainte (queued).""" r = client.post("/v1/prezentari", json=_body([{"cod_prestatie": "OE-1"}])) assert r.json()["results"][0]["status"] == "queued" def test_op_mapat_declanseaza_regula_odometru(client): """Dupa mapare la R-ODO, validarea cere odometruInitial -> needs_data (nu queued).""" client.post("/v1/prezentari", json=_body([{"cod_op_service": "OPODO", "denumire": "Reparatie odometru"}])) r = client.post("/v1/mapari", json={"cod_op_service": "OPODO", "cod_prestatie": "R-ODO", "auto_send": True}) stats = r.json()["reresolve"] assert stats["needs_data"] == 1 and stats["requeued"] == 0 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