# PRD ROAAUTO-1.0 — Transmitere operatii service la RAR AUTOPASS **Stare**: aprobat (review /autoplan complet, 2026-07-09); **revizuit 2026-07-09** — eliminat orice tabel nou Oracle (decizia lui Marius): configurarea sta in tabelul standard `optiuni`, iar situatia transmiterilor se citeste din gateway intr-un **cursor temporar** (gateway-ul e singura sursa de adevar; ROAAUTO nu persista nimic local). > Feature ROAAUTO (VFP9/Oracle): buton/fereastra pentru transmiterea operatiilor de service > din comenzile **inchise (validate) si facturate intr-o perioada** catre gateway-ul > **autopass.romfast.ro** (`POST /v1/prezentari`, auth `X-API-Key`). > Contract API (sursa de adevar): repo `rar-autopass` — `app/models.py` (`PrezentareIn`), > `app/api/v1/router.py`, `docs/api-rar-contract.md`. Maparea cod operatie ROAAUTO → cod > prestatie RAR se face **server-side** in gateway (`operations_mapping`), NU in ROAAUTO. ## 1. Obiectiv Legea 142/2023 + OM 210/2024 obliga service-urile sa declare la RAR, la finalul fiecarei lucrari, datele obligatorii (VIN, nr. inmatriculare, kilometraj, prestatii). ROAAUTO detine deja toate datele; livrabila adauga o fereastra cu **filtru pe perioada (data facturii)** care listeaza comenzile inchise+facturate si le transmite in lot la gateway-ul AUTOPASS. Gateway-ul preia validarea de continut, maparea codurilor, coada, retry, declararea efectiva la RAR **si evidenta a ce s-a transmis** — ROAAUTO ramane un **client subtire, fara stocare locala**. Fereastra pe perioada are doua roluri: (a) **stingerea backlog-ului** — obligatia e activa din 01.12.2024, deci prima utilizare recupereaza lucrarile nedeclarate de la start; si (b) transmiterea periodica curenta, pana cand ROAAUTO-1.1 adauga transmiterea automata la inchiderea comenzii (fereastra ramane atunci UI de review/exceptii). ## 2. Non-Goals (anti scope-creep) - **NU se creeaza NICIUN tabel/secventa nou(a) in schema Oracle** — configurarea sta in tabelul standard `optiuni` (mecanism existent), evidenta transmiterilor sta in gateway si se consulta prin API intr-un cursor temporar. Zero scripturi de instalare. - NU se apeleaza API-ul RAR direct — doar gateway-ul autopass.romfast.ro. - NU se face maparea cod operatie → cod prestatie RAR in ROAAUTO (exista in gateway; operatiile nemapate se rezolva in dashboard-ul web AUTOPASS, tab Mapari). - NU se implementeaza management de cont/credentiale RAR in ROAAUTO (se face pe web). - NU se transmit piese/materiale — doar operatiile de manopera (`DEV_OPER`). - NU se construieste transmitere automata pe timer in aceasta livrabila (poate deveni ROAAUTO-1.1 dupa ce fluxul manual e verificat in productie). - NU se modifica fluxul de inchidere/facturare a comenzilor. ## 3. Date sursa (ROAAUTO / Oracle) Filtru: `validat = 1 AND facturat = 1 AND id_tip IN (1,2) AND datafact BETWEEN :d1 AND :d2` pe view-ul **`auto_istoric_comenzi`** (coloanele complete: `Programe\oproceduri_vizualizare.prg:447`). **Decis**: TOATE comenzile facturate — POST GARANTIE (`ID_TIP=1`) si GARANTIE (`ID_TIP=2`), conform nomenclatorului `DEV_TIP_DEVIZ` (`Scripturi_instalare\initializari.sql:199-208`). REGIE (3), PREGATIRE (4), REGIE 2 (5), PRODUCTIE si constatarile NU se transmit (`id_tip >= 3` exclus; oricum majoritatea nu au factura → cad la `facturat=1`). | Camp payload AUTOPASS | Sursa ROAAUTO | Observatii | |---|---|---| | `vin` | `auto_istoric_comenzi.SERIES` | VARCHAR2(17), serie sasiu | | `nr_inmatriculare` | `auto_istoric_comenzi.NRINMAT` | VARCHAR2(10) | | `data_prestatie` | `DATAORAVALID` (data inchiderii/validarii) | format `YYYY-MM-DD`; **decis** — perioada de filtrare ramane pe `DATAFACT` | | `odometru_final` | `DEV_ORDL.KMINT` (km la primire, snapshot pe comanda) | string numeric; **decis** — singura citire disponibila | | `prestatii[]` | `DEV_OPER` (sters=0) JOIN `DEV_NOM_NORME` | per operatie: `{cod_op_service: CODOP, denumire: DENOP}` | | `obs` | `NRORD` + `NRFACT` (ex. `Comanda 1234 / Factura 5678`) | **cheia de corelare** comanda ↔ prezentare in gateway (vezi US-005) | Comenzile fara operatii (doar piese) nu se transmit (gateway respinge `PRESTATII_GOALE`). ## 4. Stories atomice ### US-001: Configurare conexiune AUTOPASS (tabelul `optiuni`) **Ca** administrator **vreau** sa configurez URL-ul gateway-ului, cheia API si mediul RAR (`test`/`prod`) **pentru ca** transmiterea sa functioneze per societate, fara valori hardcodate si **fara tabele noi**. - **Depinde de**: — - **Fisiere**: `Programe\oproceduri_autopass.prg` (citire config); NIMIC in `Scripturi_instalare\` - **Mecanism (existent, refolosit)**: tabelul `optiuni` (varname/vartype/varvalue/vardesc/programe) + procedurile din `COMUN\programe\oinit_optiuni.prg`: - la pornirea aplicatiei, `optiuni_firma` creeaza variabilele globale din `optiuni` (CHARACTER → prefix `gc`, ex. `gcAUTOPASS_URL`); - la runtime, `citeste_optiune('')` citeste din cursorul `crsOptiuni` (incarcat la pornire de `actualizeaza_optiuni`), `scrie_optiune()` scrie prin `PACK_SESIUNE.SetOptiune` (merge: randul se creeaza la prima scriere — deci NU e nevoie de niciun script de seed); - **UI de configurare (decis)**: valorile se editeaza DIRECT din fereastra de transmitere (US-004) — panou "Configurare" in aceeasi forma, un singur formular, fara fereastra separata. (Fiind tot tabelul `optiuni`, raman vizibile si in fereastra standard Optiuni, dar acela nu e fluxul principal.) - **Optiuni noi** (toate CHARACTER): | varname | global | continut | |---|---|---| | `AUTOPASS_URL` | `gcAUTOPASS_URL` | URL gateway, implicit `https://autopass.romfast.ro` | | `AUTOPASS_KEY` | `gcAUTOPASS_KEY` | cheia API (`X-API-Key`) | | `AUTOPASS_ENV` | `gcAUTOPASS_ENV` | `test` / `prod` / gol = default cont | - **Acceptance criteria**: - [ ] `autopass_get_config()` citeste cele 3 valori prin `citeste_optiune()` (fallback pe variabilele globale `gcAUTOPASS_*` daca exista); la prima rulare, daca `AUTOPASS_URL` lipseste, se scrie valoarea implicita cu `scrie_optiune('AUTOPASS_URL', 'https://autopass.romfast.ro', 'URL gateway RAR AUTOPASS')`. - [ ] `autopass_salveaza_config(tcUrl, tcKey, tcEnv)` scrie cele 3 valori prin `scrie_optiune()` — apelata de panoul Configurare din fereastra (US-004). - [ ] Panoul **Configurare** din fereastra de transmitere: URL gateway, cheie API (textbox cu `PasswordChar` + buton arata/ascunde), mediu RAR (combo: `Testare`/`Productie`/`implicit cont`), butoanele **Test conexiune** si **Salveaza**. Test conexiune apeleaza `GET /v1/ping` si afiseaza `mediu`, `autentificat_cu_cheie`, `are_creds_test/prod`. - [ ] `AUTOPASS_KEY` goala → fereastra se deschide direct cu panoul Configurare extins + mesaj clar; gridul si Transmite raman dezactivate pana exista cheie salvata. - [ ] Dupa **Salveaza**: config-ul se reciteste, ping-ul se reia automat, badge-ul de mediu si starea butoanelor se actualizeaza fara a inchide fereastra. - **Verificare E2E**: completare cheie in panou → Salveaza → `GET /v1/ping` intoarce `autentificat_cu_cheie: true`; valorile apar in tabelul `optiuni`. ### US-002: Extragere comenzi + operatii pe perioada **Ca** utilizator **vreau** lista comenzilor inchise si facturate in perioada aleasa, cu operatiile lor, **pentru ca** sa vad exact ce urmeaza sa se transmita. - **Depinde de**: — - **Fisiere**: `Programe\oproceduri_autopass.prg` — proceduri cursor header + detaliu - **Acceptance criteria**: - [ ] Cursor header din `auto_istoric_comenzi`: `id_ordl, nrord, dataoravalid, datafact, nrfact, nrinmat, series, kmint, nume, tip_comanda`, filtrat `validat=1 AND facturat=1 AND id_tip IN (1,2) AND datafact BETWEEN d1 AND d2` (+ `sters=0` unde e cazul). - [ ] Cursor detaliu: `SELECT o.id_ordl, n.codop, n.denop FROM dev_oper o JOIN dev_nom_norme n ON o.id_norme=n.id_norme WHERE o.sters=0 AND o.id_ordl IN (…)`. - [ ] Pre-validare locala pe rand (aceleasi reguli ca `app/validation.py`): VIN 17 caractere fara O/I/Q, NRINMAT ≤10 alfanumeric, `data_prestatie ≥ 2024-12-01` si ≤ azi, km numeric — randurile invalide se marcheaza vizual cu motivul si nu se pot bifa. - [ ] `CODOP` gol/NULL in `DEV_NOM_NORME` → operatia se marcheaza pe rand (motiv "operatie fara cod"); operatiile identice duplicate in aceeasi comanda se deduplica inainte de trimitere. - **Verificare E2E**: perioada cu comenzi cunoscute → numarul de randuri corespunde cu istoricul comenzilor. ### US-003: Client HTTP + serializare JSON (`POST /v1/prezentari`) **Ca** sistem **vreau** o clasa VFP care construieste JSON-ul si face POST cu `X-API-Key` **pentru ca** transmiterea sa fie robusta si raspunsul parsabil. - **Depinde de**: US-001 - **Fisiere**: `Programe\oproceduri_autopass.prg` (clasa `AutopassClient`); biblioteca JSON `nfjsoncreate.prg`/`nfjsonread.prg` din `COMUN\utile\nfjson\` - **Acceptance criteria**: - [ ] POST via `winHTTP.winHTTPrequest.5.1` (pattern `D:\ROA\ems_trimite_facturi_spv.prg` → `SendeFactura`), headere `Content-Type: application/json` + `X-API-Key`, body UTF-8. - [ ] Body: `{"prezentari": [...], "rar_env": }` — prestatii cu `cod_op_service` + `denumire` (maparea ramane in gateway); `raspuns` implicit `minim`. - [ ] Transmitere in loturi de max 50 prezentari per request; corelarea raspunsului se face pe `index` **per lot** (index e relativ la cererea curenta, nu global) — clientul tine maparea `index lot → id_ordl` explicit. - [ ] Encoding **verificat empiric, nu presupus**: intai se testeaza ce emite `nfjsoncreate` pentru ă/â/î/ș/ț (escape `\uXXXX` ASCII vs bytes locale). Daca escapeaza in ASCII → NU se aplica STRCONV (l-ar corupe); daca emite bytes cp1250 → conversie UTF-8 (`STRCONV(...,9)`) SAU Send pe byte-array cu `charset=utf-8`. Criteriu: round-trip pe mediul test cu diacritice, verificat in dashboard. - [ ] Datele Oracle (DATAORAVALID) → `YYYY-MM-DD` construit explicit (`STR(YEAR())+'-'+PADL(MONTH(),2,'0')+'-'+PADL(DAY(),2,'0')`), NICIODATA DTOC/DTOS (depind de SET DATE). Valabil si pentru CSV (US-006). - [ ] Parametrii de perioada in SQL pass-through ca literali `TO_DATE('YYYY-MM-DD','YYYY-MM-DD')` — elimina ambiguitatea DMY/MDY. - [ ] Timeout-uri explicite pe WinHTTP — semnatura reala e `SetTimeouts(resolve, connect, send, receive)` in ms (ex. 30000 fiecare); FARA retry automat in client — retrimiterea e manuala si sigura (idempotenta server-side). Statusul/eroarea WinHTTP bruta intra in contextul logat (diagnoza proxy-uri client). - [ ] `DOEVENTS` + verificare Renunta/ESC intre loturi (Send e sincron si blocheaza UI-ul); peste ~200 comenzi bifate, dialog suplimentar de confirmare. - [ ] **Cheia API nu se logheaza niciodata** (nici header-ele complete); raspunsurile logate in LOG.txt contin VIN/nr. inmatriculare → se trateaza ca date personale (trunchiate la strictul necesar diagnosticului). - [ ] Clientul ramane **transport pur**: primeste obiecte/cursoare si intoarce `{index, submission_id, status, motiv, id_prezentare}`; corelarea cu id_ordl si actualizarea gridului raman in proceduri/forma → testabil dintr-un driver .prg fara forma. - [ ] Parsare raspuns minim per element: `index, submission_id, vehicul, status, motiv, id_prezentare`; HTTP ≠ 200 (401/422/5xx) → mesaj cu detaliul din body, fara crash. - [ ] Erorile HTTP/parse se scriu si in `LOG.txt` (logul runtime existent), cu context: actiune, lot, cod HTTP, primele 500 caractere din raspuns. - [ ] Retrimiterea aceluiasi continut e sigura (idempotenta server-side → `deduped`); statusul intors se afiseaza onest (inclusiv `needs_mapping`/`needs_data`/`held`). - **Verificare E2E**: POST pe mediul RAR **test** cu o comanda reala → `status: queued` si submission vizibil in dashboardul web. ### US-004: Fereastra "Transmitere AUTOPASS" + buton **Ca** utilizator **vreau** o fereastra cu perioada, grid cu bife si butonul **Transmite la AUTOPASS** **pentru ca** sa controlez ce se declara si sa vad rezultatul per comanda. - **Depinde de**: US-002, US-003, US-005 - **Fisiere**: `Ferestre\frm_autopass.scx` (forma noua, in VFP IDE), lansata din procedura `trimitere_autopass` in `oproceduri_autopass.prg`; **punct de intrare (decis)**: butonul existent "Export" — `Clase\ofundal_dev.vcx`, clasa `pg_meniu_princ`, `Page2.Cw8.do_actiune()` (azi: `DO export_comanda_xml IN oproceduri_devize.prg`) devine meniu contextual, dupa pattern-ul `Page5.Cw3.do_actiune`: ```foxpro lnOptiune = xmenu("Export \>] | +- Configurare (panou pliabil, extins automat cand lipseste cheia) ---------+ | URL gateway: [https://autopass.romfast.ro ] | | Cheie API: [************************] [arata] | | Mediu RAR: [Testare v] [Test conexiune] [Salveaza] | +--------------------------------------------------------------------------+ | [x] | NrCmd | DataInch | Factura | NrInmat | VIN | Km | Client | Op | Status | Motiv | | x | 1234 | 02.07 | 5678 | B99XYZ | ... | .. | ... | 3 | sent | | <- 2: ce se trimite | | 1235 | 03.07 | 5679 | (gri — fara operatii / VIN invalid) | | +--------------------------------------------------------------------------+ | [Bifeaza tot] [Debifeaza] [Valideaza (dry-run)] [TRANSMITE] [Statusuri] | <- 3: actiuni | [Deschide dashboard AUTOPASS] n bifate / m total | +--------------------------------------------------------------------------+ ``` **Un singur formular**: configurarea (US-001) traieste in acelasi `frm_autopass.scx`, ca panou pliabil sub bara de perioada — implicit strans cand config-ul e valid, extins automat (cu focus pe cheie) cand `AUTOPASS_KEY` lipseste sau ping-ul intoarce 401. Grid dens, limbaj utilitar (conventiile aplicatiei, pattern `frm_istoric_comenzi`); butonul TRANSMITE e cel mai proeminent, dar la dreapta actiunilor de verificare. - **Acceptance criteria**: - [ ] Filtru perioada (implicit luna curenta) pe **data facturii** + buton Actualizeaza. - [ ] Grid: bifa, nr. comanda, data inchidere, nr./data factura, nr. inmatriculare, VIN, km, client, nr. operatii, **status transmitere** (din situatia gateway-ului, US-005) + motiv. - [ ] Bifeaza tot / debifeaza tot; comenzile regasite in situatia gateway-ului cu status ne-esuat (`queued`/`sent`/`deduped`/`held`/`needs_*`) vin implicit nebifate. - [ ] Badge vizibil de mediu: `PRODUCTIE` (rosu) / `Testare` (gri) — regula "rosu = real"; pe `prod`, confirmare explicita inainte de trimitere cu numarul de comenzi. - [ ] Dupa trimitere, statusul si motivul se actualizeaza pe fiecare rand fara a inchide fereastra (din raspunsul POST, direct in cursorul gridului — nu se persista nimic). - [ ] Butonul Transmite se dezactiveaza pe durata transmiterii (guard dubla-apasare); progres vizibil (ex. "lot 2/5..."). - [ ] Stare goala: perioada fara comenzi → mesaj clar in grid + buton Transmite dezactivat. - [ ] **Indicator de acoperire** vizibil permanent: "Declarabile in perioada: N | Transmise (sent): M | Blocate/nedeclarabile: K" — singura metrica ce raspunde la "suntem conformi?"; K > 0 e evidentiat. (M/K calculate din situatia US-005 + pre-validarea US-002, la fiecare refresh.) - [ ] Comenzile fara operatii apar in grid (gri, nebifabile) cu motivul "fara operatii de manopera" — vizibile, nu ascunse tacit. - [ ] La deschiderea ferestrei se apeleaza `GET /v1/ping`: mediul si starea creds RAR apar in bara de titlu/status; cheie lipsa/invalida → gridul si actiunile raman dezactivate, panoul Configurare se extinde automat cu mesaj (US-001) — utilizatorul corecteaza si salveaza fara sa inchida fereastra. - [ ] Schimbarea mediului RAR din panoul Configurare + Salveaza → badge-ul si situatia (US-005) se reincarca imediat (statusurile difera intre test si prod). - [ ] Buton **Valideaza (dry-run)**: `POST /v1/prezentari/valideaza` pe selectie — arata verdictul per comanda (status_estimat, erori, coduri nemapate) FARA enqueue; recomandat inainte de prima trimitere pe Productie. - [ ] Buton/link **Deschide dashboard AUTOPASS** (browser, URL-ul din config). - [ ] **Vocabular statusuri** (gateway → eticheta romaneasca + culoare + pasul urmator; NU se afiseaza tokenii englezesti bruti): | Gateway | Eticheta | Culoare | Pas urmator afisat | |---|---|---|---| | `queued` | In asteptare la RAR | galben | se actualizeaza cu butonul Statusuri | | `sent` | Transmis | verde | — (afiseaza nr. prezentare) | | `needs_mapping` | Cod fara mapare RAR | portocaliu | rezolva in dashboardul AUTOPASS, tab Mapari | | `needs_data` | Date incomplete | portocaliu | corecteaza comanda si retrimite | | `held` | Retinut (Auto OFF) | rosu | elibereaza din dashboard sau activeaza Auto | | `error` | Eroare | rosu | vezi motivul; corecteaza si retrimite | | `deduped` | Deja transmis | gri | nimic de facut | | *(negasit in situatie)* | Netransmis | alb | bifeaza si transmite | - [ ] **Fail-closed la deschidere**: pana raspunde ping-ul, badge = "Se verifica mediul...", Transmite si Valideaza dezactivate; wait cursor pe apelurile sincrone. - [ ] Badge-ul de mediu = banda plina in partea de sus a formei (nu doar title bar) + cuvantul PRODUCTIE/TESTARE si langa butonul Transmite; niciodata doar culoare. Dialogul de confirmare repeta cuvantul mediului + numarul de comenzi bifate valide. - [ ] Verdictul dry-run se afiseaza pe **canal separat** (coloana "Verdict validare" + banner sumar "Validare: 12 OK, 2 coduri nemapate") — NU suprascrie coloana de status transmitere. - [ ] **Sumar la final de transmitere**: dialog/linie "18 transmise, 3 in asteptare, 1 cod fara mapare — vezi randurile portocalii." - [ ] Textbox read-only sub grid cu status+motiv complet al randului curent (motivele lungi nu incap in celula de grid). - [ ] "Bifeaza tot" selecteaza DOAR randurile eligibile (valide si netransmise). - [ ] Buton **Renunta** onorat intre loturi (WinHTTP e sincron — singurul punct de anulare). - [ ] Nota implementare VFP: randuri invalide = `DynamicBackColor`/`DynamicForeColor` + `When() = .F.` pe coloana de bifa (gridul VFP nu are readonly per celula). - **Verificare E2E**: flux complet pe mediul test — filtrare, bifare, transmitere, statusuri corecte in grid. ### US-005: Situatia prezentarilor din gateway (cursor temporar, FARA stocare locala) **Ca** utilizator **vreau** sa vad, per comanda din perioada, ce s-a transmis deja si cu ce status **pentru ca** sa nu retransmit inutil si sa pot proba conformarea — **fara** ca ROAAUTO sa tina vreo evidenta locala. - **Depinde de**: US-003 - **Fisiere**: `Programe\oproceduri_autopass.prg` — procedura `autopass_situatie(d1, d2)` → cursor temporar `crs_autopass_situatie`. NICIUN tabel, NICIO secventa, NICIUN script. - **Principiu**: gateway-ul este **singura evidenta** a transmiterilor (are deja submissions, statusuri, istoricul complet si dashboardul web). ROAAUTO doar interogheaza si coreleaza in memorie, la fiecare refresh; la inchiderea ferestrei totul dispare. - **Acceptance criteria**: - [ ] `autopass_situatie(d1, d2)` apeleaza endpoint-ul de listare al gateway-ului (`GET /v1/prezentari?data_de=YYYY-MM-DD&data_pana=YYYY-MM-DD`, filtrat pe `data_prestatie` si pe cheia API a societatii) si construieste cursorul temporar `crs_autopass_situatie`: `submission_id, vin, nr_inmatriculare, data_prestatie, status, motiv, id_prezentare, obs`. **Dependenta gateway**: daca endpoint-ul de listare pe perioada nu exista inca in `rar-autopass`, se adauga INTAI acolo (produs propriu) — blocheaza US-005, nu se ocoleste cu stocare locala. - [ ] **Corelare** prezentare ↔ comanda: primar pe `obs` (`Comanda NRORD / Factura NRFACT` — string determinist generat de ROAAUTO la trimitere); fallback pe `vin + data_prestatie`. Rezultatul populeaza coloanele status/motiv din gridul US-004. - [ ] Comanda negasita in situatie = "Netransmis" (eligibila la bifare); comanda gasita cu orice status ne-esuat vine implicit nebifata (protectie la retransmitere, pe langa idempotenta server-side). - [ ] Buton **Actualizeaza statusuri** = re-apeleaza `autopass_situatie()` pe perioada afisata si reimprospateaza gridul (aduce `queued` → `sent` + `id_prezentare` dupa ce workerul gateway proceseaza). - [ ] Acelasi refresh ruleaza **automat la deschiderea ferestrei** (decizia 6, poarta /autoplan) si dupa fiecare transmitere, cu wait cursor. - [ ] Situatia indisponibila (endpoint picat / eroare) → gridul afiseaza "Status necunoscut — situatia gateway indisponibila" pe toate randurile, transmiterea ramane posibila DOAR cu confirmare explicita (idempotenta face retrimiterea sigura); eroarea se logheaza in LOG.txt. - **Verificare E2E**: dupa ce workerul gateway proceseaza, Actualizeaza statusuri aduce `sent` + `id_prezentare` in grid; cazul 2 comenzi / acelasi VIN / aceeasi zi se coreleaza corect pe `obs` (chei de idempotenta diferite prin NRORD). ### US-006: Export operatii facturate CSV (canal alternativ + mod degradat oficial) **Ca** utilizator **vreau** sa export operatiile facturate din perioada intr-un CSV compatibil cu importul web AUTOPASS **pentru ca** sa pot incarca manual lucrarile in dashboard cand prefer canalul de import — si ca **fallback desemnat** cand API-ul e indisponibil sau neconfigurat (exportul functioneaza si cu config-ul API gol; obligatia legala nu depinde de un singur canal). - **Depinde de**: US-002 - **Fisiere**: `Programe\oproceduri_autopass.prg` — procedura `export_operatii_csv` - **Acceptance criteria**: - [ ] Cere perioada (data facturii), refoloseste cursoarele din US-002 (acelasi filtru `validat=1, facturat=1, id_tip IN (1,2)`). - [ ] Format acceptat de `POST /v1/import` / upload web (vezi `rar-autopass/exemple/prezentari_test.csv`): separator `;`, antet `VIN;Numar inmatriculare;Data prestatie;Odometru initial;Odometru final;Operatie;Observatii`, **un rand per operatie** (aceeasi comanda se repeta pe mai multe randuri — importul le grupeaza pe vehicul+data). - [ ] `Data prestatie` = `DATAORAVALID` in format `YYYY-MM-DD`; `Odometru final` = `KMINT`; `Operatie` = `CODOP` (sau `DENOP` — coloana `Operatie` accepta text liber, maparea o face gateway-ul); `Observatii` = `Comanda NRORD / Factura NRFACT`. - [ ] Fisier salvat cu PUTFILE/GETDIR, encoding compatibil (diacriticele din denumiri nu sparg importul). - **Verificare E2E**: CSV-ul exportat se incarca in dashboardul web AUTOPASS si coloanele se auto-mapeaza corect. ## 5. Riscuri - **Calitatea datelor istorice** (VIN gol/invalid, NRINMAT cu spatii/cratime, km 0): mitigat prin pre-validarea din US-002 (randuri marcate, netransmisibile) + statusul onest `needs_data` intors de gateway. - **Dubla declarare la RAR**: mitigat dublu — idempotenta server-side (dedup pe continut) + situatia din gateway (US-005: comenzile regasite vin nebifate). - **Corelarea pe `obs`** depinde de formatul fix `Comanda NRORD / Factura NRFACT`: formatul se genereaza dintr-un singur loc (functie dedicata, folosita si la POST, si la corelare, si la CSV) — nu se construieste ad-hoc in doua locuri. - **Trimitere accidentala pe Productie** (ireversibila conform Legii 142): badge rosu + dialog de confirmare cu mediul si numarul de comenzi (US-004). - **Operatii nemapate in gateway**: primele loturi vor produce `needs_mapping`; se rezolva o singura data per cod in dashboardul web (sau bulk cu `tools/import_dbf.py` din `legacy-vfp/mapare_prestatii.DBF`, care contine deja mapari ROAAUTO). - **VFP + TLS**: `winHTTP` pe Windows vechi poate esua pe TLS 1.2; pattern-ul e deja folosit in productie pentru ANAF SPV (`ems_trimite_facturi_spv.prg`), deci riscul e cunoscut/mic. - **Endpoint de listare in gateway**: US-005 presupune `GET /v1/prezentari` cu filtru pe perioada; daca lipseste, se implementeaza intai in `rar-autopass` (blocant asumat — NU se compenseaza cu tabel local). ## 6. Intrebari deschise > Se rezolva cu utilizatorul INAINTE de executie. Decizii luate (fost intrebari 1-4): 1. **DECIS** — `data_prestatie` = `DATAORAVALID` (data validarii/inchiderii comenzii); perioada de filtrare ramane pe `DATAFACT`. 2. **DECIS (confirmat la poarta /autoplan, dupa contestarea ambelor voci independente)** — `odometru_final` = `KMINT`. Justificare asumata: e singura citire de bord existenta in date, e o citire reala a vehiculului in perioada lucrarii, iar contractul RAR cere `odometruFinal` obligatoriu (a trimite doar `initial` ar fi respins). Semantic, KMINT e km la primire — decizie documentata, de revizuit doar daca RAR o conteste. 3. **DECIS** (revizuit la review-ul CEO) — TOATE comenzile facturate: post-garantie (`ID_TIP=1`) si garantie (`ID_TIP=2`). Regie/pregatire/productie/constatare (`id_tip >= 3`) NU se transmit. 4. **DECIS** — punct de intrare: butonul "Export" din `Clase\ofundal_dev.vcx` (`pg_meniu_princ.Page2.Cw8.do_actiune`) devine `xmenu` cu 3 optiuni: Export xml (existent) / Export operatii facturate csv (US-006) / Trimitere operatii facturate in autopass.romfast.ro (US-004). 5. **DECIS** — o singura cheie API per baza de date (societate); optiunile `AUTOPASS_*` din tabelul `optiuni` tin o singura configurare. Context (poarta /autoplan): clientii actuali au un singur service auto per firma; daca apar clienti cu mai multe service-uri/conturi RAR, config-ul se extinde atunci. 6. **DECIS (poarta /autoplan)** — la deschiderea ferestrei, pe langa ping, se actualizeaza automat situatia prezentarilor (US-005) pentru perioada afisata; butonul "Actualizeaza statusuri" ramane pentru refresh manual. 7. **DECIS (revizie 2026-07-09, Marius)** — **ZERO tabele noi**: configurarea in tabelul `optiuni` (mecanismul existent `oinit_optiuni.prg`), evidenta transmiterilor NUMAI in gateway, consultata prin API intr-un cursor temporar. Fostele `AUTO_AUTOPASS_CONFIG`, `AUTO_AUTOPASS_TRIMITERI`, `SEQ_AUTOPASS_TRIMITERI` sunt eliminate din plan (si revertate din `Scripturi_instalare\`). 8. **DECIS (revizie 2026-07-10, Marius)** — **un singur formular**: URL-ul, cheia API si mediul RAR se editeaza direct din fereastra de transmitere (panou Configurare pliabil in `frm_autopass.scx`), nu dintr-o fereastra separata; salvarea trece prin `scrie_optiune()` (`autopass_salveaza_config`). 9. **DECIS (revizie 2026-07-10, Marius)** — **normalizare NRINMAT aprobata**: eliminarea spatiilor, cratimelor si punctelor din numarul de inmatriculare inainte de validare se aplica consecvent pe cele 3 canale: gateway `rar-autopass` (validare + idempotency), clientul VFP (`autopass_valideaza_rand` din `oproceduri_autopass.prg`) si spike-ul SQL de calitate a datelor (`docs\spike_calitate_date_autopass_v2.sql`, versiune noua fata de spike-ul v1 rulat initial). Motivatie: spike-ul v1 a aratat doar 13,8% NRINMAT valide din cauza formatelor reale cu spatii/cratime (ex. "B 99 XYZ"), regula stricta anterioara (doar strip+upper) fiind prea restrictiva fata de datele istorice reale. Nu mai exista intrebari deschise — PRD aprobat prin poarta /autoplan (2026-07-09), revizuit conform deciziilor 7-9 (decizia 9 e o completare post-aprobare, 2026-07-10). ## 7. Valuri de executie ``` Val 0: [SPIKE calitate date] ← un singur SQL, INAINTE de orice implementare: din comenzile facturate (id_tip 1,2) de la 01.12.2024, ce procent au VIN valid 17 car., NRINMAT si KMINT > 0? Rezultatul calibreaza asteptarile si decide daca e nevoie si de un proiect de remediere a datelor. [VERIF gateway] ← exista GET /v1/prezentari (listare pe perioada)? daca nu → se adauga intai in rar-autopass. Val 1: [US-001] [US-002] ← independente, zone distincte → paralel Val 2: [US-003] [US-005] [US-006]← US-003 dupa config; US-005 dupa client HTTP; US-006 dupa cursoare Val 3: [US-004] ← forma finala + xmenu in ofundal_dev.vcx (VFP IDE) ``` --- ## Anexa review /autoplan (CEO + Design + Eng, 2026-07-09) ### NOT in scope (considerat si amanat explicit) - **Transmitere automata la validarea comenzii** (hook in `validare_comenzi`) — ROAAUTO-1.1, dupa ce fluxul manual e verificat in productie. - **Vizualizare/rezolvare mapari pending in ROAAUTO** (`GET /v1/mapari/pending`) — se face in dashboardul web AUTOPASS; duplicarea editorului in VFP nu aduce valoare. - **Listare/tiparire jurnal transmiteri** (raport FRX) — gridul + dashboardul web acopera nevoia; raport doar la cerere ulterioara. - **Actualizare automata a statusurilor pe timer** — refresh-ul la deschidere + butonul manual "Actualizeaza statusuri" sunt suficiente in v1.0. - **Criptarea cheii API** — cheia sta in clar in `optiuni.varvalue` (AUTOPASS_KEY), ca restul configurarilor din schema; acces limitat la schema aplicatiei. Se poate cripta ulterior. ### What already exists (refolosit, nu reconstruit) - `auto_istoric_comenzi` — view-ul cu tot header-ul necesar (comanda+factura+vehicul+km). - `DEV_OPER` + `DEV_NOM_NORME` — operatiile cu CODOP/DENOP. - **Tabelul `optiuni` + `oinit_optiuni.prg`** (`optiuni_firma`, `citeste_optiune`, `scrie_optiune`, fereastra standard Optiuni) — configurarea AUTOPASS fara tabele noi. - `D:\ROA\ems_trimite_facturi_spv.prg` (`SendeFactura`) — pattern-ul WinHTTP + header auth, deja folosit in productie pentru ANAF SPV (inclusiv TLS pe Windows-urile clientilor). - `nfjsoncreate/nfjsonread` — biblioteca JSON VFP (vendored din rar-autopass/legacy-vfp). - Gateway-ul insusi: validare continut, mapare coduri, idempotenta, coada, retry, dashboard **si evidenta completa a transmiterilor** (motivul pentru care ROAAUTO nu mai tine jurnal). - Pattern-ul `xmenu` + `do_actiune` din `ofundal_dev.vcx` (Page5.Cw3) pentru punctul de intrare. ### Error & Rescue Registry (US-003 `AutopassClient` + fereastra) | Codepath | Ce poate esua | Tratare | Utilizatorul vede | |---|---|---|---| | WinHTTP Send | timeout / DNS / TLS / gateway down | catch `loEx`, log LOG.txt, opreste lotul curent | "Gateway indisponibil: . Reincearca mai tarziu." | | HTTP 401 | cheie API invalida/lipsa | opreste tot, nu continua loturile; panoul Configurare se extinde | "Cheie API respinsa — corecteaza cheia in panoul Configurare." | | HTTP 422 | mediu RAR indisponibil / limita plan / JSON invalid | afiseaza `detail`-ul din body per lot | mesajul gateway-ului, netradus | | HTTP 5xx | eroare interna gateway | log + mesaj, lotul se poate retrimite (idempotent) | "Eroare gateway (500). Retrimiterea e sigura." | | Parse JSON raspuns | raspuns malformat/gol | catch nfjsonread, log body brut in LOG.txt | "Raspuns neasteptat de la gateway — vezi LOG.txt" | | SQL pass-through Oracle | conexiune cazuta / view lipsa | pattern-ul standard al aplicatiei (verificare cursor) | eroarea standard a aplicatiei | | GET situatie (US-005) | endpoint picat / raspuns invalid | statusuri "necunoscut" in grid, transmitere doar cu confirmare explicita; log | "Situatia gateway indisponibila — statusurile nu au putut fi citite" | | Rand `needs_data`/`needs_mapping` | date incomplete / cod nemapat | status onest in grid, motiv afisat | motivul exact (ex. "Coduri fara mapare RAR: ...") | **Reguli**: fara catch-all mut — orice Catch scrie context in LOG.txt; niciun esec nu e silentios (fiecare rand bifat primeste un status vizibil sau un motiv de esec). ### Failure Modes Registry | Codepath | Failure mode | Tratat? | Vizibil? | |---|---|---|---| | Transmitere lot | crash intre loturi (lot 2/5 trimis, 3 nu) | gateway-ul are submissions-urile trimise; refresh-ul situatiei (US-005) le arata; retrimiterea e idempotenta | DA — statusuri per rand la urmatorul refresh | | Dubla transmitere | acelasi continut retrimis | dedup server-side → `deduped` | DA — status "deja transmis" | | KMINT=0 / VIN gol | date istorice proaste | pre-validare US-002 → rand marcat, nebifabil | DA — motiv pe rand | | Diacritice corupte | encoding gresit in JSON | encoding verificat empiric (US-003) | test E2E cu denumiri cu diacritice | | IN (...) > 1000 elemente | perioada mare, Oracle ORA-01795 | detaliul se citeste pe chunk-uri de max 500 id-uri | transparent | | Situatie indisponibila | GET listare esueaza | statusuri necunoscute + confirmare explicita la transmitere | DA — mesaj pe grid | | Trimitere pe prod din greseala | mediu gresit | badge rosu + dialog de confirmare cu mediu si numar | DA — confirmare explicita | ### Decizii auto-luate (audit trail — principiile /autoplan) | # | Faza | Decizie | Clasificare | Principiu | |---|------|---------|-------------|-----------| | 1 | CEO 0C-bis | Client subtire → gateway (vs CSV-only vs API RAR direct in VFP) | mecanic | P1 completeness, P4 DRY | | 2 | CEO 0D | Accept: buton "Deschide dashboard AUTOPASS" | auto-accept | P2 blast radius, S | | 3 | CEO 0D | Accept: ping + badge mediu la deschiderea ferestrei | auto-accept | P2, era partial in US-004 | | 4 | CEO 0D | Accept: buton Valideaza (dry-run) via `/v1/prezentari/valideaza` | auto-accept | P1 — verificare fara efecte | | 5 | CEO 0D | Defer: auto-send la validare, mapari pending, listare jurnal, timer statusuri | auto-defer | P3 — in afara blast radius | | 6 | CEO S2 | Timeout-uri explicite + fara retry client (idempotenta server) | mecanic | P5 explicit | | 7 | CEO S4 | Encoding UTF-8 verificat + test diacritice | mecanic | P1 | | 8 | CEO S7 | Chunk-uri de max 500 id-uri la detaliul operatiilor | mecanic | corectitudine Oracle | | 9 | Premise gate | Scope: toate comenzile facturate (id_tip 1,2), fara regie/productie | decizia utilizatorului | — | | 10 | Design P2 | Tabel stari interactiune adaugat in US-004 (loading/empty/error/success) | mecanic | P1 | | 11 | Eng S1 | Corelare index→id_ordl per lot, explicit in US-003 | mecanic | P5 | | 12 | Design voice #1 | Vocabular statusuri RO (fara tokeni englezesti in grid) | mecanic | P1 — utilizatorul e consilier service, nu dev | | 13 | Design voice #2/#3 | Banda de mediu + fail-closed pana la ping | mecanic | P1 — actiune ireversibila | | 14 | Design voice #4 | Verdict dry-run pe canal separat de statusul real | mecanic | P5 — evita retrimiterile accidentale | | 15 | Design voice #5-#9 | Sumar final, textbox motiv, Bifeaza-tot doar eligibile, Renunta intre loturi, nota DynamicBackColor | mecanic | P1/P5 | | 16 | CEO voice #2 | Reframe: v1.0 = stingere backlog (obligatie din 01.12.2024) + transmitere curenta | mecanic | P6 | | 17 | CEO voice #4 | Val 0: SPIKE SQL calitate date (procent comenzi declarabile) inainte de implementare | auto-accept | P1 — un singur SQL | | 18 | CEO voice #5 | Indicator de acoperire (declarabile/transmise/blocate) in fereastra | auto-accept | P1 — metrica de conformare | | 19 | CEO voice #7 | CSV US-006 desemnat mod degradat oficial (functioneaza fara config API) | mecanic | P3 | | 20 | Eng voice #2 | Encoding verificat empiric (nfjsoncreate) inainte de STRCONV | mecanic | P5 — nu pe incredere | | 21 | Eng voice #3/#12 | Date YYYY-MM-DD construite explicit + TO_DATE in SQL | mecanic | P5 | | 22 | Eng voice #4 | DOEVENTS + Renunta intre loturi + prag confirmare 200 | mecanic | P1 | | 23 | ~~Eng voice #5~~ | ~~Jurnal append-only cu PK secventa~~ **ANULAT de decizia 7 (Marius): fara jurnal local — evidenta e in gateway, consultata prin API** | decizia utilizatorului | — | | 24 | Eng voice #6-#9 | Dedup VIN+zi verificat in E2E, cheia API nelogata, CODOP gol marcat, client transport pur | mecanic | P1/P5 | | 25 | Revizie Marius | Config in `optiuni` (mecanism existent), zero tabele noi, situatie in cursor temporar | decizia utilizatorului | — | | 26 | Revizie Marius | Un singur formular: panou Configurare (URL/cheie/mediu) direct in fereastra de transmitere | decizia utilizatorului | — | Contestari NEauto-decise (poarta finala): C1 enqueue-on-close vs manual (CEO voice #1); C2 KMINT ca odometru_final (CEO #3 + Eng #1 — ambele voci independente); C3 multi-CUI (CEO #6); T1 auto-refresh statusuri la deschiderea ferestrei (taste). ### Arhitectura (Eng S1, revizuita — zero tabele noi) ``` ofundal_dev.vcx (Page2.Cw8 xmenu) |1 Export xml -> export_comanda_xml (existent, oproceduri_devize.prg) |2 Export CSV -> export_operatii_csv \ |3 Trimitere AUTOPASS -> trimitere_autopass } oproceduri_autopass.prg (NOU) | frm_autopass.scx (NOU) | | cursoare Oracle AutopassClient (WinHTTP, JSON UTF-8) (auto_istoric_comenzi, | dev_oper+dev_nom_norme) +--> https://autopass.romfast.ro | /v1/ping /v1/prezentari config: tabel `optiuni` /v1/prezentari/valideaza (AUTOPASS_URL/KEY/ENV via /v1/prezentari?perioada (situatie) citeste_optiune/gc*) | crs_autopass_situatie (cursor temporar, corelat pe `obs` cu gridul — NU se persista nimic local) ``` Cuplaj: fereastra depinde doar de procedurile din `oproceduri_autopass.prg`; clientul HTTP nu stie de Oracle (primeste/intoarce cursoare/obiecte) → reutilizabil pentru auto-send 1.1. ### Acoperire de test (Eng S3 — verificare manuala E2E, VFP nu are framework de teste) ``` CODEPATHS VERIFICARE AUTOPASS_KEY goala -> panou Configurare extins E2E: goleste cheia, redeschide fereastra salvare config din panou -> ping + badge E2E: schimba mediul test<->prod, Salveaza GET /v1/ping ok/401 E2E: cheie buna / cheie gresita cursor header (perioada cu/fara comenzi) E2E: 2 perioade cunoscute pre-validare (VIN invalid, km 0, fara operatii)E2E: comenzi istorice reale dry-run /valideaza E2E: verdictele = trimiterea reala POST lot ok / 422 / 5xx E2E pe mediul RAR TEST dedup (retrimitere aceleasi comenzi) E2E: a doua trimitere -> deduped diacritice in DENOP E2E: comanda cu operatii cu s,t,a,i situatie: corelare obs + refresh statusuri E2E: queued -> sent + id_prezentare in grid situatie indisponibila E2E: URL gresit -> statusuri necunoscute + confirmare CSV export -> import web E2E: upload in dashboard, automap coloane xmenu (3 optiuni, Esc) E2E: fiecare ramura + anulare driver .prg fara forma (1 comanda hand-built) E2E: acopera encoding/headers/timeouts izolat 2 comenzi, acelasi VIN, aceeasi zi E2E: corelare corecta pe obs (NRORD diferit) ``` Toate pe mediul RAR **test** inainte de orice trimitere pe prod. ### Dream state delta 12 luni: declararea RAR e zero-touch — la validarea comenzii, transmiterea pleaca automat, statusul apare pe comanda, iar utilizatorul intervine doar la `needs_mapping`/`needs_data`. Planul v1.0 construieste exact fundatia reutilizabila (config in optiuni, client HTTP, situatie din gateway, fereastra); 1.1 adauga hook-ul de auto-send. Nicio piesa din v1.0 nu se arunca. ## Raport VERIFY > Se completeaza la faza VERIFY: PASS/FAIL per criteriu, cu dovezi (ping, POST pe RAR test, > capturi grid + dashboard web). Lipseste pana la VERIFY. ## GSTACK REVIEW REPORT | Review | Trigger | Why | Runs | Status | Findings | |--------|---------|-----|------|--------|----------| | CEO Review | `/plan-ceo-review` | Scope & strategy | 1 | CLEAN (PLAN via /autoplan) | 6 propuneri, 3 acceptate, 4 amanate; contestarile C1-C3 rezolvate la poarta | | Codex Review | `/codex review` | Independent 2nd opinion | 0 | — (Codex neinstalat, voci = subagent-only) | — | | Eng Review | `/plan-eng-review` | Architecture & tests (required) | 1 | CLEAN (PLAN via /autoplan) | 12 constatari, 0 critical gaps, toate incorporate | | Design Review | `/plan-design-review` | UI/UX gaps | 1 | CLEAN (FULL via /autoplan) | scor 5/10 → 9/10, 9 decizii adaugate | | DX Review | `/plan-devex-review` | Developer experience gaps | 0 | SKIPPED | fara scope developer-facing | - **VERDICT:** CEO + ENG + DESIGN CLEARED — gata de implementare. Decizii poarta finala: C1=A (manual v1.0, auto-send in 1.1), C2=A (KMINT ca odometru_final, documentat), C3=A (o cheie/BD; multi-service se revizuieste la nevoie), T1=A (auto-refresh la deschidere). - **Revizie post-aprobare (2026-07-09, Marius)**: decizia 7 — zero tabele noi; US-001 rescris pe tabelul `optiuni`, US-005 rescris pe situatia din gateway (cursor temporar); scripturile SQL revertate. - **Revizie post-aprobare (2026-07-10, Marius)**: decizia 9 — normalizare NRINMAT (strip spatii/cratime/puncte) aprobata pe cele 3 canale (gateway, client VFP, spike SQL v2); motivata de rata scazuta de valid (13,8%) gasita in spike-ul v1. NO UNRESOLVED DECISIONS