Doua fisiere, unul per canal: prezentari_test.csv (import web) si prezentari_test.json (API). Fiecare contine randuri valide + randuri care declanseaza erorile de validare (VIN/nr/data/odometru, prestatii goale), plus README cu cele 3 niveluri de eroare (shape 422, needs_mapping, needs_data) si comenzi curl. Operatiile folosesc coduri/denumiri proprii de service, nu coduri RAR. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6.5 KiB
Exemple payload pentru testare
Doua fisiere, cate unul pentru fiecare canal de intrare (vezi CLAUDE.md -> Arhitectura).
Fiecare contine randuri valide + randuri de eroare in acelasi fisier:
| Fisier | Canal | Continut |
|---|---|---|
prezentari_test.csv |
Import web (Treapta 2) | 5 randuri valide + 10 randuri de eroare |
prezentari_test.json |
API (POST /v1/prezentari) |
4 prezentari valide + 9 cu erori de continut |
Sunt doua fisiere si nu unul singur fiindca CSV (import) si JSON (API) sunt canale diferite, cu formate diferite — nu pot fi acelasi fisier.
Operatiile sunt denumiri/coduri proprii de service, NU coduri RAR (OE-1, R-ODO etc.).
Asta reflecta realitatea: utilizatorul nu cunoaste si nu trimite codurile RAR — gateway-ul
le traduce prin maparile contului (operations_mapping / reguli text), iar ce nu se rezolva
intra in editorul web (needs_mapping) cu sugestii fuzzy pe nomenclator.
Maparea coloanelor la import
La upload, importul sugereaza maparea coloanelor (fuzzy). Antetele din prezentari_test.csv
se auto-sugereaza corect:
| Coloana fisier | Camp canonic |
|---|---|
VIN |
vin |
Numar inmatriculare |
nr_inmatriculare |
Data prestatie |
data_prestatie |
Odometru initial / Odometru final |
odometru_initial / odometru_final |
Operatie |
operatie (-> cod_op_service) |
Observatii |
obs |
Important — ce operatie se trimite:
- Operatia (ce s-a lucrat) trebuie sa fie pe coloana mapata la campul
Operatie. - Campul
Denumire operatieNU este o operatie de sine statatoare. Singur, nu produce nimic — doar adauga o descriere unei operatii care exista deja peOperatie. - Regula simpla: fara
Operatienu exista prestatie (randul pica pePRESTATII_GOALE).
In prezentari_test.csv, coloana cu operatia se cheama Operatie si contine text liber
(ex. „Reparatie motor"): cod_op_service devine textul integral, iar denumire = acelasi
text, deci sugestia fuzzy din editor are pe ce lucra. Daca softul tau trimite un cod intern
scurt (ex. REP-MOT), il pui tot pe coloana Operatie — se comporta identic.
Reguli de validare (din docs/api-rar-contract.md)
- VIN: exact 17 caractere, MAJUSCULE, fara spatii/caractere speciale, fara literele O, I, Q.
- nr_inmatriculare: max 10 caractere, litere + cifre, fara spatii.
- data_prestatie: format
AAAA-LL-ZZ, intre2024-12-01si azi. - odometru_initial: obligatoriu doar cand operatia se mapeaza la
R-ODO/I-ODO, si trebuie sa fie <= odometru_final.
Cele trei niveluri de eroare (ordinea verificarii)
- Shape (422) — JSON malformat / item de prestatie fara nici un cod. Pydantic respinge
intreaga cerere inainte de orice procesare. Nu se aplica la CSV (la import, un rand
fara operatie devine pur si simplu
PRESTATII_GOALE, nu 422). Vezi sect. „Eroare de shape". - Mapare (
needs_mapping) — operatia nu are cod RAR mapat. Randul NU se trimite; apare in editor. Aici ajung implicit toate randurile din exemple (utilizatorul nu da coduri RAR). - Continut (
needs_data) — VIN/data/odometru invalide. Validarea de continut ruleaza DOAR dupa ce operatia e mapata (nivelul 2 trece). Deci randurile de eroare apar intai caneeds_mapping; abia dupa ce mapezi operatia (ex. „Reparatie motor" ->OE-1) eroarea de continut iese la suprafata caneeds_data.
Exceptie utila: un rand fara nicio operatie (ultimul rand din CSV) nu are ce mapa, deci pica direct pe
PRESTATII_GOALE(needs_data), vizibil imediat la preview.
Erori de continut acoperite (randurile EROARE ...)
| Cod eroare | Cum e declansat in exemple |
|---|---|
VIN_FORMAT |
VIN cu litera Q (...00Q123) si VIN de 16 caractere |
NR_INMATRICULARE_FORMAT |
nr de 13 caractere (BUCURESTI2026) |
DATA_FORMAT |
data 2026-13-05 (luna inexistenta) |
DATA_PREA_VECHE |
data 2024-06-01 (inainte de 01.12.2024) |
DATA_VIITOR |
data 2027-01-01 |
ODOMETRU_FINAL_FORMAT |
odometru final o-suta-mii (nu e numar) |
ODOMETRU_INITIAL_LIPSA |
operatie R-ODO fara odometru initial |
ODOMETRU_INITIAL_ORDINE |
odometru initial 400000 > final 300000 |
PRESTATII_GOALE |
rand fara operatie deloc (doar in CSV) |
Forma erorii returnate are 6 chei (field, message, cod, problema, cauza, fix) — vezi
docs/api-rar-contract.md sect. „Envelope de eroare imbogatit".
Fluxul complet (de la upload la trimitere)
- La upload / POST: niciun cod nu e mapat inca -> toate randurile devin
needs_mapping. - In editorul de mapari (tab Mapari /
GET /v1/mapari/pending): fiecare operatie distincta apare cu sugestii fuzzy pe nomenclator. Alegi codul RAR si salvezi. - Re-rezolvare automata: la salvarea maparii, submission-urile blocate se re-rezolva ->
queued(sauneeds_datadaca validarea de continut mai cere ceva, ex. odometru initial laR-ODO). - Worker: trimite cele
queuedla RAR (doar cand send-ul e activat).
Comenzi de test
Din radacina proiectului, cu API-ul pornit (./start.sh test both sau
uvicorn app.main:app --reload --port 8010):
# CSV — import web (valid + erori)
curl -F "file=@exemple/prezentari_test.csv" http://localhost:8010/v1/import
# JSON — API (valid + erori de continut)
curl -X POST http://localhost:8010/v1/prezentari \
-H "Content-Type: application/json" \
--data @exemple/prezentari_test.json
# Dry-run (nu enqueue, doar verdictul): acelasi body pe /valideaza
curl -X POST http://localhost:8010/v1/prezentari/valideaza \
-H "Content-Type: application/json" \
--data @exemple/prezentari_test.json
Eroare de shape (422) — exemplu inline
Cazul 422 nu poate sta in prezentari_test.json (un singur item fara cod respinge toata
cererea). Il declansezi cu un body minimal — prestatie fara cod_prestatie si fara
cod_op_service (asteapta HTTP 422):
curl -i -X POST http://localhost:8010/v1/prezentari \
-H "Content-Type: application/json" \
-d '{"prezentari":[{"vin":"WVWZZZ1KZAW000123","nr_inmatriculare":"B123ABC","data_prestatie":"2026-06-20","odometru_final":"145000","prestatii":[{"denumire":"fara niciun cod"}]}]}'
Optiuni pe JSON (POST /v1/prezentari)
rar_credentials: {email, password}— creds RAR efemere (top-level, nu se persista).on_unmapped_error: true— respinge codurile necunoscute/nemapate fara enqueue (submission_id=null,erori=[COD_NEMAPAT]) in loc deneeds_mapping.odometru_finaleste string (per contract);odometru_initialdoar laR-ODO/I-ODO.