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
9.4 KiB
S4 runda 2 (PAGE3 "Articole factura") - view VVANZARI_ARTICOLE, pozitionare in tact, garda ROACONT/ROAGEST
Runda 2 pe fisierele deja livrate in runda 1 (docs\diff_s4_runda1_page3.patch, netrimis inca la
commit). Diff: docs\diff_s4_runda2_view_pozitionare.patch (COMUN\programe\ofacturare_editare.prg
COMUN\clase\omodificari.vc2, clasafrm_modific2024). Fara commit.
Ce s-a schimbat
IncarcaArticoleFacturatrece pe view-ul OracleVVANZARI_ARTICOLE(creat si validat separat, scriptff_2026_08_08_01_COMUN_VVANZARI_ARTICOLE.sql,versiune_db.txtbumpat):select * from vvanzari_articole where id_vanzare = <n> and sters = 0 order by id_vanzare_det, in loc de lista de 20 de coloane + join pe 4 tabele. Coloana nouaid_vanzare(era doar inWHERE, acum si inSELECT).- Pozitionarea in
tact-IncarcaVanzareDinNota(tcAliasAct), functie noua: incearca toate combinatiile distincte(nract, serie_act, dataact)din alias (sters=0) pana gaseste un rand inVANZARI, in loc deGo Top In tactorb. Repara blocantul documentat inrec_gotop_tact_s4.md/rec_review_ancorare_s4.md: pe notele unde primul rand e o INCASARE,Go Topciteanract/serie_act/dataactde pe randul gresit si PAGE3 lipsea silentios. Salveaza/restaureaza workarea (Select()) siRecno()pe alias - fara requery intre timp, restaurarea e sigura.IncarcaVanzareNotaisi pastreaza contractul (4 scalari), refolosita neschimbata ca functie de interogare pe un singur triplet. - Garda ROACONT/ROAGEST -
"OFACTURARE_EDITARE" $ Upper(Set("Procedure"))inainte de blocul PAGE3 dinShow()si inLoad(). Verificat headless (test_set_procedure.prg) caSET("PROCEDURE")intoarce lista COMPLETA a fisierelor incarcate prinADDITIVEsuccesive (nu doar ultimul), deci garda ramane corecta indiferent cate alteSET PROCEDUREurmeaza dupaofacturare_editare.prgin secventa de start. Fara garda,frm_modific2024(folosit si de ROACONT/ROAGEST) ar fi apelat functii inexistente acolo si ar fi rupt "registru jurnal > modificare" in ambele produse. Pe guard-fail:PageCount = 2, fara eroare, fara mesaj.roacont.prg/roagest.prgNU au fost atinse (decizie cross-proiect, semnalata separat). AMESSAGEBOXpe caile de eroare Oracle dinIncarcaVanzareNota/IncarcaArticoleFactura(goExecutor.cEroare, acelasi tipar caIncarcaCursoareModificareNota) - o coloana stearsa/redenumita in schema devine semnal vizibil, nu cursor gol tacut.- O singura structura pentru cursorul gol:
CreeazaCursorTvdGol()(21 campuri,id_vanzarenou) apelata din fallback-ul de eroare si dinLoad()cand garda trece;CreeazaCursorTvanzGol()analog pentrutvanz.Load()pastreaza un fallback inline separat (20 campuri, nemodificat) pentru cazul in care garda NU trece (ROACONT/ROAGEST) -ofacturare_editare.prgnefiind incarcat acolo, functia comuna nu exista, deci placeholder-ul trebuie sa ramana literal in.vc2. E singura duplicare ramasa, inerenta constrangerii, nu scapata din vedere.
Corectii aplicate dupa livrarea initiala (runda 2b)
Team-lead a aplicat direct 2 corectii mici in ofacturare_editare.prg (sub 5 linii), plus o corectie
suplimentara gasita si aplicata de mine cand am adaugat testul cerut la punctul 2:
codinSELECT DISTINCT, nu de pe randul curent. Varianta initiala citeaEvaluate(tcAliasAct + '.cod')de pe randul curent altactinainte de bucla.Show()cheamaThis.CalculeazaTotal()chiar inainte de blocul PAGE3, iar aceea poate lasatactla EOF (nu restaureaza pozitia daca era deja EOF). La EOF,codcitit asa iese gol -> exact clasa de bug pe care runda asta o repara. Acumcodintra si el inSELECT DISTINCT cod, nract, serie_act, dataact FROM (tcAliasAct) WHERE sters=0si se citeste din cursorul de triplete, nu de pe pozitia curenta a apelantului.- Fisierul era LF-only (0 CR / 296 LF), mostenit din runda 1, nu din runda 2 - convertit la CRLF
(acum 302 CR / 302 LF dupa fixul de mai jos, zero LF izolat, zero octeti non-ASCII), consistent cu
restul
.prg-urilor dinCOMUN\programe. - Gasit de mine la testul cerut la punctul 2 de mai jos: restaurarea pozitiei pe
tactla iesirea dinIncarcaVanzareDinNotafaceaGo (lnRecnoOrigine) In (tcAliasAct)necondiționat - daca pozitia initiala era chiar EOF,Recno()intoarceReccount()+1, iarGOla acel numar pica cu eroarea VFP 5 "Record is out of range" (capturata deON ERROR, dar restaurarea nu se mai facea - risc real, latent din prima versiune, nu introdus de corectiile 1-2). Fix:GOdoar dacalnRecnoOriginee in intervalul valid; altfelGo Bottom+Skip(restaureaza tot la EOF).
Rezultat suita (dupa corectiile de mai sus)
COMUN\utile\Teste\editare_factura\test_page3_articole.prg, sub
watchdog_vfp.ps1 -AutoDismiss: exit 0, 0 dialoguri, 10/10 PASS (7 din runda 1 + 3 noi):
cod=1137874(an=2009,luna=8) ->id_vanzare=506- blocantul din runda 2, azi cuGo Toporb ar fi dat 0 randuri;cod=1139934(an=2021,luna=12) ->id_vanzare=882- coliziuneVANZARI.COD+ Go Top orb, cazul cel mai riscant (ambele probleme suprapuse);- garda ROACONT/ROAGEST: cu
ofacturare_editare.prgscos dinSET PROCEDURE(lista reconstruita fara el, restul procedurilor pastrate) -PageCountramane 2, fara eroare.
test_incarca_vanzare_din_nota.prg (izolat, direct pe functii): exit 0, 0 dialoguri, 5/5 PASS
(4 din livrarea initiala + 1 nou, cazul EOF cerut de team-lead: tact pozitionat deliberat la EOF
Go Bottom + Skip inainte de apel, verifica id_vanzare=506 gasit corect si Eof(tact) ramas
.T. dupa apel - proba directa ca fixul de la punctul 1 si de la punctul 3 chiar functioneaza
impreuna). Neschimbate si nerulate din nou (nu au fost atinse de corectii):
test_incarca_articole_view.prg (3/3 PASS la livrarea initiala), test_set_procedure.prg.
Write-back .vc2 -> .vcx/.vct: txt2vcx.ps1 -AllowComun, fidelity check OK (nu s-a mai atins
.vc2 in runda 2b - corectiile sunt strict in .prg).
Ce NU e acoperit
- Calea de eroare Oracle propriu-zisa (
lnSucces < 0) dinIncarcaVanzareNota/IncarcaArticoleFactura- netestabila fara sa rupi deliberat conexiunea; verificata doar static, pe simetrie cu
IncarcaCursoareModificareNota(acelasi tipar, deja in productie).
- netestabila fara sa rupi deliberat conexiunea; verificata doar static, pe simetrie cu
- Cursorul
tvdgol pe calea de eroare reala (doarCreeazaCursorTvdGol()testat direct, nu prin declansarea efectiva a unei erori SQL). - Fluxul UI complet (utilizator care deschide efectiv
frm_modific2024din formular, nu din test) - neschimbat fata de runda 1, ramane netestat prin UI real.
Abateri de la briefing
Niciuna in scop; o adaugare: testul garda ROACONT/ROAGEST foloseste reconstructia listei
SET(PROCEDURE) (capturare + SET PROCEDURE TO fara argumente + redeschidere ADDITIVE a restului),
nu RELEASE PROCEDURE <fisier> (comanda nu exista in VFP pentru un singur fisier din lista) - metoda
verificata sa pastreze toate celelalte proceduri incarcate de care Show() are nevoie.
Runda 2, inchidere (08.08.2026, predare de la s4-runda2)
Trei sarcini mici, preluate cand omodificari.vc2 avea deja textul rundei 2 editat dar
write-back-ul nu era facut (.vc2 mai nou decat .vcx):
- Marcaje
*!* DD.MM.YYYY autor - ...deasupra celor doua blocuri din runda 2 (omodificari.vc2:14076inLoad(),:14172inShow()) - textul era deja scris, doar write-back-ul lipsea. - Comentariu pe ramura
ELSEdinLoad()(omodificari.vc2:14081) - explica de ceCREATE CURSOR tvdse repeta identic acolo (ROACONT/ROAGEST nu incarcaofacturare_editare.prg, deciCreeazaCursorTvdGol()nu exista pe acele produse) - deja scris odata cu punctul 1. ROACONT\Programe\roacont.prg:212:SET PROCEDURE TO ofacturare_editare.prg ADDITIVE, inserata langaofacturare_comun.prg/oproceduri_facturare.prg(grupul de facturare), convenind cu stilul local (majuscule, spatiu final). Deblocheaza PAGE3 pe ROACONT (decizia 5 dinprogres.md), garda ramane activa pentru ROAGEST (neatins, inca in discutie).
Write-back .vc2 -> .vcx/.vct: txt2vcx.ps1 -AllowComun, fidelity check OK. Suita re-rulata
dupa write-back, sub watchdog_vfp.ps1 -AutoDismiss: test_page3_articole.prg 10/10 PASS,
test_incarca_vanzare_din_nota.prg 5/5 PASS, ambele exit 0 si 0 dialoguri. roacont.prg
verificat byte-cu-byte: CR/LF simetrice (1221->1222, +1 linie), octetul non-ASCII unic pastrat
neatins (0xA9), fara scriere prin Edit/Write (doar [IO.File]::ReadAllText/WriteAllText cu
codepage 1252). Fara commit git/SVN pe niciunul din cele doua proiecte.
Acceptat constient: un roundtrip Oracle per triplet in IncarcaVanzareDinNota
IncarcaVanzareDinNota incearca tripletele distincte (nract, serie_act, dataact) din tact
pe rand, cate un apel IncarcaVanzareNota (deci un roundtrip Oracle) per triplet, pana gaseste un
rand in VANZARI. Masurat pe toate cele 419 note legate de VANZARI (decizia 27,
progres.md): maxim 2 triplete per nota, medie 1.17 pe toata multimea. Nu se comaseaza
intr-un singur SQL cu OR pe toate tripletele: ar complica interogarea (listă variabila de
OR-uri) si ar schimba contractul lui IncarcaVanzareNota, care ramane o functie de interogare pe
un singur triplet, refolosibila neschimbata si in alte cai. Cu maxim 2 roundtrip-uri pe cazul
cel mai rau, costul e neglijabil fata de complexitatea adaugata.