Files
roafacturare/docs/cercetare/rec_s4_runda2.md
Marius Mutu b5a7108f34 docs: cercetarile comune trec in COMUN, reziduul #6 dispare, progres.md la zi
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
2026-08-11 22:31:42 +03:00

9.3 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 (diff aplicat (sters), netrimis inca la commit). Diff: diff aplicat (sters) (COMUN\programe\ofacturare_editare.prg

  • COMUN\clase\omodificari.vc2, clasa frm_modific2024). Fara commit.

Ce s-a schimbat

  1. IncarcaArticoleFactura trece pe view-ul Oracle VVANZARI_ARTICOLE (creat si validat separat, script ff_2026_08_08_01_COMUN_VVANZARI_ARTICOLE.sql, versiune_db.txt bumpat): 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 noua id_vanzare (era doar in WHERE, acum si in SELECT).
  2. Pozitionarea in tact - IncarcaVanzareDinNota(tcAliasAct), functie noua: incearca toate combinatiile distincte (nract, serie_act, dataact) din alias (sters=0) pana gaseste un rand in VANZARI, in loc de Go Top In tact orb. Repara blocantul documentat in rec_gotop_tact_s4.md/rec_review_ancorare_s4.md: pe notele unde primul rand e o INCASARE, Go Top citea nract/serie_act/dataact de pe randul gresit si PAGE3 lipsea silentios. Salveaza/restaureaza workarea (Select()) si Recno() pe alias - fara requery intre timp, restaurarea e sigura. IncarcaVanzareNota isi pastreaza contractul (4 scalari), refolosita neschimbata ca functie de interogare pe un singur triplet.
  3. Garda ROACONT/ROAGEST - "OFACTURARE_EDITARE" $ Upper(Set("Procedure")) inainte de blocul PAGE3 din Show() si in Load(). Verificat headless (test_set_procedure.prg) ca SET("PROCEDURE") intoarce lista COMPLETA a fisierelor incarcate prin ADDITIVE succesive (nu doar ultimul), deci garda ramane corecta indiferent cate alte SET PROCEDURE urmeaza dupa ofacturare_editare.prg in 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.prg NU au fost atinse (decizie cross-proiect, semnalata separat).
  4. AMESSAGEBOX pe caile de eroare Oracle din IncarcaVanzareNota/IncarcaArticoleFactura (goExecutor.cEroare, acelasi tipar ca IncarcaCursoareModificareNota) - o coloana stearsa/redenumita in schema devine semnal vizibil, nu cursor gol tacut.
  5. O singura structura pentru cursorul gol: CreeazaCursorTvdGol() (21 campuri, id_vanzare nou) apelata din fallback-ul de eroare si din Load() cand garda trece; CreeazaCursorTvanzGol() analog pentru tvanz. Load() pastreaza un fallback inline separat (20 campuri, nemodificat) pentru cazul in care garda NU trece (ROACONT/ROAGEST) - ofacturare_editare.prg nefiind 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:

  1. cod in SELECT DISTINCT, nu de pe randul curent. Varianta initiala citea Evaluate(tcAliasAct + '.cod') de pe randul curent al tact inainte de bucla. Show() cheama This.CalculeazaTotal() chiar inainte de blocul PAGE3, iar aceea poate lasa tact la EOF (nu restaureaza pozitia daca era deja EOF). La EOF, cod citit asa iese gol -> exact clasa de bug pe care runda asta o repara. Acum cod intra si el in SELECT DISTINCT cod, nract, serie_act, dataact FROM (tcAliasAct) WHERE sters=0 si se citeste din cursorul de triplete, nu de pe pozitia curenta a apelantului.
  2. 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 din COMUN\programe.
  3. Gasit de mine la testul cerut la punctul 2 de mai jos: restaurarea pozitiei pe tact la iesirea din IncarcaVanzareDinNota facea Go (lnRecnoOrigine) In (tcAliasAct) necondiționat - daca pozitia initiala era chiar EOF, Recno() intoarce Reccount()+1, iar GO la acel numar pica cu eroarea VFP 5 "Record is out of range" (capturata de ON ERROR, dar restaurarea nu se mai facea - risc real, latent din prima versiune, nu introdus de corectiile 1-2). Fix: GO doar daca lnRecnoOrigine e in intervalul valid; altfel Go 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 cu Go Top orb ar fi dat 0 randuri;
  • cod=1139934 (an=2021,luna=12) -> id_vanzare=882 - coliziune VANZARI.COD + Go Top orb, cazul cel mai riscant (ambele probleme suprapuse);
  • garda ROACONT/ROAGEST: cu ofacturare_editare.prg scos din SET PROCEDURE (lista reconstruita fara el, restul procedurilor pastrate) - PageCount ramane 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) din IncarcaVanzareNota/IncarcaArticoleFactura
    • netestabila fara sa rupi deliberat conexiunea; verificata doar static, pe simetrie cu IncarcaCursoareModificareNota (acelasi tipar, deja in productie).
  • Cursorul tvd gol pe calea de eroare reala (doar CreeazaCursorTvdGol() testat direct, nu prin declansarea efectiva a unei erori SQL).
  • Fluxul UI complet (utilizator care deschide efectiv frm_modific2024 din 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):

  1. Marcaje *!* DD.MM.YYYY autor - ... deasupra celor doua blocuri din runda 2 (omodificari.vc2:14076 in Load(), :14172 in Show()) - textul era deja scris, doar write-back-ul lipsea.
  2. Comentariu pe ramura ELSE din Load() (omodificari.vc2:14081) - explica de ce CREATE CURSOR tvd se repeta identic acolo (ROACONT/ROAGEST nu incarca ofacturare_editare.prg, deci CreeazaCursorTvdGol() nu exista pe acele produse) - deja scris odata cu punctul 1.
  3. ROACONT\Programe\roacont.prg:212: SET PROCEDURE TO ofacturare_editare.prg ADDITIVE , inserata langa ofacturare_comun.prg/oproceduri_facturare.prg (grupul de facturare), convenind cu stilul local (majuscule, spatiu final). Deblocheaza PAGE3 pe ROACONT (decizia 5 din progres.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.