Files
roafacturare/docs/cercetare/rec_s5_grid_articole.md
Marius Mutu d9f5ca4226 docs: planurile, proiectarile si rapoartele de lucru intra in versionare
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
2026-08-11 22:17:17 +03:00

7.8 KiB

S5 — grid PAGE3: coloana pret_achizitie si editabilitate per rand

Implementare in COMUN\clase\omodificari.vc2, clasa frm_modific2024 (singura clasa afectata din fisier — fisierul mai contine frm_editare_set, frm_modific si frm_modific2007, cu metode inainte_de_do_termin byte-identice intre frm_modific (:5004) si frm_modific2007; scrierea a fost restransa explicit la sufixul de dupa DEFINE CLASS frm_modific2024 ca sa nu atinga duplicatele mai vechi).

A. Sincronizare cursor tvd (ramura ROACONT/ROAGEST)

frm_modific2024.Load (:14554-14591 inainte de editare) are un CREATE CURSOR tvd duplicat literal, folosit cand ofacturare_editare.prg nu e incarcat in SET("PROCEDURE"). I s-au adaugat id_vanzare_set I NULL, pret_achizitie N(14,4) NULL intre sters si denumire, identic ca pozitie si tip cu CreeazaCursorArticoleGol (COMUN\programe\ofacturare_editare.prg:273-276).

B. Coloana noua pret_achizitie in grdArticoleFactura

  • inserata ca Column7 (dupa coloana de pret, Column6), cu renumerotarea Column7..14 -> Column8..15 — gridurile VFP nu au ColumnOrder implicit setat in acest fisier (ordinea vizuala = ordinea numerica a Column<N>), deci pastrarea conventiei existente a insemnat renumerotare, nu introducerea unei proprietati noi;
  • ControlSource = "tvd.pret_achizitie", Format/InputMask copiate de la Column6 (pret, get_mask(12,gnPPRET)), Width = 90 (comparabil cu discount unitar), eticheta „Pret achizitie” (fara diacritice, ca sa evite riscul de corupere cp1250 pe siruri noi);
  • ColumnCount 14 -> 15; blocurile ADD OBJECT pentru Header1/Text1 inserate in pozitia alfabetica corecta (dupa cLotArt, inainte de cPretArt — cPretAchizitieArt < cPretArt alfabetic, verificat impotriva ordinii reale din fisier, nu presupus).

C. Editabilitate per rand (nu per coloana)

ReadOnly a ramas .F. la nivel de coloana pentru cantitate/pret/pret_cu_tva/ pret_achizitie (ca si azi) — gating-ul e mutat in metodele When ale controalelor din coloana, singurul punct din care VFP decide daca celula primeste focus:

  • cCantitateArt.Text1.When, cPretArt.Text1.When: adaugat IF Nvl(tvd.id_vanzare_set,0)<>0 RETURN .F. ENDIF inaintea liniei existente (Thisform.oldvalue = This.Value), fara alta modificare de comportament pe liniile normale;
  • cPretCuTvaArt._checkbox1 nu avea When — s-a adaugat unul nou, RETURN Nvl(tvd.id_vanzare_set,0) = 0;
  • cPretAchizitieArt.Text1.When (nou): editabil doar cand id_vanzare_set = 0 AND id_vanzare_det = 0 (linie noua, nu componenta de set).

Marcaj vizual: DynamicForeColor extins pe toate cele 15 coloane (era pe toate cele 14), IIF(tvd.sters=1,RGB(150,150,150),IIF(NVL(tvd.id_vanzare_set,0)<>0,RGB(0,70,153),RGB(0,0,0))) — gri pentru sters (neschimbat), albastru RGB(0,70,153) nou pentru linie de set, negru normal in rest. nrgbrow = 0 pe ADD OBJECT-ul gridului nu a fost atins.

D. Validari noi in inainte_de_do_termin

Inserate inaintea lui RETURN m.llRet, gardate pe "OFACTURARE_EDITARE" $ Upper(Set("Procedure")) AND Used('tvd'). Pe liniile active (Nvl(sters,0)<>1, parcurse cu un singur SCAN): cantitate<=0 si pret NULL si id_articol nul/0 blocheaza salvarea (RETURN .F., mesaj cu numele liniei din denumire); linie noua cu pret_achizitie 0/NULL cere confirmare Da/Nu (tiparul amessagebox(...,4+32,...) deja folosit in metoda, la <>6 = anulare); zero linii active cu documentul avand rand in tvanz (semnalul din rec_s5_cale_scriere_vfp.md 2.5, Used('tvanz') AND Reccount('tvanz')=1) cere aceeasi confirmare. Workarea de dinainte de validare se salveaza in lnAreaTvd si se restaureaza pe toate iesirile.

Runda 2 — corectii din code-review obligatoriu pe diff

  • AdaugaLinieTvdDinArticol nu copia pret_achizitie. Linia noua adaugata prin dialogul frm_articol_factura (cmdAdaugaArticol.Click -> CreeazaPoArticolNouTvd, ofacturare_editare.prg:379) primeste poArticol.pret_achizitie ca proprietate, dar REPLACE-ul care creeaza randul in tvd nu o citea — coloana noua ramanea goala pe orice linie noua, desi valoarea putea fi deja disponibila. Corectat: pret_achizitie WITH Nvl(toArticol.pret_achizitie,0) adaugat in acelasi REPLACE. id_vanzare_set nu are nevoie de valoare explicita — Nvl(id_vanzare_set,0) pe camp NULL dupa APPEND BLANK evalueaza deja corect la 0.
  • Recno('tvd') nu se restaura la iesire timpurie din validari. SELECT (m.lnAreaTvd) restaura doar workarea apelantului, nu si pozitia in tvd insusi. Corectat: lnRecnoTvd = Recno('tvd') salvat inainte de SCAN, restaurat cu GO (m.lnRecnoTvd) IN tvd pe toate cele 5 iesiri (4x RETURN .F. + finalul cu succes).
  • Isnull(pret_achizitie) OR Nvl(pret_achizitie,0)=0 era redundant — Nvl transforma deja NULL in 0, deci a doua conditie il acopera pe primul. Simplificat la o singura conditie.
  • Analizat, nu schimbat: garda "OFACTURARE_EDITARE" $ Upper(Set("Procedure")) AND Used('tvd') se reduce practic la "sunt in ROAFACTURARE", pentru ca tvd exista mereu dupa Load(). Nu s-a extins gardarea: tvd are randuri active doar cand exista un match real cu VANZARI (deci randurile pornesc valide, din Oracle), iar confirmarea pe "zero linii active" e ea insasi gardata separat pe Used('tvanz') AND Reccount('tvanz')=1 — riscul practic de blocare pe un ecran neasociat unei vanzari e deja redus de aceasta a doua conditie.
  • Neschimbate, evaluate ca stil existent, nu bug: DynamicForeColor repetat identic pe cele 15 coloane, verificarea id_vanzare_set duplicata in 4 handlere When separate, cPretAchizitieArt.Text1 fara Valid (nu are nevoie — nu alimenteaza calculeaza_valori_articol, iar lmodificat nu e citit pe calea liniilor noi la salvare).

Runda 3 — inconsecventa latenta semnalata de al doilea review (docs\review_s5_grid_articole.md)

Avertismentul de pret_achizitie = 0/NULL la salvare (inainte_de_do_termin) exempteaza doar Nvl(id_vanzare_det,0) = 0 (linie noua). Garda de editare cPretAchizitieArt.Text1.When (omodificari.vc2, cauta PROCEDURE ...cPretAchizitieArt.Text1.When) exempteaza in plus Nvl(id_vanzare_set,0) <> 0 — adica, daca ar exista vreodata o linie cu id_vanzare_det = 0 AND id_vanzare_set <> 0 (linie noua care apartine deja unui set), campul ar fi needitabil in grid, dar avertismentul tot ar aparea la fiecare salvare, fara ca userul sa poata corecta valoarea.

Neexploatabil pe codul actual: singura cale de adaugare a unei linii noi e AdaugaLinieTvdDinArticol (APPEND BLANK + REPLACE), care nu scrie niciodata id_vanzare_set — campul ramane .NULL., deci Nvl(id_vanzare_set,0) = 0 intotdeauna pe linii noi. Combinatia id_vanzare_det = 0 AND id_vanzare_set <> 0 nu se poate produce azi. Fara fix.

Conditia care ar activa-o: daca se implementeaza vreodata editarea/adaugarea de linii in seturi de articole si liniile noi rezultate primesc id_vanzare_set populat, cele doua conditii (avertismentul din inainte_de_do_termin si garda din When) trebuie aliniate in acelasi commit care aduce acea functionalitate — altfel userul ramane blocat intr-un nag fara iesire.

Ce nu s-a atins

ofacturare.vc2, ofacturare_comun.vc2, comun.vc2, ofacturare_editare.prg — nicio scriere. Helperul ScrieArticoleFacturaEditate si agatarea in cele doua puncte de intrare raman lucrarea altor loturi ale sesiunii S5.

Netestabil headless

Coloanele gridului nu se materializeaza sub -A -T (grid-coloane-nu-se-materializeaza-headless, memorie recurenta) — verificarea vizuala a coloanei noi si a marcajului de culoare cere harnessul UI existent (test_ui_grid_articole.prg sau echivalent). Validarile din inainte_de_do_termin sunt totusi testabile headless, apeland metoda direct pe o instanta cu tvd populat manual.