Raportat din client VFP: POST /v1/prezentari raspundea submission_id+status
fara motiv pe randuri blocate (erori se popula doar pe on_unmapped_error=True),
deci un needs_data/needs_mapping parea succes.
API (aditiv): SubmissionResult += nemapate + motiv. create_prezentari
populeaza erori (validare continut, 3 niveluri) / nemapate (coduri fara
mapare, COD_NEMAPAT) / motiv (rezumat uman) pe TOATE caile non-queued —
enqueue, respins (on_unmapped_error=True) si reactivare dedup peste error,
prin helperele _rezultat_enqueue / _rezultat_respins / _motiv_clasificare.
on_unmapped_error=True pastreaza erori=COD_NEMAPAT (compat clienti vechi).
Web: mapare inline in panoul de detaliu trimitere — ruta
POST /trimitere/{id}/mapeaza (reuse save_mapping + reresolve_account, scoped
sesiune + CSRF, re-rezolva pe batch_id-ul randului), helper
_nemapate_pentru_submission + context in _detaliu_ctx, sectiune in
_trimitere_detaliu.html (selector cod RAR cu sugestie fuzzy preselectata).
Apare doar pe operatii nemapate reale (nu pe auto_send=0).
/code-review high: reparat raspuns neonest la reactivare + dublu
load_nomenclator in _detaliu_ctx.
Teste: pytest -q 765 passed. Backend trimitere (worker/masina stari/
idempotenta) si schema NEATINSE. PRD: docs/prd/prd-5.7-*.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
10 KiB
PRD 5.7 — Raspuns API onest la blocaje + mapare inline din detaliu
Stare: inchis
Proces complet:
docs/ROADMAP.md§5. Contract RAR (sursa de adevar):docs/api-rar-contract.md. Starea trece:draft → aprobat → in-executie → verify-pass → inchis(actualizata de lead).
1. Obiectiv
Doua goluri raportate din clientul Visual FoxPro (2026-06-23):
-
Raspunsul
POST /v1/prezentariminte prin omisiune. Cand o prezentare e blocata (needs_data— date respinse de RAR;needs_mapping— cod fara mapare), API-ul intoarce{submission_id, status}fara detalii: campuleroriramane gol (se populeaza azi DOAR pe ramuraon_unmapped_error=True). Un integrator care verifica "amsubmission_idsierorie gol → e ok" trateaza un rand blocat ca succes. Screenshot live: randneeds_data(data in viitor) pe care clientul l-a primit "fara erori". Reparam: raspunsul devine onest — pentru orice status !=queuedexpuneerori(validare continut),nemapate(coduri fara mapare) si unmotivuman pe o linie. Strict aditiv (campuri noi + populare a unui camp existent) — clientii vechi nu se rup. -
Maparea unui cod nemapat cere drum prin tab-ul Mapari. Din panoul de detaliu al unei trimiteri
needs_mapping, userul vede "Lipseste codul prestatiei" dar trebuie sa navigheze in alt tab ca sa o mapeze. Adaugam mapare inline: chiar in panoul de detaliu, fiecare operatie nemapata primeste un selector de cod RAR (cu sugestii fuzzy preselectate) si un buton care salveaza maparea + re-rezolva submission-ul pe loc.
Etapa 5 (ergonomie & integrare). Niciun apel live la RAR.
2. Non-Goals (anti scope-creep)
- NU schimba masina de stari, worker-ul, idempotency-ul, schema. Zero coloane noi.
classify_prezentareramane sursa unica de clasificare (invariantul dry-run din 5.2 se pastreaza). - NU schimba comportamentul
on_unmapped_error(ramuraerror/respins):eroricuCOD_NEMAPATramane exact ca azi (lock-uit detest_on_unmapped_error_respinge_fara_enqueue). Doar adaugamnemapate+motivsi pe acea ramura. - NU imbogateste raspunsul
dedupedcu erori/motiv: un dedup intoarce starea curenta a randului existent fara re-clasificare (clientul poate cereGET /v1/prezentari/{id}pentru detaliu). Pastram semantica actuala a caii de dedup. - NU atinge
/valideaza(dry-run-ul are dejaerori+nemapate; ramane referinta de forma). - NU schimba editorul din tab-ul Mapari — maparea inline il completeaza, nu il inlocuieste;
reutilizeaza
save_mapping+reresolve_account(aceeasi logica, fara ramura noua). - NU mapare inline pe
needs_data— acolo exista deja corectia de campuri (US-010, 3.5). Inline-ul de mapare apare DOAR peneeds_mappingcu operatii nemapate reale.
3. Stories atomice
US-001: Raspuns POST /v1/prezentari onest pentru randuri blocate
Ca integrator (ROAAUTO / soft propriu / punte VFP) vreau ca raspunsul la enqueue sa-mi spuna
de ce un rand e blocat (nu doar status), pentru ca sa nu tratez un needs_data/needs_mapping
drept succes si sa pot reactiona programatic.
- Depinde de: —
- Fisiere:
app/models.py(SubmissionResult+=nemapate,motiv),app/api/v1/router.py(create_prezentaripopuleaza dincl),tests/test_api.py+tests/test_mapping.py(~4 fisiere) - Test intai (RED):
tests/test_api.py—test_needs_data_intoarce_erori(data in viitor →status="needs_data",erorinegol cucod="DATA_VIITOR"pefield="data_prestatie",motivnegol)test_vin_invalid_intoarce_erori_pe_camp(VIN cu O/I/Q →eroricufield="vin")test_needs_mapping_intoarce_nemapate(cod necunoscut →status="needs_mapping",nemapatenegol cucod_op_service,erori=[],motivnegol)test_queued_fara_erori_nemapate(valid →erori=[],nemapate=[],motivnull)tests/test_mapping.py::test_on_unmapped_error_pastreaza_erori(regresie:on_unmapped_error=Trueinca daerori[0].cod=="COD_NEMAPAT"; + acumnemapatenegol)
- Acceptance criteria:
SubmissionResultare campurile noinemapate: list[dict] = []simotiv: str | None = None(aditiv;eroriramane).- Pe enqueue cu
status="needs_data":erori= exactvalidate_prezentare(3 niveluri),nemapate=[],motiv= rezumat uman pe o linie. - Pe enqueue cu
status="needs_mapping"din coduri nemapate:nemapate=[{cod_op_service, denumire, cod, problema, cauza, fix, message}],erori=[],motivnegol. - Pe enqueue cu
status="needs_mapping"dinauto_send=0:motivexplica "confirmare manuala" (chiar dacaerori/nemapatesunt goale). - Pe
status="queued":erori=[],nemapate=[],motiv=None. - Ramura
on_unmapped_error=True(status="error",submission_id=None):erorineschimbat (COD_NEMAPAT),nemapatenegol,motivnegol. - Raspunsul nu contine niciodata echo de creds (
password) — validat pe corpul serializat.
- Verificare E2E:
POST /v1/prezentaridin client (sau curl) cu data in viitor → JSON cuerorivizibile; cu cod intern →nemapate.
US-002: Backend mapare inline din panoul de detaliu (ruta + context)
Ca operator in dashboard vreau sa mapez codul unei operatii direct din detaliul trimiterii pentru ca sa deblochez randul fara sa schimb tab-ul.
- Depinde de: —
- Fisiere:
app/web/routes.py(helper_nemapate_pentru_submission, context in_detaliu_ctx, rutaPOST /trimitere/{id}/mapeaza),tests/test_web_mapare_inline.py(~2 fisiere) - Test intai (RED):
tests/test_web_mapare_inline.py—test_detaliu_needs_mapping_arata_operatii_nemapate(GET detaliu peneeds_mapping→ HTML contine selectorul de cod RAR + denumirea operatiei + cel putin o sugestie)test_mapeaza_inline_deblocheaza_randul(POST/trimitere/{id}/mapeazacu cod valid → submission trecequeued, maparea apare inoperations_mapping)test_mapeaza_inline_cod_necunoscut_respins(cod inexistent in nomenclator → mesaj eroare, submission ramaneneeds_mapping, nicio mapare salvata)test_mapeaza_inline_scoped_pe_sesiune(POST pe submission al altui cont → 404, fara mapare)test_mapeaza_inline_csrf_obligatoriu(fara token → 403)test_mapeaza_inline_respecta_batch(submission din import cubatch_id→ re-rezolvarea il atinge)
- Acceptance criteria:
_detaliu_ctxpestatus="needs_mapping"expunenemapate_inline=[{cod_op_service, denumire, suggestions:[{cod_prestatie, nume_prestatie, score}]}]+nomenclator.POST /trimitere/{id}/mapeaza(Form:cod_op_service,cod_prestatie,auto_send,csrf_token): verifica CSRF, scope pe sesiune (404 cross-account/inexistent ca restul rutelor), respinge cod absent din nomenclator (re-randeaza detaliul cu mesaj), altfelsave_mapping+reresolve_accountcubatch_idal randului, re-randeaza detaliul cu starea noua + mesaj.- Re-rezolvarea foloseste EXACT
save_mapping/reresolve_accountexistente (fara logica noua de clasificare); randurile-frate cu aceeasi operatie din acelasi batch se deblocheaza si ele. - Raspunsul trimite
HX-Trigger: trimiteriChanged(lista Trimiteri se reimprospateaza).
- Verificare E2E: dashboard pe
needs_mapping→ alegi cod RAR inline → randul devinequeued.
US-003: UI mapare inline in _trimitere_detaliu.html
Ca operator vreau un formular clar in detaliu (operatie + sugestii + selector cod + salveaza) pentru ca maparea sa fie evidenta si rapida.
- Depinde de: US-002
- Fisiere:
app/web/templates/_trimitere_detaliu.html, (eventual reuse din_macros.html),tests/test_web_mapare_inline.py(asserts pe HTML) - Test intai (RED): acoperit de US-002 (
test_detaliu_needs_mapping_arata_operatii_nemapate) - Acceptance criteria:
- Sectiune "Mapeaza codul operatiei" vizibila DOAR cand
status="needs_mapping"si existanemapate_inline; un<form hx-post="/trimitere/{id}/mapeaza">per operatie,hx-target="#trimitere-detaliu". - Selector cod RAR populat din nomenclator, cu sugestia top (score >= 60) preselectata; sugestiile afisate cu procent (ca in tab-ul Mapari).
- Include
csrf_token+ comutatorul auto-send (reuseui.autosend_toggle, default pornit). - Mesaj de rezultat (succes/eroare) randat la re-render, fara a pierde restul panoului.
- Sectiune "Mapeaza codul operatiei" vizibila DOAR cand
- Verificare E2E: idem US-002 (browser HTMX).
4. Riscuri
- Divergenta clasificarii: maparea inline NU trebuie sa reimplementeze rezolvarea. Mitigare:
reutilizeaza
save_mapping+reresolve_account(singura cale, ca tab-ul Mapari) — orice corectie de comportament ramane intr-un singur loc. - Scope batch:
reresolve_account(batch_id=None)atinge doar canalul API (batch_id IS NULL). Un submission de import (batch_idsetat) nu s-ar debloca. Mitigare: ruta paseazabatch_id-ul randului (test dedicattest_mapeaza_inline_respecta_batch). - Compat raspuns: noile campuri trebuie sa fie pur aditive. Mitigare: defaulturi goale + test de
regresie pe
on_unmapped_errorsi pe formadeduped.
5. Intrebari deschise — REZOLVATE (poarta de aprobare, 2026-06-23)
- Q1 [DA]: pastram AMBELE — campuri structurate (
erori/nemapate) pentru masini +motiv(string uman pe o linie) pentru log/UI rapida. Implementat ca atare. - Q2 [DA]: maparea inline apare DOAR pe operatii nemapate reale. Pe
needs_mappingdinauto_send=0(cod deja mapat, doar trimitere oprita) NU se afiseaza —_nemapate_pentru_submissionintoarce lista goala in acel caz; confirmarea ramane in tab-ul Mapari.
6. Valuri de executie (graful de dependente)
Val 1: [US-001] [US-002] ← fisiere disjuncte (router/models vs web routes) → paralel
Val 2: [US-003] ← deblocat de US-002 (template peste contextul nou)
Raport VERIFY
Completat de subagentul verificator (context curat) in faza VERIFY — vezi ROADMAP §5.6. PASS/FAIL per criteriu, cu dovezi (output pytest citat, E2E pe RAR test). Lipseste pana la VERIFY.