Folderul docs\ era pana acum in afara oricarui control de versiuni - nici git, nici SVN - desi contine planurile pe puncte, proiectarile si rapoartele de cercetare pe care se sprijina modificarile din cod. O stergere acolo era definitiva. Fisierele intermediare (handoff-uri intre sesiuni, diff-uri deja aplicate) au fost sterse inainte, nu versionate: ce era durabil in ele a intrat in antetele fisierelor de test la care se refereau. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
222 lines
13 KiB
Markdown
222 lines
13 KiB
Markdown
# S4 — doua defecte pe pagina de articole: culoarea liniei sterse + valuta liniilor noi (09.08.2026)
|
|
|
|
Doua defecte raportate dupa livrarea sub-blocului B (stergere + adaugare de linii). Ambele in
|
|
`COMUN\clase\omodificari.vc2` (`frm_modific2024`, `pgfArticole.PAGE3`); al doilea atinge si
|
|
`COMUN\programe\ofacturare_editare.prg`. **Ambele REZOLVATE, dovedite, scrise in binar,
|
|
necomise.**
|
|
|
|
## Defectul 1 — marcajul vizual `DynamicForeColor` nu se aplica pe linia stearsa
|
|
|
|
### Cauza reala (nu ipoteza de start, confirmata pe cod)
|
|
|
|
`grdArticoleFactura` e definit ca `ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura' AS _grdrow`
|
|
(`omodificari.vc2:12306`), unde `_grdrow` (`COMUN\clase\_grd_base.vc2:445-489`) e o clasa a suitei
|
|
comune (nu proprietatea acestei livrari — doar citita) care evidentiaza linia curenta a gridului:
|
|
|
|
```
|
|
PROCEDURE Init
|
|
DoDefault()
|
|
If This.nRgbrow = 1
|
|
...
|
|
This.SetAll("DynamicForeColor","iif(RECNO() = This.nRecno,RGB(" + This.cRGB_Font + "),RGB(0,0,0))","Column")
|
|
Endif
|
|
ENDPROC
|
|
```
|
|
|
|
`nrgbrow` implicit e `1`. La instantiere, dupa ce `PropValue`-urile clasei (inclusiv
|
|
`Column1..14.DynamicForeColor = "IIF(tvd.sters=1,RGB(150,150,150),RGB(0,0,0))"`) sunt aplicate,
|
|
`Init` ruleaza si **`SetAll` suprascrie necondiționat** `DynamicForeColor` pe toate cele 14
|
|
coloane cu o expresie care ignora `tvd.sters` complet — de-asta linia stearsa avea pixeli negri
|
|
puri (0,0,0), nu gri (150,150,150): codul din clasa era corect, dar era deja inlocuit inainte de
|
|
primul `Refresh()`.
|
|
|
|
Ipoteza de start din briefing ("`_grdrow.Init` castiga in fata lui `DynamicForeColor`") s-a
|
|
confirmat exact, cu mecanismul precis identificat (`SetAll` in `Init`, nu doar `AfterRowColChange`).
|
|
|
|
### De ce nu solutia gridurilor surori
|
|
|
|
`grdRulaje`/`grdRulajeObinv` (`pgfArticole.PAGE1`/`PAGE2`) rezolva coliziunea cu `Init` **gol**
|
|
(`*Nu sterge`, `omodificari.vc2:~15659`/`~15926`) — asta taie tot lantul `DoDefault()`, deci si
|
|
`_grid.Init()` (cel care seteaza `ReadOnly` pe coloanele text dupa `lcamptextneeditabil`).
|
|
`grdArticoleFactura` are nevoie sa ramana editabil pe `cantitate`/`pret`/`pret_cu_tva`
|
|
(`lcamptextneeditabil=.F.`, fix din sesiunea anterioara) — un `Init` gol ar fi rupt din nou
|
|
editabilitatea.
|
|
|
|
### Fix
|
|
|
|
O singura proprietate pe `ADD OBJECT`-ul gridului (`omodificari.vc2:12317`):
|
|
|
|
```
|
|
nrgbrow = 0, ;
|
|
```
|
|
|
|
`nrgbrow=0` scurt-circuiteaza intreg blocul `If This.nRgbrow = 1` din `_grdrow.Init` (deci si
|
|
`SetAll`) **fara sa taie** `DoDefault()` -> `_grid.Init()` — editabilitatea ramane intacta.
|
|
Tiparul e deja folosit in **20+ griduri** din suita comuna (`COMUN\clase\configurare.vc2`,
|
|
`COMUN\clase\onomenclatoare.vc2`), deci nu e o solutie inventata pentru acest caz — e conventia
|
|
existenta pentru "grid cu culoare proprie pe randuri, fara evidentierea implicita a liniei
|
|
curente".
|
|
|
|
### Dovada — esantionare de pixeli, nu vizual
|
|
|
|
Doua capturi noi, sub `vfp_ui_harness.ps1 -SyncDir` explicit (capcana de sincronizare deja
|
|
rezolvata in sesiunea precedenta):
|
|
|
|
- `COMUN\utile\Teste\editare_factura\screenshots_after_fix_culoare\step_0_contrast_gri_vs_negru.png`
|
|
— document cu 4 linii (`cod=1140895`/`id_vanzare=1050`), linia 2 marcata stearsa prin
|
|
`cmdStergeArticol.Click()`, linia curenta a gridului mutata pe linia 3 (`GO 3` +
|
|
`loGrid.SetFocus()`) ca selectia (fundal albastru) sa nu acopere nici linia stearsa, nici o
|
|
linie de control. Esantionare cu `System.Drawing.Bitmap.GetPixel` pe banda de text a fiecarei
|
|
linii (PowerShell, cautare pixel cu luminanta minima in regiune):
|
|
|
|
| Linie | Pixel cel mai inchis (RGB) |
|
|
|---|---|
|
|
| Linia 1 (normala, `sters=0`) | `(0,0,0)` |
|
|
| **Linia 2 (STEARSA, `sters=1`)** | **`(150,150,150)`** — exact `RGB(150,150,150)` din `DynamicForeColor` |
|
|
| Linia 4 (normala, `sters=0`) | `(0,0,0)` |
|
|
|
|
- `COMUN\utile\Teste\editare_factura\screenshots_after_fix_culoare\step_0_linia_grizata.png` —
|
|
document cu 2 linii (`cod=1139934`/`id_vanzare=882`), aceeasi verificare, acelasi rezultat
|
|
(`RGB(150,150,150)` pe linia stearsa).
|
|
|
|
Capturile "before" (linia stearsa cu pixeli negri puri, dovada defectului inainte de fix), mutate
|
|
din sesiunea anterioara: `screenshots_before_fix_culoare\step_0_linia grizata dupa sters.png` +
|
|
`step_0_crop_zoom.png`.
|
|
|
|
### Testat, regresie
|
|
|
|
`test_ui_sterge_linie.prg` (existent, nemodificat in logica — doar rerulat): **8 PASS / 0 FAIL**,
|
|
log complet pana la `REZULTAT`. `test_page3_articole.prg`: **14 PASS / 2 FAIL** (identic cu
|
|
baseline, cele 2 FAIL sunt artefactul headless cunoscut de la datoria 7 — `ColumnCount`/`ReadOnly`
|
|
nu se materializeaza sub `-A -T`). `test_incarca_vanzare_din_nota.prg`: **5 PASS / 0 FAIL**.
|
|
|
|
Suita noua `test_ui_culoare_contrast.prg` (dedicata acestui fix, ramane in suita de regresie):
|
|
descopera dinamic un document cu minim 3 linii (`DescoperaCazTest('FACTURA_ARTICOLE', ...)`,
|
|
nu ancorat pe `cod`), marcheaza a doua linie stearsa, muta linia curenta pe a treia, face captura.
|
|
**1 PASS / 0 FAIL** pe asertia functionala (`sters=1` dupa click); dovada vizuala e in captura +
|
|
esantionarea de pixeli de mai sus, nu intr-o asertie automata (culoarea nu se poate verifica prin
|
|
`EVALUATE` in interiorul testului — eroarea 1929, deja documentata in `rec_s4_runda3b2.md`).
|
|
|
|
## Defectul 2 — liniile adaugate intrau fortat in RON
|
|
|
|
### Cauza reala (diferita de formularea initiala din briefing)
|
|
|
|
Briefingul presupunea ca `AdaugaLinieTvdDinArticol` scrie `tip_valuta = 0` fix — **verificat pe
|
|
cod, fals**: `tvd` (structura din `CreeazaCursorArticoleGol`, `ofacturare_editare.prg:268-271`) nu
|
|
are deloc un camp `tip_valuta`, `curs` sau `multiplicator` — acele campuri nu exista in view-ul
|
|
`VVANZARI_ARTICOLE` (linia stocheaza doar `id_valuta`, o referinta la `nom_valute`, fara factor de
|
|
conversie propriu).
|
|
|
|
Cauza reala e in alta parte: `tip_valuta=0`/`Curs=1`/`multiplicator=1` sunt hardcodate pe
|
|
**`poArticol`** in `CreeazaPoArticolNouTvd` (`ofacturare_editare.prg:429-431`), iar
|
|
`poDate.in_valuta` e hardcodat `0` in `cmdAdaugaArticol.Click` (`omodificari.vc2:16190`) — asta
|
|
tine dialogul `frm_articol_factura` in **modul RON** indiferent de valuta reala a documentului.
|
|
Dialogul calculeaza `pretftva`/`pretctva` (campurile RON) pe baza a ce introduce utilizatorul, iar
|
|
`AdaugaLinieTvdDinArticol` scria acele valori **neconvertite** in `tvd.pret`/`tvd.discount_unitar`.
|
|
|
|
Bara de totaluri (`ActualizeazaBaraTotaluri`, decizia 33, `omodificari.vc2:12856-12899`) insumeaza
|
|
`tvd.valoare` **brut** (`SUM valoare FOR sters<>1`) si aplica **o singura data**
|
|
`tvanz.curs`/`multiplicator` pe suma — asta presupune ca fiecare linie e deja stocata in valuta
|
|
documentului, nu in RON. Verificat pe date (schema `MARIUSM_AUTO`):
|
|
|
|
| `id_vanzare` | `VANZARI.in_valuta` | `VANZARI.id_valuta` | `curs` | linia (`VANZARI_DETALII.pret`) |
|
|
|---|---|---|---|---|
|
|
| 1037 | 1 | 2 (EURO) | 5.2688 | `pret=200` — 200 EUR brut, nu 200 RON |
|
|
|
|
O linie noua scrisa in RON (ex. utilizatorul intentioneaza 1053.76 RON) ar fi ramas `pret=1053.76`
|
|
in `tvd`, iar bara de totaluri ar fi calculat `1053.76 * 5.2688 = 5551.6` RON — de peste 5 ori
|
|
valoarea reala.
|
|
|
|
### Fix — scopat strict pe stocare, fara sa ating dialogul
|
|
|
|
`frm_articol_factura`/`ofacturare.vc2` **nu sunt in proprietatea acestei livrari** (partajate cu
|
|
tot restul suitei), si a face dialogul sa accepte pret direct in valuta ar cere
|
|
`poDate.id_valuta`/`poDate.zi_curs` populate corect (altfel validarea interna a dialogului
|
|
respinge la "Terminare" cu mesaj — verificat pe cod, `ofacturare.vc2:9484,9490`) — netestabil
|
|
headless (`Show()` e modal) si risc pe o clasa mare, necunoscuta. Fix ales, minim si sigur:
|
|
|
|
1. **`tvanz` extins** cu `in_valuta`, `id_valuta`, `nume_val` (join nou pe `nom_valute` in
|
|
`IncarcaVanzareNota`, `ofacturare_editare.prg:150-176`; `CreeazaCursorTvanzGol` la fel).
|
|
2. **`AdaugaLinieTvdDinArticol` (`omodificari.vc2:12901-12934`) converteste** pretul/discountul
|
|
calculate de dialog (RON) in valuta documentului, inainte de a le scrie in `tvd`:
|
|
`pret = pretRON * tvanz.multiplicator / tvanz.curs` (si simetric pentru `discount_unitar`) —
|
|
inversul exact al formulei din bara de totaluri, deci **no-op pe documente RON**
|
|
(`curs=multiplicator=1`, verificat neregresat pe suita existenta).
|
|
3. **`id_valuta`/`nume_val` ale liniei noi preiau valorile de pe `tvanz`** (`tvanz.id_valuta`,
|
|
`tvanz.nume_val`) in loc de `.Null.`/gol — simetric cu liniile existente, care le au populate
|
|
din `VVANZARI_ARTICOLE`.
|
|
|
|
**Limitare ramasa, de raportat explicit**: dialogul **tot lucreaza in RON** — utilizatorul introduce
|
|
pretul in RON chiar si pe un document in valuta, iar conversia se face "in spate", la scriere.
|
|
STOCAREA e acum corecta valutar (bara de totaluri calculeaza corect regardless de valuta
|
|
documentului), dar UX-ul de introducere a pretului direct in valuta nu e implementat — ar cere
|
|
atingerea `ofacturare.vc2`, in afara scope-ului primit ("nu era ceruta multi-valuta in briefing" —
|
|
decizie mostenita din sub-blocul B partea 2, `rec_s4_runda3b2.md`).
|
|
|
|
### Testat
|
|
|
|
- `test_page3_articole.prg`: **14 PASS / 2 FAIL** (identic cu baseline).
|
|
- `test_incarca_vanzare_din_nota.prg`: **5 PASS / 0 FAIL**.
|
|
- `test_adauga_linie_articol.prg` (existent, caz RON): **20 PASS / 0 FAIL** — confirma ca
|
|
conversia e no-op cand `curs=multiplicator=1`, nicio regresie pe calea deja acoperita.
|
|
- **Suita noua** `test_adauga_linie_valuta.prg`: foloseste un document real cu articole
|
|
(descoperit dinamic, nu ancorat pe `cod`), dar suprascrie manual `tvanz.curs=5.2688`,
|
|
`multiplicator=1`, `in_valuta=1`, `id_valuta=2`, `nume_val='EURO'` dupa `Show()` — nu exista in
|
|
schema un caz descoperibil simultan "cu articole" si "in valuta reala" (`id_vanzare=1037`, EURO,
|
|
are o singura linie, nefolosibila pentru un test de "adaugare langa liniile existente" fara
|
|
ambiguitate). Construieste `poArticol` cu `pretftva=1053.76` (echivalentul RON a 200 EUR la
|
|
cursul testat) si verifica: **6 PASS / 0 FAIL** —
|
|
`tvd.pret` convertit la `200.00`, `id_valuta=2`, `nume_val='EURO'`, `tvd.valoare=200.00`, iar
|
|
bara de totaluri creste cu exact `1053.76` RON (echivalentul corect, nu suma bruta).
|
|
|
|
## Cens de octeti si write-back
|
|
|
|
Baseline la inceputul sesiunii: `2 aa / 2 e3 / 2 fe`, zero `EF BF BD`. Primul `Edit` pe
|
|
`omodificari.vc2` (adaugarea `nrgbrow = 0`) a reencodat tot fisierul, stricand din nou cele doua
|
|
linii `Caption = "CTRL+F = Terminare; ESC = Renunțare; CTRL+N = Adăugare; CTRL+D = Ștergere"`
|
|
(capcana deja cunoscuta, lovita si in sesiunile precedente) — cens dupa: `6 ef / 6 bf / 6 bd`.
|
|
Reparat byte-cu-byte cu Perl (pozitional: octetul 1 din fiecare tripleta `EF BF BD` -> `0xFE`
|
|
(ț), octetul 2 -> `0xE3` (ă), octetul 3 -> `0xAA` (Ș), ciclic pe cele 2 linii x 3 caractere).
|
|
Cens final, verificat inainte si dupa `txt2vcx.ps1`: **identic cu baseline, `2 aa/2 e3/2 fe`, zero
|
|
`EF BF BD`**.
|
|
|
|
`ofacturare_editare.prg` e ASCII pur (verificat, zero octeti >0x7F) — fara risc de encoding, nu
|
|
necesita reparare.
|
|
|
|
**Fidelity-check trecut din prima incercare** (`txt2vcx.ps1 -AllowComun`, un singur fisier
|
|
regenerat) — spre deosebire de sesiunile precedente, nu a fost nevoie sa adopt textul regenerat
|
|
din `<staging>\verify\`.
|
|
|
|
## Fisiere atinse, stare write-back
|
|
|
|
| Fisier | Stare |
|
|
|---|---|
|
|
| `COMUN\clase\omodificari.vc2` | Editat (`nrgbrow=0` pe grid + `AdaugaLinieTvdDinArticol` rescrisa), write-back FACUT, fidelity check OK din prima, cens OK |
|
|
| `COMUN\clase\omodificari.vcx` / `.VCT` | Scrise, mtime sincron cu `.vc2` (16:59) |
|
|
| `COMUN\clase\omodificari.vc2.pre_fix_culoare.bak` | Backup, luat la inceputul sesiunii |
|
|
| `COMUN\programe\ofacturare_editare.prg` | Editat (`CreeazaCursorTvanzGol` + `IncarcaVanzareNota` extinse cu valuta documentului, antet rescris), ASCII pur |
|
|
| `COMUN\programe\ofacturare_editare.prg.pre_fix_culoare.bak` | Backup, luat la inceputul sesiunii |
|
|
| `COMUN\utile\Teste\editare_factura\test_adauga_linie_valuta.prg` | Nou, testat, 6/6 PASS |
|
|
| `COMUN\utile\Teste\editare_factura\test_ui_culoare_contrast.prg` | Nou, testat, captura + esantionare pixeli |
|
|
| `COMUN\utile\Teste\editare_factura\screenshots_after_fix_culoare\` | Nou — 2 capturi, dovada pe pixeli |
|
|
| `COMUN\utile\Teste\editare_factura\screenshots_before_fix_culoare\` | Capturile "before" din sesiunea anterioara, mutate din `screenshots\` ca sa nu se piarda |
|
|
| `docs\diff_s4_fix_culoare_valuta.patch` | Nou — `omodificari.vc2` |
|
|
| `docs\diff_s4_fix_culoare_valuta_ofacturare_editare.patch` | Nou — `ofacturare_editare.prg` |
|
|
| `docs\progres.md` | Actualizat |
|
|
|
|
**Fara commit** — asteapta review, conform regulii.
|
|
|
|
## Ce NU e acoperit
|
|
|
|
1. **Dialogul `frm_articol_factura` tot lucreaza in RON** — utilizatorul introduce pretul in RON
|
|
chiar si pe un document in valuta; conversia se aplica la scriere, nu la intrare. A schimba
|
|
asta ar cere atingerea `ofacturare.vc2` (`poDate.in_valuta=1` + `id_valuta`/`zi_curs`
|
|
populate), in afara proprietatii/scope-ului acestei livrari.
|
|
2. **`Show(1)` (dialogul modal chiar deschis)** — netestat automat (netestabil headless), ca in
|
|
sesiunile precedente; acoperit doar prin analiza de cod si testare manuala recomandata.
|
|
3. **Editarea unei linii existente prin acelasi dialog** (dublu-clic) — ramane nefacuta, in afara
|
|
scope-ului primit in aceasta sesiune.
|
|
4. **Decizia de arhitectura despre `_grd_base.vc2`**: fixul defectului 1 s-a facut fara sa ating
|
|
`_grd_base.vc2` (clasa comuna) — `nrgbrow` era deja o proprietate expusa pentru exact acest caz,
|
|
nu a fost nevoie de nicio modificare acolo.
|