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
14 KiB
Propunere S4b — actiunea explicita de sincronizare RUL <-> articole factura
Document de proiectare, nu implementare. Niciun .vc2/.prg nu a fost modificat. Cerinta
sursa: docs\plan_06_editare_factura.md:208-231. Context: handoff intermediar (sters)
(sectiunea „S4b — ce e facut si ce lipseste"), handoff intermediar (sters).
Corectie fata de predarea anterioara — nu e nevoie de cursor de instantaneu
docs\cercetare\rec_s5_cale_scriere_vfp.md 2.3 propunea un cursor tvd_initial, luat imediat
dupa IncarcaArticoleFactura, ca solutie la blocajul „tvd nu pastreaza valorile de dinainte de
editare". Verificat pe cod si pe plan: acea propunere rezolva o alta problema — istoricul
editarilor utilizatorului in aceeasi sesiune (cat a schimbat el insusi o cantitate) — nu ce cere
literal S4b.
Planul spune explicit: „preturile si cantitatile din rulaje si cele din articolele
facturii se pot desincroniza la editare" (plan_06_editare_factura.md:209-210) — deci
comparatia ceruta e intre trul (rulaje) si tvd (articole), doua reprezentari independente
ale aceluiasi document, editabile separat in acelasi formular (PAGE1 vs PAGE3). Nu e nevoie de
niciun instantaneu: „vechi" = valoarea curenta din cursorul-tinta (ce s-ar salva daca
utilizatorul apasa Salveaza acum, fara sincronizare), „nou" = valoarea calculata din cursorul-
sursa. Ambele cursoare sunt deja rezidente si populate cand utilizatorul ajunge pe PAGE3 —
comparatia se face live, nu din istoric.
Confirmare suplimentara ca ACT/tact nu poate fi parte a acestei comparatii (desi indicatorul
existent ActualizeazaVerdictActRul compara ACT cu RUL): tact e un jurnal de postari
debit/credit (scd/scc/suma), fara cantitate/pret/id_articol per linie de marfa —
structural nu poate fi sursa sau tinta a unei sincronizari „cantitate/pret". Sincronizarea din
S4b ramane exclusiv RUL <-> articole, distincta de indicatorul de verdict deja livrat.
1. Unde traieste actiunea
Buton nou cmdSincronizeazaArticole, in randul de butoane din PAGE3, langa cele existente:
COMUN\clase\omodificari.vc2:12291-12305 ADD OBJECT 'pgfArticole.PAGE3.cmdAdaugaArticol' ... Left=175 Width=170
COMUN\clase\omodificari.vc2:12307-12321 ADD OBJECT 'pgfArticole.PAGE3.cmdStergeArticol' ... Left=0 Width=170
Randul e la Top=0, latimea paginii e 764 (omodificari.vc2:8702); cmdAdaugaArticol se termina
la 345 — spatiul liber pana la 764 (419px) e suficient pentru un al treilea buton. Propunere:
Left=350, Top=0, Width=250, Height=22, caption „Sincronizeaza cu rulaje...". lblArticoleReadOnly
(:12776-12787, Left=360 Top=4) ocupa aceeasi zona vizual, dar e vizibila doar cand
lArticoleReadOnly=.T. — exact starea in care butonul trebuie oricum dezactivat, deci overlap-ul
nu se vede niciodata simultan (acelasi tipar folosit deja pentru celelalte doua butoane).
Toggle vizibilitate/enabled: se extinde blocul deja existent din Show():
omodificari.vc2:14811-14814
This.pgfArticole.PAGE3.cmdAdaugaArticol.Enabled = !This.lArticoleReadOnly
This.pgfArticole.PAGE3.cmdStergeArticol.Enabled = !This.lArticoleReadOnly
This.pgfArticole.PAGE3.txtDiscountArt.ReadOnly = This.lArticoleReadOnly
This.pgfArticole.PAGE3.lblArticoleReadOnly.Visible = This.lArticoleReadOnly
cu o linie This.pgfArticole.PAGE3.cmdSincronizeazaArticole.Enabled = !This.lArticoleReadOnly.
Gardare gratuita pentru ROACONT/ROAGEST: butonul exista doar in PAGE3, care la randul ei
exista doar cand This.lAreArticoleVanzari (:14792-14818, gatat deja pe
"OFACTURARE_EDITARE" $ Upper(Set("Procedure"))). Nu e nevoie de nicio garda noua — butonul
mosteneste gating-ul deja livrat in S3/S4.
2. Cum se calculeaza „vechi -> nou"
Fara FK la nivel de rand intre trul si VANZARI_DETALII/tvd — verificat direct pe schema
Oracle (DESCRIBE VRUL_TOT prin sqlplus, 09.08.2026): view-ul sursa al lui trul
(ofacturare_editare.prg:33-100, in special :74) are 218 coloane, niciuna de tip
id_vanzare_det/id_rulaj_vanzare. Singura cheie comuna e ID_ARTICOL, prezenta in ambele:
VRUL_TOT.ID_ARTICOL (confirmat pe schema) si tvd.id_articol
(ofacturare_editare.prg:274, CreeazaCursorArticoleGol). Matching-ul e deci obligatoriu la
nivel de articol (agregat), nu la nivel de linie individuala — nu exista alta optiune.
Agregarea RUL per articol refoloseste formula validata pe date reale, nu una noua:
docs\cercetare\rec_suma_act.md, sectiunea E.3, verificata exact pe doua documente (unul de test,
unul de productie, E.4/E.5):
valoare_articol_rul = SUM(cant * pretvtva) + SUM(CASE WHEN id_tip_rulaj <> 3 THEN cante * pretvtva ELSE 0 END)
cantitate_articol_rul = SUM(cant) + SUM(CASE WHEN id_tip_rulaj <> 3 THEN cante ELSE 0 END)
pret_propus = valoare_articol_rul / cantitate_articol_rul -- pret mediu ponderat, daca sunt mai multe randuri RUL pe acelasi articol
GROUP BY id_articol, filtrat sters = 0 (trul incarca deja doar randuri active,
ofacturare_editare.prg:57 cu tlAratasterse=.F. din apelantii de editare).
Articolele nestocate (in_stoc=0, rec_suma_act.md E.5/E.6) nu au niciodata randuri in RUL —
excluse automat din comparatie, afisate cu actiune „N/A — articol nestocat, fara corespondent in
rulaje" (aceeasi coloana in_stoc deja incarcata in tvd, ofacturare_editare.prg:301, folosita
azi doar pentru corectia verdictului RUL).
Liniile adaugate/sterse (cerinta explicita din plan) intra natural in acelasi matching pe
id_articol, ca diferenta de multimi:
- articol activ in sursa, absent (sau
sters=1) in tinta -> actiune Adaugare in tinta; - articol activ in tinta, absent (sau agregat 0) in sursa -> actiune Semnalare (vezi risc, punctul 6 — NU stergere automata);
- articol in ambele, cantitate/pret diferite -> actiune Modificare;
- articol in ambele, identic -> nu apare in enumerare (fara zgomot).
3. Cum alege utilizatorul directia
Dialog modal nou, frm_sincronizare_articole, in COMUN\clase\omodificari.vc2 (langa
frm_modific2024, ca sa poata referi direct cursoarele tvd/trul din acelasi data session
implicit — sectiunea 2.5 din rec_s5_cale_scriere_vfp.md). Deschis din
cmdSincronizeazaArticole.Click, modal (WindowType=1, acelasi tipar ca frm_modific2024 insusi
si ca frm_modifica_articol_factura).
Continut:
- doi radio-butoni (optiongroup): „Rulajul e sursa (actualizeaza articolele facturii)" (implicit, recomandat — vezi punctul 5) / „Articolele sunt sursa (actualizeaza rulajul)"; schimbarea selectiei recalculeaza si reafiseaza enumerarea imediat (fara buton „recalculeaza" separat);
- grid needitabil pe cursorul
propunere_sincronizare, coloane: Articol (denumire + codmat), Cantitate veche, Cantitate noua, Pret vechi, Pret nou, Actiune (Modificare/Adaugare/Semnalare/N-A), cuDynamicForeColorgri pe randurile N-A (acelasi tipar catvd.stersingrdArticoleFactura,omodificari.vc2:12344); - „Aplica" — activ doar daca exista minim o linie cu actiune Modificare sau Adaugare; „Renunta".
Dialogul citeste tvd/trul doar pentru afisare — nu le modifica pana la „Aplica". Refuzul
(„Renunta" sau inchiderea ferestrei) nu are nimic de desfacut, pentru ca nimic n-a fost atins:
satisface direct cerinta din plan („refuzul propunerii lasa datele nemodificate").
4. Ce scrie efectiv sincronizarea, si prin ce cale
Nimic in Oracle, niciodata. AplicaSincronizareArticole (nou, ofacturare_editare.prg, langa
restul helperelor pure — nu un nou punct de scriere Oracle) scrie doar in cursoarele VFP
in-memory tvd/trul, la apasarea „Aplica":
- Directia „rulajul e sursa": pentru fiecare articol cu actiune Modificare —
REPLACE tvd.cantitate, tvd.pret, tvd.pret_cu_tva WITH ..., lmodificat WITH .T., apoi recalculul luivaloarecu aceeasi formula deja folosita incalculeaza_valori_articol(omodificari.vc2:13397-13409) — refolosita, nu reimplementata — si apel laThisform.ActualizeazaBaraTotaluri()ca dupa orice editare manuala. Pentru Adaugare, se refoloseste tiparul dinAdaugaLinieTvdDinArticol(omodificari.vc2:13130+), populat cu valorile din RUL. - Directia „articolele sunt sursa": pentru fiecare articol cu match unic activ in
trul—REPLACE trul.cant, trul.pretvtva WITH ...pe randul respectiv, fara sa atingaid_tip_rulaj/conturi/scd/scc. Cand exista mai multe randuri RUL active pe acelasi articol (perechi de diferenta de pret,id_tip_rulaj=3, sau randurile „duplicat" nelamurite dinrec_suma_act.mdE.4), linia se marcheaza N-A — mai multe randuri RUL, verificati manual — nu se alege automat care rand sa fie atins.
Scrierea reala in Oracle ramane exact calea deja livrata in S5, neschimbata:
do_termin -> OSCRIE_IN_FISIERE pentru trul/tact (neatins de aceasta lucrare) +
ScrieArticoleFacturaEditate pentru tvd (ofacturare_editare.prg:469-556, comisa in S5).
Sincronizarea doar pregateste cursoarele exact cum ar face utilizatorul manual din grid —
niciun helper Oracle nou.
5. Alternative, cu recomandare
A. Granularitatea matching-ului: pe linie vs pe articol.
Pe linie — respins, nu exista nicio cheie (verificat pe schema, punctul 2). Recomandat: pe
articol (id_articol), singura cheie comuna confirmata.
B. O singura directie vs alegere intre doua.
Planul cere explicit alegerea utilizatorului (plan_06_editare_factura.md:226-227). Recomandat:
ambele directii, dar cu directia „articole -> RUL" restransa la actualizarea cantitate/pret pe
randuri RUL deja existente, niciodata la crearea de randuri noi de contabilitate (motivat la
punctul 6 — un rand RUL nou cere cont/scd/scc pe care sincronizarea nu le poate deduce
sigur din articol). Directia „RUL -> articole" nu are aceasta limitare, pentru ca tvd/
VANZARI_DETALII nu poarta conturi contabile — de aici si recomandarea ei ca implicit in dialog.
C. Dialog modal separat vs panou inline pe PAGE3.
PAGE3 n-are loc: layout-ul complet (omodificari.vc2:12780-12956) foloseste toata latimea de 764px
pe cele doua randuri de totaluri, iar randul de butoane are doar 419px liberi — insuficient pentru
un grid de propuneri cu 6 coloane. Recomandat: dialog modal separat, ca frm_modifica_articol_ factura (acelasi tipar deja folosit in acest formular).
D. Stergerea automata de linii cand sursa nu mai are articolul.
Riscant — vezi punctul 6. Recomandat: fara stergere automata, in nicio directie — doar
semnalare in enumerare; stergerea efectiva ramane pe butonul deja existent cmdStergeArticol,
actionat manual dupa ce utilizatorul a vazut divergenta.
6. Ce poate strica
- Cel mai mare risc concret: randurile RUL „duplicat" cu
id_tip_rulaj=0gasite langa perechiid_tip_rulaj=3(rec_suma_act.mdE.4, intrebarea 3 nerezolvata catre Marius) — pe un document cu asemenea randuri, agregarea per articol ar putea propune o cantitate/pret gresit(a). Atenuare: eticheta explicita pe dialog („propunere calculata, verificati inainte de aplicare"), niciodata aplicare automata sau implicita; cand exista >1 rand activ pe acelasi articol, linia se marcheaza N-A in loc sa se aleaga arbitrar (punctul 4). - Registrul jurnal ROACONT/ROAGEST: butonul si dialogul exista doar in interiorul gardei deja
existente pe PAGE3 (
lAreArticoleVanzari) — cod complet inert acolo, fara garda noua de adaugat (punctul 1). Risc zero suplimentar fata de ce e deja livrat in S3-S5. omodificari.vc2e partajat de toata suita — orice atingere in afara blocului gatat pelAreArticoleVanzari/PAGE3 (de ex. o modificare gresita inLoad()/Show()inainte de gate) ar afecta toate notele contabile editate din ROACONT/ROAGEST, nu doar facturile. Implementarea trebuie sa ramana strict in interiorul blocului PAGE3 existent, fara sa atingagrid1/tact(grid-ul comun de note, folosit de toata suita).- Directia „articole -> RUL" scrie in randuri de contabilitate (
trul) fara sa recalculeze conturile — acceptabil DOAR daca ramane strict la actualizarea cantitate/pret pe randuri deja existente (punctul 5.B), exact echivalent cu o corectie manuala facuta azi direct in grid-ul de rulaje (PAGE1) — nu introduce o cale de scriere noua sau mai permisiva decat ce exista deja.
7. Estimare de efort
| Bucata | Zile |
|---|---|
Agregare RUL per articol (formula E.3) + agregare tvd per articol, logica pura testabila headless |
0.5-1 |
ConstruiestePropunereSincronizare (matching pe id_articol, ambele directii, adaugat/modificat/semnalare) |
1 |
AplicaSincronizareArticole (mutatii in memorie pe tvd/trul, reutilizare calculeaza_valori_articol/AdaugaLinieTvdDinArticol) |
1 |
frm_sincronizare_articole (radio directie, grid needitabil, Aplica/Renunta) |
1-1.5 |
Buton + toggle pe PAGE3 (txt2vcx.ps1 pe omodificari.vc2) |
0.5 |
| Teste headless (logica pura de agregare/matching, pe cursoare construite in test, model S5) | 0.5 |
Teste UI vizibile (dialogul modal nu e testabil -A -T, la fel ca frm_articol_factura) |
0.5-1 |
| Total | ~5-6.5 zile |
Confirma caracterizarea din plan: „cea mai mare ramasa, nu blocheaza pe nimeni" (handoff intermediar (sters)).
Ce ramane deschis, de decis cu Marius inainte de implementare
- Directia implicita in dialog — recomandare: „rulajul e sursa" preselectat (punctul 5.B).
- Randurile RUL „duplicat" nelamurite (
rec_suma_act.mdE.4/F.3) — daca raman nerezolvate, orice document cu ele va produce linii N-A in loc de propunere, ceea ce e sigur dar posibil frustrant pentru utilizator pe acele documente specifice. - Daca se doreste si optiunea „aplica pe toate liniile deodata" vs selectie linie cu linie in grid — propunerea de mai sus e „aplica tot ce nu e N-A", cea mai simpla; o selectie fina ar adauga complexitate UI fara sa fie ceruta explicit de plan.