Curatenie ceruta dupa inchiderea lui #6. Folderul cercetare\ NU se putea sterge in bloc: plan_13 se sprijina pe el cu 85 de trimiteri, deci e baza de dovezi a planului aflat in lucru. Impartirea: - 14 cercetari trans-proiect trec in COMUN\docs\cercetare\ - valuta si curs, TVA/VANZARI, consumatorii VANZARI din toata suita, integrarile #10/#11/#12, watchdog VFP, proiectarea Oracle a lui S5, view-ul VVANZARI_ARTICOLE. Nu sunt ale ROAFACTURARE, iar #10/#11/#12 se reiau chiar din ele. - 20 de rapoarte de executie ale lui #6, nereferite de nimic viu, sterse. - 91 raman, neatinse. Trimiterile catre handoff-urile si diff-urile intermediare deja desfiintate au fost curatate peste tot (39 de fisiere): 50 catre handoff-uri, 37 catre diff-uri aplicate, plus caile celor mutate in COMUN. Zero trimiteri rupte ramase. progres.md preia rolul de predare: ce ramane din #6 (cele sase documente parazite, cele doua esecuri reale din S8 pe factura din aviz), cifrele de test citite din log, si cele doua capcane de mediu platite - .FXP vechi executat in locul .prg-ului, si GETFONT() care atarna un formular instantiat fara goApp. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
246 lines
16 KiB
Markdown
246 lines
16 KiB
Markdown
# Implementarea deciziei 42 — articole needitabile pe factura trimisa in eFactura
|
|
|
|
Scris 10.08.2026. Implementare + testare + write-back verificat. **ZERO commit** (git/svn),
|
|
conform interdictiei primite.
|
|
|
|
> ## COMPLETARE, 10.08.2026 ora ~12:55 — discountul de antet intra sub garda
|
|
>
|
|
> Agentul care a scris acest raport a apucat sa faca **modificarea de cod si write-back-ul**, apoi a
|
|
> cazut pe limita de sesiune **inainte de verificare**. Blocul de mai jos e scris de orchestrator,
|
|
> care a preluat si a dus verificarea la capat.
|
|
>
|
|
> **Decizia lui Marius**: `txtDiscountArt` (discountul de antet) **se blocheaza si el** cand documentul
|
|
> e trimis in eFactura — schimba totalurile unui document deja depus la ANAF, chiar daca nu atinge
|
|
> nicio linie.
|
|
>
|
|
> **Codul**: `omodificari.vc2:14813` — `This.pgfArticole.PAGE3.txtDiscountArt.ReadOnly =
|
|
> This.lArticoleReadOnly`, prin acelasi flag, fara mecanism nou.
|
|
>
|
|
> **A doua cale de scriere — cautata si exclusa**: `txtDiscountArt.Valid` (`:16592`) doar cheama
|
|
> `Thisform.ActualizeazaBaraTotaluri()`, deci **recalculeaza afisajul, nu scrie discountul nicaieri**.
|
|
> Nu exista buton sau apel programatic care sa-l seteze ocolind caseta, deci garda dubla care a fost
|
|
> necesara la butoanele de articole (`Click`) **nu isi are rostul aici**. Salvarea propriu-zisa trimite
|
|
> discountul ca parametru catre `recalculeaza_totaluri_vanzari` (decizia 41), luand valoarea din caseta.
|
|
>
|
|
> **Verificat de orchestrator pe disc, dupa caderea agentului**:
|
|
> - **Write-back complet**, dovedit prin reconversie binar -> text in cache temporar si comparatie
|
|
> **octet cu octet**: identic, 540712 octeti. Cens de octeti `2 aa . 2 e3 . 2 fe`, zero `EF BF BD`.
|
|
> - **Regresia rerulata integral pe starea de pe disc**, dupa write-back (binar 12:33:09):
|
|
> `test_page3_articole` **14/2** (artefactul headless cunoscut), `test_adauga_linie_articol` **20/0**,
|
|
> `test_adauga_linie_valuta` **16/0**, `test_ui_sterge_linie` **8/0**, `test_verdict_act_rul` **26/0**,
|
|
> `test_incarca_vanzare_din_nota` **5/0**, `test_s5_validari_articole` **35/0**. Nicio regresie.
|
|
> - **Acoperire noua**: `test_efactura_readonly.prg` extins cu doua asertii si rerulat —
|
|
> **23 PASS / 0 FAIL** (de la 21). Cele doua noi: `caz A: txtDiscountArt.ReadOnly = .T.` pe documentul
|
|
> real trimis in eFactura, si `caz B: txtDiscountArt.ReadOnly = .F. (neregresat)` pe cel netrimis.
|
|
> Garda e verificata deci **in ambele sensuri**, nu doar pe cazul pozitiv.
|
|
> - Zero procese `vfp9.exe` ramase, zero commituri.
|
|
>
|
|
> **Ce NU e acoperit**: suita UI vizibila (`test_ui_efactura_readonly.prg`, 14/0) **nu a fost rerulata**
|
|
> dupa adaugarea discountului — ea verifica `.When`-urile de celula, neatinse de aceasta completare,
|
|
> deci riscul e mic, dar golul e declarat, nu ascuns.
|
|
>
|
|
> Diff-ul consolidat (COMUN + ROAGEST) e regenerat in diff aplicat (sters).
|
|
|
|
## Ce s-a schimbat, si unde
|
|
|
|
### `COMUN\clase\omodificari.vc2` (`frm_modific2024`)
|
|
|
|
- **Proprietate noua** `lArticoleReadOnly` (Boolean, implicit `.F.`): `*p:` la `:6827`, valoare
|
|
implicita la `:6866`.
|
|
- **`Show`** (`:14788-14827`): calculeaza flagul in acelasi bloc unde se determina
|
|
`lAreArticoleVanzari`/`nIdVanzare`/`nTipVanzare` (adica doar cand `ofacturare_editare.prg` e
|
|
incarcat si documentul are rand in `VANZARI`):
|
|
`This.lArticoleReadOnly = EsteInEFactura(Nvl(tvanz.id_fact,0))` (`:14798`). In blocul care
|
|
pregateste `PAGE3`, aplica flagul: `cmdAdaugaArticol.Enabled`/`cmdStergeArticol.Enabled` =
|
|
`!lArticoleReadOnly` (`:14811-14812`), `lblArticoleReadOnly.Visible = lArticoleReadOnly`
|
|
(`:14813`). **`PAGE3` continua sa se pregateasca si sa se afiseze normal** —
|
|
`PregatesteArticoleFacturaEditare`/`PageCount=3`/`grdArticoleFactura.Refresh()` raman neatinse,
|
|
conform corectiei explicite a lui Marius (articolele raman vizibile).
|
|
- **Control nou** `pgfArticole.PAGE3.lblArticoleReadOnly` (`ADD OBJECT` la `:12776`): eticheta
|
|
discreta, `Visible=.F.` implicit, pozitionata pe randul butoanelor (`Top=4`, `Left=360`,
|
|
`Width=390`) — la dreapta lui `cmdAdaugaArticol` (care se termina la `Left+Width=345`), deci
|
|
**nu ia spatiu din grid** (gridul ramane la `Top=26`). Text: „Articole needitabile - factura
|
|
trimisa in eFactura", `ForeColor RGB(180,120,0)` (aceeasi nuanta de atentionare folosita deja
|
|
la verdictul ACT/RUL divergent).
|
|
- **Garda pe butoane** (`cmdAdaugaArticol.Click` `:16488`, `cmdStergeArticol.Click` `:16531`):
|
|
`OR Thisform.lArticoleReadOnly` adaugat la conditia de `RETURN` timpuriu — belt-and-suspenders
|
|
fata de `Enabled=.F.`, pentru ca `Enabled` nu blocheaza un apel programatic al metodei `.Click()`.
|
|
- **Garda pe celule** — cele patru `.When` care controleaza editabilitatea pe rand (mecanismul
|
|
din S5): `cCantitateArt.Text1.When` (`:16549`), `cPretAchizitieArt.Text1.When`,
|
|
`cPretArt.Text1.When` (`:16570`), `cPretCuTvaArt._checkbox1.When` (`:16587`) — toate primesc
|
|
`Thisform.lArticoleReadOnly OR ...` (respectiv `!Thisform.lArticoleReadOnly AND ...` pe
|
|
checkbox, unde conditia veche era inversa). Se construieste **peste** mecanismul de
|
|
editabilitate per rand din S5 (`id_vanzare_set`/`id_vanzare_det`), nu-l inlocuieste.
|
|
- **Notele/rulajele nu sunt atinse**: `Grid1` (nota contabila), `grdRulaje`/`grdRulajeObinv`
|
|
(paginile 1/2) raman complet neschimbate — verificat explicit in test (`Grid1.ReadOnly` ramane
|
|
`.F.` pe documentul din eFactura).
|
|
|
|
### `COMUN\programe\ofacturare_editare.prg`
|
|
|
|
Corectie necesara descoperita in timpul lucrului (vezi mai jos „Decizie/corectie luata pe
|
|
parcurs"): `EsteInEFactura` se apeleaza cu `VANZARI.ID_FACT`, **nu** cu `id_vanzare` — sunt doua
|
|
coloane distincte (verificat pe date: 0 potriviri `id_fact = id_vanzare` din 142 facturi tip=1).
|
|
Contractul existent (`ofacturare_comun.vc2:3764`, neatins) apela deja `EsteInEFactura(lnIdFact)`
|
|
cu `lnIdFact = crsfacturi.id_fact`. `tvanz` (populat de `IncarcaVanzareNota`) nu avea aceasta
|
|
coloana.
|
|
|
|
- `CreeazaCursorTvanzGol` (linia 153 din fisier): adaugat `id_fact I NULL` la structura cursorului
|
|
gol (fallback pe eroare Oracle/cod lipsa).
|
|
- `IncarcaVanzareNota` (linia 177): adaugat `v.id_fact` la lista de coloane selectate din
|
|
`VANZARI`. Restul interogarii (join, filtre) neatins.
|
|
- Antetul fisierului (o singura intrare cumulativa, rescrisa): data actualizata la 10.08.2026,
|
|
mentiunea `id_fact` adaugata la lista de campuri incarcate.
|
|
|
|
## Decizie/corectie luata pe parcurs — de raportat, nu era in briefing
|
|
|
|
Implementarea initiala folosea `EsteInEFactura(This.nIdVanzare)` (adica `id_vanzare`). Verificare
|
|
pe `MARIUSM_AUTO`:
|
|
|
|
```sql
|
|
SELECT COUNT(*) total, SUM(CASE WHEN id_fact = id_vanzare THEN 1 ELSE 0 END) equal_cnt
|
|
FROM vanzari WHERE tip = 1 AND sters = 0;
|
|
-- 142 total, 0 equal_cnt
|
|
```
|
|
|
|
`id_fact` si `id_vanzare` sunt spatii de ID complet diferite (`id_fact` are valori de forma
|
|
`8008013`, `id_vanzare` valori mici de forma `1013`) — cu `id_vanzare` gardarea nu s-ar fi
|
|
declansat NICIODATA in productie (nicio coincidenta intamplatoare intre cele doua plaje). Corectat
|
|
inainte de scrierea testelor, folosind exact coloana pe care o foloseste deja calea din
|
|
`ofacturare_comun.vc2:3764` (`lnIdFact = crsfacturi.id_fact`).
|
|
|
|
## Write-back — verificat prin reconversie + diff, nu pe mtime
|
|
|
|
`txt2vcx.ps1 -AllowComun` rulat de trei ori (prima incercare a picat fidelity-check-ul din cauza
|
|
ordinii gresite a blocului `ADD OBJECT` — proprietatile/obiectele dintr-o clasa `.vcx` trebuie in
|
|
ordine STRICT alfabetica dupa nume, nu dupa ZOrder; a doua rulare a picat pentru ca lipsea
|
|
corectia `id_fact`; **a treia rulare, OK**, fidelity check trecut).
|
|
|
|
Verificare **independenta** de fidelity-check-ul intern al `txt2vcx.ps1`: reconversie separata a
|
|
binarului proaspat scris (`vcx2txt.ps1 -Source omodificari.vcx` intr-un cache temporar izolat) +
|
|
`diff`/`cmp` octet cu octet fata de `.vc2`-ul din proiect:
|
|
|
|
```
|
|
diff -q omodificari.vc2 <reconversie>/omodificari.vc2 -> IDENTIC
|
|
cmp omodificari.vc2 <reconversie>/omodificari.vc2 -> BYTE-IDENTIC
|
|
```
|
|
|
|
Text si binar sunt sincrone, dovedit, nu presupus.
|
|
|
|
## Cens de octeti (regula cp1250) — inainte/dupa, identic cu baseline
|
|
|
|
`omodificari.vc2` are diacritice cp1250 preexistente (tooltip-uri „Renunțare/Adăugare/Ștergere",
|
|
octeti `0xFE`/`0xE3`/`0xAA`). **Baseline: `2 aa / 2 e3 / 2 fe`, zero `EF BF BD`.**
|
|
|
|
Editarea celor doua proprietati noi (`*p:`/`*<PropValue>`) s-a facut initial cu tool-ul `Edit`
|
|
(2 apeluri) — asta a **stricat** censul (`6 ef / 6 bf / 6 bd`, adica `EF BF BD` x2 aparitii x3
|
|
octeti), exact capcana documentata (`Edit`/`Write` re-encodeaza tot fisierul la orice scriere,
|
|
indiferent cat de mica). **Reparat** inainte de a continua: octetii corecti (`Renun[FE]are`,
|
|
`Ad[E3]ugare`, `[AA]tergere`) preluati din `git cat-file blob HEAD:clase/omodificari.vc2`
|
|
(varianta necorupta, comisa) si inlocuiti inapoi punctual. Toate editarile ulterioare (Show(),
|
|
garzile pe butoane/celule, blocul `ADD OBJECT` al etichetei noi) s-au facut **pe octeti**, cu
|
|
Perl (`<:raw`/`>:raw`, cautare/inlocuire literala `\Q...\E`, fara nicio decodare de encoding),
|
|
tocmai ca sa nu se repete problema. **Cens final: `2 aa / 2 e3 / 2 fe`, zero `EF BF BD`** —
|
|
identic cu baseline, verificat dupa fiecare grup de editari.
|
|
|
|
`ofacturare_editare.prg` nu are octeti `>=0x80` (cens gol inainte si dupa) — editat direct cu
|
|
`Edit`, fara risc.
|
|
|
|
## Regresie — cifre numarate din loguri, toate DUPA ultima editare de cod
|
|
|
|
Ultima editare de cod: `omodificari.vc2` scris in binar la `11:37:23` (a treia rulare
|
|
`txt2vcx.ps1`, cu corectia `id_fact`); `ofacturare_editare.prg` editat inainte de asta. Toate
|
|
rularile de mai jos sunt **dupa** acel moment.
|
|
|
|
| Suita | Rezultat | Baseline | Stare |
|
|
|---|---|---|---|
|
|
| `test_page3_articole.prg` | 14 PASS / 2 FAIL | 14/2 | **neregresat** (cele 2 FAIL = artefactul headless cunoscut, ColumnCount/ReadOnly pe grid needitabil sub `-A -T`) |
|
|
| `test_adauga_linie_articol.prg` | 20 PASS / 0 FAIL | 20/0 | **neregresat** |
|
|
| `test_adauga_linie_valuta.prg` | 16 PASS / 0 FAIL | 16/0 | **neregresat** |
|
|
| `test_ui_sterge_linie.prg` | 8 PASS / 0 FAIL | 8/0 | **neregresat** |
|
|
| `test_verdict_act_rul.prg` | 26 PASS / 0 FAIL | 26/0 | **neregresat** |
|
|
| `test_incarca_vanzare_din_nota.prg` | 5 PASS / 0 FAIL | 5/0 | **neregresat** |
|
|
| `test_s5_validari_articole.prg` | 35 PASS / 0 FAIL | 35/0 | **neregresat** (linia care contine cuvantul "FAIL" e text descriptiv al unei ramuri moarte deja documentate, nu un esec real — `REZULTAT: 35 PASS / 0 FAIL`) |
|
|
|
|
Zero regresii pe toate cele sapte suite existente.
|
|
|
|
## Suite noi
|
|
|
|
### `COMUN\utile\Teste\editare_factura\test_efactura_readonly.prg` (headless) — **21 PASS / 0 FAIL**
|
|
|
|
Documente REALE, gasite prin interogare (nu inventate):
|
|
- **Caz A — trimis in eFactura**: `id_vanzare=1013` (`cod=1140509`, an=2025, luna=8),
|
|
`VANZARI.ID_FACT=8008013`, prezent in `ANAF_EFACTURA`.
|
|
- **Caz B — NEtrimis** (regresie): descoperit prin proprietate (`DescoperaCazTest`,
|
|
`FACTURA_ARTICOLE`), `cod=1140895` (id_vanzare=1050, documentul deja folosit de restul suitei).
|
|
|
|
Acopera: `EsteInEFactura` direct (cu `0` si cu `8008013`); `lArticoleReadOnly` corect pe ambele
|
|
cazuri; **`PAGE3` NU e suprimata** (`PageCount=3`, `RecordSource` neschimbat, `tvd` cu linii);
|
|
`cmdAdaugaArticol`/`cmdStergeArticol.Enabled`; vizibilitatea etichetei; garda pe
|
|
`cmdStergeArticol.Click()` (apelat direct, fara dialog modal — confirma ca linia nu se modifica
|
|
pe documentul din eFactura si ca se modifica normal pe cel obisnuit); `Grid1.ReadOnly` neatins
|
|
(nota ramane editabila). Nu scrie in Oracle.
|
|
|
|
**Ce nu acopera** (documentat explicit in fisier, nu ascuns): editabilitatea per-celula
|
|
(`.When()` pe coloanele gridului) — coloanele **nu se materializeaza sub `-A -T`**
|
|
(`ColumnCount=0`, eroare 1925 „Unknown member" la accesul pe nume), artefact cunoscut si
|
|
documentat (`grid-coloane-nu-se-materializeaza-headless`). Mutat in suita UI de mai jos.
|
|
|
|
### `COMUN\utile\Teste\editare_factura\test_ui_efactura_readonly.prg` (UI vizibil) — **14 PASS / 0 FAIL**
|
|
|
|
Rulat prin harnessul corect (`vfp_ui_harness.ps1 -TestPrg ... -Steps @(...) -SyncDir ...`), nu
|
|
prin lansare directa — o incercare initiala prin `Start-Process` direct a dat tot `ColumnCount=0`;
|
|
cauza reala **nu era lansarea**, ci lipsa apelului `IncarcaArticoleFactura(1013,
|
|
'crsArticoleFactura')` **inainte** de `Createobject` — gridul se leaga o singura data, la
|
|
construire (in `Load()`), pe cursorul `tvd` existent atunci; fara precarcare, `Load()` creeaza
|
|
`tvd` GOL, iar fallback-ul din `Show()` il **recreeaza prin SQL** dupa constructie — cursor diferit
|
|
de cel pe care s-a legat gridul, deci `ColumnCount` ramane 0. Corectat dupa tiparul deja folosit de
|
|
`test_ui_s5_grid_pret_achizitie.prg`.
|
|
|
|
Acopera, pe acelasi document real (`id_vanzare=1013`, in eFactura): gridul are 15 coloane
|
|
(neregresat); `.When()` pe toate cele patru controale (`cCantitateArt`, `cPretArt`,
|
|
`cPretAchizitieArt`, `cPretCuTvaArt._checkbox1`) intorc `.F.` — **needitabile pe orice linie
|
|
normala, nu doar pe liniile din set**; caz sintetic de control (`lArticoleReadOnly` comutat manual
|
|
pe `.F.` pe acelasi document/aceleasi obiecte) — cele trei celule redevin editabile, deci gating-ul
|
|
e demonstrat pe flag, nu pe o coincidenta a documentului ales. Captura:
|
|
`screenshots_efactura\step_0_grid_efactura_readonly.png`. Nu scrie in Oracle.
|
|
|
|
## Ce NU s-a putut testa, si de ce
|
|
|
|
- **Dialogul de adaugare articol** (`frm_articol_factura`, `Show(1)` modal): garda de pe
|
|
`cmdAdaugaArticol.Click()` (Enabled=.F. + guard in cod) nu s-a putut exercita prin click real
|
|
headless — consecvent cu limitarea deja documentata pe restul suitei S4/S5 (dialog modal). Doar
|
|
`Enabled=.F.` verificat direct.
|
|
- **Ramura moarta preexistenta, gasita dar NEATINSA** (nu in scope): linia
|
|
`IF !Used('tvd') OR !This.lAreArticoleVanzari OR Thisform.lArticoleReadOnly` din
|
|
`cmdAdaugaArticol.Click` (`:16497`) foloseste `This.lAreArticoleVanzari` — `This` acolo e
|
|
butonul, nu formularul, deci proprietatea nu exista pe el. Ramane neexecutata in practica pentru
|
|
ca `!Used('tvd')` e `.F.` de fiecare data cand butonul chiar e vizibil (short-circuit VFP), deci
|
|
runtime-ul nu ajunge niciodata sa evalueze operandul gresit. Preexistenta editarii mele
|
|
(adaugarea mea e doar `OR Thisform.lArticoleReadOnly`, corect scris cu `Thisform`), nu se
|
|
repara aici — in afara scope-ului deciziei 42.
|
|
- **Verificarea vizuala pe ecran de Marius**: eticheta discreta, pozitionarea ei fata de butoane,
|
|
culoarea, comportamentul real la click de mouse pe grid.
|
|
|
|
## Stare finala verificata
|
|
|
|
- **Write-back facut si dovedit** pentru `omodificari.vc2` (reconversie + diff octet cu octet,
|
|
identic). `ofacturare_editare.prg` e `.prg` — sursa directa, fara pas de write-back.
|
|
- Cens de octeti pe `omodificari.vc2`: **`2 aa / 2 e3 / 2 fe`, zero `EF BF BD`** — identic cu
|
|
baseline, verificat dupa ultima editare.
|
|
- Zero procese `vfp9.exe` ramase (verificat cu `tasklist`) dupa toate rularile mele. Procesul
|
|
`vfp9.exe` al agentului `s8-creare-variante` (fereastra „S8 - creare documente") a ramas
|
|
intact, neatins.
|
|
- Zero scrieri in Oracle in toata sesiunea — toate interogarile (`EsteInEFactura`,
|
|
`IncarcaCursoareModificareNota`, `IncarcaVanzareNota`, `IncarcaArticoleFactura`) sunt `SELECT`.
|
|
- Zero commit (git/svn).
|
|
- Diff consolidat: diff aplicat (sters) (ambele fisiere).
|
|
- Fisiere noi, necomise: `COMUN\utile\Teste\editare_factura\test_efactura_readonly.prg` (+ log),
|
|
`COMUN\utile\Teste\editare_factura\test_ui_efactura_readonly.prg` (+ log + screenshot in
|
|
`screenshots_efactura\`).
|
|
|
|
## Interzis — respectat
|
|
|
|
`ofacturare.vc2`, `ofacturare_comun.vc2`, `comun.vc2`: neatinse (verificat — niciun `Edit`/`Write`
|
|
pe ele in aceasta lucrare). `actualizeaza_vanzari`, `PACK_CONTAFIN`, `PACK_FACTURARE`: neatinse.
|
|
Niciun `INSERT`/`UPDATE` pe `id_vanzare` `1049`/`1050`/`1048`.
|