# Plan QA + corectii: adaugare/editare FACTURA si AVIZ Stare: **APROBAT 17.09.2026**. Mandat de executie continua: toate stories, commit dupa fiecare, fara aprobare per story; singura exceptie e mockup-ul de la S4, care se arata inainte de implementare. Handoff la limita de context. Ultima actualizare: 17.09.2026. Fisier de stare viu asociat: `docs/progres_qa_factura.md` (se actualizeaza dupa FIECARE story). Harti de pornire (deja scrise, read-only): `docs/qa_factura_harta.md`, `docs/qa_factura_unelte.md`, `docs/qa_factura_hooks_ref.md`. ## 0. Unde se executa Executia trece pe **VM 304** (are D:\ROA, VFP 9, acces Oracle ROA_CENTRAL/MARIUSM_AUTO). Motiv: UI vizibil fara sa fure focusul de pe masina lui Marius. O sesiune noua acolo porneste din acest fisier + `docs/progres_qa_factura.md`. Momentul mutarii (decizie Marius): **dupa S0**, cu prototipul de context/handoff deja functional. S0 se face pe masina curenta (nu cere UI); de la S1 incolo totul e pe VM 304. Conexiune probe: `DO test_init_env_auto_roafacturare WITH 'CENTRAL','MARIUSM_AUTO','ROMFASTSOFT'` (`COMUN\utile\Teste\test_init_env_auto_roafacturare.prg:11,16-18`). `gnAn=2026`, `gnLuna=8`, `gnIdFirma=110`, `gnIdUtil=8` inainte de serii. ## 1. Constatari confirmate pe cod (baza planului) | # | Constatare | Dovada | |---|---|---| | C1 | Ecranul e clasa `frm_facturare_articole2`, nu `.scx`; instantiata doar cand `llFacturareNoua` | `COMUN\clase\ofacturare.vc2:15936-22614`; `COMUN\programe\ofacturare.prg:246-248` | | C2 | Pragul de 3 caractere = `ncharcountbegin=2` pe cele doua combo-uri + garda `Len(...) <= nCharCountBegin` | `ofacturare.vc2:17524-17537`, `17560-17574`, `463-496` | | C3 | Cautarea implicita e "incepe cu" (`RefreshData(1)`); "contine" exista dar e ascunsa dupa Ctrl+Enter | `COMUN\clase\_cb_base.vc2:636-649,720`; `ofacturare.vc2:476-489` | | C4 | Zero feedback in timpul cautarii: `KeyPress` cheama direct `RefreshData`, fara indicator, fara numar de rezultate, fara mesaj "nimic gasit" | `_cb_base.vc2:610-776` | | C5 | Nu exista debounce: se cauta la fiecare tasta peste prag | idem C4 | | C6 | Sursa duplicatelor pe articol e **in Oracle**, in `pack_facturare.cursor_preturi` (join cu politicile de pret) - nu in VFP | `ofacturare.vc2:446-461`; tabela `crm_politici_pret_art` folosita la `ofacturare.vc2:21755` | | C7 | Nu exista niciun selector de lista de preturi in formular; se trimite `poDate.id_gestiune_init`, sau `poDate.listaid` doar cand `tip=45` | `ofacturare.vc2:453-457` | | C8 | Controalele de jos sunt copii directe ale formularului, fara container, cu Top 742/745/767/789/792 si Anchor mixt 4 vs 12; nimic nu le repozitioneaza la runtime | `ofacturare.vc2:18082-18195`; `Resize` la `21847-21854` nu le atinge | | C9 | Factura vs aviz = `poDate.nIdTipDoc` 5 vs 6; helper `EsteAviz()` | `COMUN\programe\ofacturare_antet.prg:16-18` | **Necunoscuta blocanta**: corpul `pack_facturare.cursor_preturi` nu e in working copy. Se citeste din `ALL_SOURCE` pe MARIUSM_AUTO inainte de orice decizie despre listele de preturi (Story S3). ## 2. Constrangeri de perimetru - `combosql` (`COMUN\clase\_cb_base.vc2:519`) e clasa de baza folosita de TOATE produsele ROA. **Nu se modifica.** Tot comportamentul nou de cautare se suprascrie in `combosql_cautare` (`ofacturare.vc2:407-531`), care e specifica facturarii. - `ofacturare.vc2` traieste in `COMUN\` - dublu-versionat SVN+git, commit tintit din `COMUN\`. - `.vc2` se editeaza cu script Python binar (nu `sed -i`, nu Edit pe linii cu octeti >0x7F); diacriticele sunt cp1250. Write-back doar `txt2vcx.ps1 -ProjectRoot D:\ROA\ROAFACTURARE`. - Dupa fiecare write-back: `MODIFY CLASS` + captura, apoi designerul se INCHIDE inainte de urmatorul write-back. - Un singur agent scrie pe `ofacturare.vc2` la un moment dat. Probele pe aceeasi clasa nu ruleaza in paralel cu write-back-ul. ## 3. Stories ### S0 - Prototip context/handoff (se face PRIMUL, se foloseste pe restul planului) Reutilizeaza ce exista: `context_watch.ps1` (in `D:\ROA\ROAGEST\COMUN\utile\`) deja citeste `usage` din transcriptul JSONL si alerteaza la 250k/275k. Nu se rescrie. Se repara si se extinde: 1. **Bug activ**: hook-ul `SubagentStop` din `~/.claude/settings.json` re-injecteaza acelasi mesaj runda dupa runda (observat azi, si notat deja in memorie). Cauza documentata: hook-ul nu citeste `stop_hook_active` din JSON-ul de pe stdin si nu iese cu 0 cand e adevarat (plafon 8 blocari consecutive). Fix: garda `stop_hook_active` la inceputul hook-ului. 2. **Fisier de stare scris de hook, nu de model**: `context_watch.ps1` primeste `-StareFile` si, la pragul de avertisment, scrie/actualizeaza un antet in `docs/progres_.md` (procent context, ora, ultimul bloc). Modelul completeaza continutul; hook-ul garanteaza ca fisierul exista si e datat chiar daca sesiunea moare. 3. **Compactare mai devreme si previzibila**: `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` in `env` din settings (ex. 70), ca auto-compact-ul sa cada DUPA pragul de avertisment al lui `context_watch`, nu inaintea lui. Compactarea NU poate fi declansata programatic - documentat, deci mecanismul ramane: hook avertizeaza -> modelul scrie handoff -> compactarea vine singura. 4. Se muta in `COMUN` (cerinta Marius) ca sa fie refolosibil de toate produsele ROA. Proba: o sesiune de proba cu un subagent care se termina => hook-ul ruleaza o singura data; fisierul de stare exista si are marca de timp. ### S1 - Baseline QA: dovada vizuala si scenarii Pe VM 304, formular vizibil prin `vfp_ui_harness.ps1`: - capturi la 1366x768 si la rezolutia de lucru, pentru FACTURA si pentru AVIZ; - captura zonei de jos (totaluri+discount) cu formularul la inaltime minima si maximizat - dovada pentru C8 si pentru comportamentul Anchor 4 vs 12; - scenariul de cautare: tastare progresiva pe un cod cunoscut din MARIUSM_AUTO, captura dupa fiecare caracter - dovada pentru C2/C4; - articol prezent in mai multe politici: captura cu randurile duplicate - dovada pentru C6. Livrabil: `docs/qa_factura_baseline.md` + capturi. Nicio modificare de cod in S1. ### S2 - Cautare articole (toate cele patru cerinte) In `combosql_cautare`, fara sa atinga `combosql`: - prag de la primul caracter (`ncharcountbegin=0` pe cele doua instante + garda actualizata); - cautare "contine" implicita, si pe cod si pe denumire; - debounce ~250ms + limita de randuri, ca sa nu plece o interogare per tasta; - feedback: indicator "se cauta...", numarul de rezultate, mesaj explicit la zero potriviri. Proba: headless pe filtrul construit (asertii pe sirul trimis catre `cursor_preturi`) + proba UI vizibila pe VM pentru feedback si latenta. ### S3 - Selector de lista de preturi (implicit lista clientului) **Depinde de citirea `pack_facturare.cursor_preturi` din `ALL_SOURCE` pe MARIUSM_AUTO.** Decizie Marius 17.09.2026: citirea `ALL_SOURCE` e permisa, iar modificarea pachetului e permisa **doar pe MARIUSM_AUTO**, prin script `wip13_*.sql.txt` idempotent (`CREATE OR REPLACE`), inregistrat in registrul de scripturi. Nimic nu pleaca spre clienti. Tinta functionala: un combo in formular, prefixat cu lista din politica clientului, plus optiunea "Toate listele"; in modul implicit fiecare articol apare o singura data. ### S4 - Zona totaluri + discount, regandita ca bloc Mockup HTML inainte de implementare (mockup-urile stau online, nu in `docs/`). Dupa aprobarea mockup-ului: container dedicat, Anchor unitar, aliniere pe grila, etichete. Atentie: `Anchor=4` face ca Top-ul design-time sa conteze la rulare - orice schimbare de inaltime se probeaza la 1366 maximizat. ### S5 - Regresie Suita existenta + probele noi, pe FACTURA si pe AVIZ, adaugare si editare. Raport prin `raport_teste.ps1`, nu loguri brute. ## 4. Ordine si commit S0 -> S1 -> S2 -> S3 -> S4 -> S5. Commit pe branch de lucru dupa fiecare story (cod `COMUN` din `COMUN\`, restul din radacina), fara push; SVN si merge raman la Marius. `docs/progres_qa_factura.md` se actualizeaza dupa fiecare story, nu la final. Documentele de lucru din `docs/` nu se comit pe main. ## 5. Datorii deschise cunoscute la scrierea planului - Corpul `pack_facturare.cursor_preturi` necitit - blocheaza S3. - Cifra plafonului de blocari repetate ale unui stop hook: 8 (confirmat in ghid) vs 100 (`CLAUDE_CODE_STOP_HOOK_BLOCK_CAP`), nereconciliat. - Daca `PreCompact` poate bloca compactarea prin exit 2: nedocumentat.