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
11 KiB
S7 — rotunjirea la reeditare. Rezultat
Cerinta din plan (docs\plan_06_editare_factura.md:275-280): verifica_total_document insereaza o
linie de corectie in ACT_TEMP cand totalul documentului difera de suma din note; gata cand trei
editari consecutive nu lasa trei linii de corectie.
Verdict
Nu se acumuleaza. Mecanismul e marginit prin constructie: nota activa a documentului nu poate contine niciodata mai mult decat o singura generatie de linii de corectie (cel mult 2, cate una pentru fiecare din cele doua verificari ftva/tva), indiferent de cate ori a fost editat documentul inainte. Nu e nevoie de reparatie — nu exista defect.
Dovada pe cod
Sursa: D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql (fisierul
real aplicat in baza, nu un export all_source — capcana deja platita in S5, vezi
handoff intermediar (sters)).
1. ACT_TEMP e tabela de lucru (scratch), golita automat la fiecare COMMIT/ROLLBACK.
Verificat direct din dictionar, nu presupus:
select table_name, temporary, duration from all_tables where table_name in ('ACT_TEMP','ACT');
--> ACT N (tabela persistenta)
--> ACT_TEMP Y SYS$TRANSACTION (global temporary table, DURATION = SYS$TRANSACTION)
Un GTT cu DURATION = SYS$TRANSACTION se goleste singur la finalul TRANZACTIEI curente. Decizia 38
(handoff intermediar (sters), deja testata cu scriere reala in S5) stabileste ca fiecare editare ruleaza
intr-o singura tranzactie manuala, incheiata cu COMMIT — deci ACT_TEMP porneste mereu goala
la inceputul fiecarei editari; nu poate purta randuri dintr-o editare anterioara.
2. verifica_total_document se apeleaza o singura data pe generatie, imediat dupa reconstructia
notei. cumuleaza_note_act (:14070-14107):
14078 UPDATE ACT_TEMP SET STERS = 1, TVA_INCASARE = ...
...
14092 pack_facturare.cumuleaza_note_act_temp();
14094 if pack_facturare.ntip <> pack_facturare.nTipNotaPlata then
14095 pack_facturare.verifica_total_document();
14096 end if;
cumuleaza_note_act_temp (:14109-14319) marcheaza tot ce e in ACT_TEMP (deci doar randurile
scrise in TRANZACTIA curenta, ACT_TEMP fiind goala la start) STERS=1, reconstruieste randurile
prin GROUP BY peste ele (:14215-14312) si sterge randurile pre-agregare (:14318 DELETE FROM ACT_TEMP WHERE STERS = 1). Rezultatul, inainte de verifica_total_document, e un set de randuri
agregate, cate unul pe combinatie (scd,scc,...), construit exclusiv din datele editarii
curente.
3. Corectia insereaza cel mult un rand per verificare, pe baza totalurilor abia calculate.
verifica_total_document (:16276-16690): calculeaza V_TOTFTVA_VER/V_TOTTVA_VER prin SUM
peste ACT_TEMP (fara filtrare pe cod, dar ACT_TEMP contine oricum o singura generatie — vezi
punctul 1), le compara cu pack_facturare.ntotftva/ntottva (setate mai devreme in acelasi flux)
si, la neconcordanta, insereaza UN rand nou, copiat dupa randul-ancora (scd,ascd,scc,ascc,
explicatia, etc.) cu suma = diferenta si id_act = max(id_act)+1:
16349 IF NVL(pack_facturare.ntotftva, 0) <> 0 and NVL(pack_facturare.ntotftva, 0) <> V_TOTFTVA_VER THEN
16352 pack_facturare.ndifftva := pack_facturare.ntotftva - V_TOTFTVA_VER;
16353 insert into act_temp (...) select b.id_act, ..., pack_facturare.ndifftva as suma, ...
16456 from act_temp a
16457 left join (select max(id_act) + 1 as id_act, 0 as sters from act_temp) b on a.sters = b.sters
16460 where a.id_act = V_ID_TOTFTVA;
16461 END IF;
16462 IF NVL(pack_facturare.ntottva, 0) <> 0 and NVL(pack_facturare.ntottva, 0) <> V_TOTTVA_VER THEN
-- acelasi tipar, insereaza a doua linie (verificarea de TVA)
16575 END IF;
16577 IF pack_facturare.ntip in (48, 49) AND (...) THEN
-- a treia linie, DOAR pentru tip 48/49 (nota de credit/debit) - nu e cazul facturii (tip=1)
16688 END IF;
Fiecare din cele doua/trei IF-uri e evaluat o singura data pe apel, deci maximum 2 linii de
corectie pe generatie (3 doar pentru ntip in (48,49)) — niciodata proportional cu numarul de
editari anterioare.
4. Blocul vechi e retras integral la fiecare editare, nu doar linia de corectie. OSCRIE_IN_FISIERE(2)
(sterge nota veche) + actualizeaza_vanzari marcheaza tot cod-ul vechi STERS=1 — confirmat
empiric mai jos, pe 8 generatii reale. Deci nota activa contine mereu rezultatul unei singure
generatii, cu cel mult 2 linii de corectie proprii — niciodata suma corectiilor din generatii
anterioare.
Dovada pe date, in tranzactie — trei editari consecutive
Suita noua: COMUN\utile\Teste\editare_factura\test_s7_rotunjire.prg
(log: COMUN\utile\Teste\editare_factura\test_s7_rotunjire_log.txt).
Acelasi lant real ca in S5 (OSCRIE_IN_FISIERE(2) → OSCRIE_IN_FISIERE(0) →
finalizeaza_modificare_nota → ScrieArticoleFacturaEditate), pe id_vanzare = 1049, trei treceri
consecutive, fiecare in tranzactia ei proprie, cu COMMIT — fara nicio modificare de continut
(reeditare pura, ca sa izoleze exact mecanismul verifica_total_document, nu efectele altor
modificari). Dupa fiecare COMMIT s-a citit VANZARI.cod (nou) si s-a numarat in ACT:
- randurile active (
STERS=0) pecod-ul curent; - liniile de corectie, cu semnatura exacta a INSERT-ului de mai sus: aceeasi cheie
(scd,scc,nract,dataact,explicatia), cel putin 2 randuri, sume diferite si cu diferenta mica (< 5) — nu orice pereche(scd,scc)duplicata, care poate fi legitim generata de doua linii de detaliu diferite ale documentului (vezi capcana de mai jos).
Rezultat: 6 PASS / 0 FAIL.
| Trecere | cod inainte -> dupa |
randuri active ACT |
linii de corectie |
|---|---|---|---|
| 1 | 1140903 -> 1140904 | 10 | 0 |
| 2 | 1140904 -> 1140905 | 10 | 0 |
| 3 | 1140905 -> 1140906 | 10 | 0 |
Totalurile documentului au ramas neschimbate (747.96 / 157.06 / 905.02), confirmand ca cele trei
treceri au fost reeditari pure, fara alta variabila.
Limitare, consemnata explicit: pe compozitia acestui document, verifica_total_document nu
declanseaza NICIODATA neconcordanta (ntotftva = V_TOTFTVA_VER exact, la toate cele 8 generatii
verificate — vezi mai jos). Cifra 0/0/0 arata ca randurile nu cresc, dar „zero cazuri in date nu
e dovada" — nu demonstreaza prin ea insasi ca, DACA s-ar declansa, corectiile nu s-ar acumula.
Pentru asta raspunsul vine din cod (sectiunea de mai sus) si din exemplul real de mai jos.
Capcana prinsa in propria masuratoare — semnatura gresita la prima incercare
Prima versiune a interogarii de numarare (fara filtrul de diferenta mica) a gasit „3 linii de
corectie" la fiecare trecere — fals pozitiv. Documentul are legitim doua linii de detaliu active
(det=1581, det=1583) care genereaza fiecare propriile perechi (371,378)/(378,371)/(4111,4428)
in notă — duplicat structural normal, cu diferente mari intre sume (ex. 126.04, 57.48), nu
diferente de rotunjire. Corectat cu filtrul abs(max(suma)-min(suma)) < 5 AND max(suma) <> min(suma)
(interogare separata, sqlplus, verificat pe cod 1140900-1140903 dupa corectie: 0 randuri la toate
patru) inainte de rularea finala (mai sus). NumaraCorectii din test_s7_rotunjire.prg are acum
filtrul corect.
Confirmare independenta: mecanismul chiar functioneaza in productie
Cautare in ACT (an=2026), dupa semnatura exacta a corectiei — cauta orice caz real, nu doar pe
documentul de test:
select cod, scd, scc, nract, dataact, count(*) nr, min(suma) smin, max(suma) smax
from act where an=2026 and sters=0 and id_fact is not null
group by cod, scd, scc, nract, dataact, explicatia
having count(*) = 2 and min(suma) <> max(suma) and abs(max(suma)-min(suma)) < 5;
Gasit: cod=1140709 (id_fact=8008816, an=2026 luna=3) — id_act=122905 (scd=4428, scc=401, suma=150) si id_act=122906 (acelasi scd/scc/nract/dataact, suma=150.02, diferenta 0.02).
Corespunde exact tiparului INSERT-ului: id_act cel mai mare = max(id_act)+1, restul coloanelor
copiate de pe randul-ancora, suma = diferenta de rotunjire. Acest document nu a fost editat
niciodata dupa (o singura valoare cod), deci nu arata direct comportamentul la editari repetate —
dar confirma pe date reale ca mecanismul chiar insereaza, si insereaza exact un rand cand se
declanseaza, in acord cu structura codului (un INSERT per IF).
Istoricul complet al documentului de test — randurile nu cresc
id_vanzare=1049 / id_fact=8009659 a fost editat de 8 ori pana acum (S5 + acest test), fiecare
generatie verificata in ACT:
cod |
randuri active la generare | linii de corectie |
|---|---|---|
| 1140887 | 10 | 0 |
| 1140896 | 10 | 0 |
| 1140897 | 10 | 0 |
| 1140898 | 10 | 0 |
| 1140900 | 10 | 0 |
| 1140904 | 10 | 0 |
| 1140905 | 10 | 0 |
| 1140906 (curent) | 10 | 0 |
Numarul de randuri e identic la fiecare generatie — regenerare completa, nu acumulare incrementala, consistent cu punctul 4 din dovada pe cod (blocul vechi se retrage integral).
Ce NU acopera cercetarea
- Niciun caz gasit in productie unde corectia se declanseaza PE UN DOCUMENT editat de mai multe
ori — cautarea (an=2026, semnatura stricta) a gasit un singur exemplu real, pe un document editat
o singura data. N-a fost fortata o neconcordanta artificiala pe
id_vanzare=1049(ar fi cerut modificarea logicii de calcul a notei,scrie_nota, cateva mii de linii, in afara bugetului acestei cercetari) si nici o cautare exhaustiva pe alti ani/luni. - Ramura
ntip in (48,49)(a treia linie de corectie,:16577-16688) — nu se aplica facturii de test (tip=1), neexercitata. PACK_CONTAFIN(flux-ul care muta randurile dinACT_TEMPinACTpersistenta) a fost citit doar punctual (INITIALIZEAZA_SCRIERE_ACT_RUL), viaALL_SOURCE(read-only,sqlplus) — nu integral; concluzia despre golirea luiACT_TEMPse bazeaza pe metadataALL_TABLES.DURATION(autoritara), nu pe citirea completa a fluxului de flush.
Date de test consumate
Continuare pe id_vanzare = 1049 (deja in lucru din S5, handoff intermediar (sters)):
cod realocat suplimentar 1140900 -> 1140901 -> 1140902 -> 1140903 (prima rulare, cu interogarea
de numarare gresita — pastrata doar ca generatie reala, nu s-a revenit peste ea) -> 1140904 ->
1140905 -> 1140906 (rularea finala, cea raportata mai sus). Cod curent: 1140906. Niciun
det schimbat sau sters suplimentar fata de S5 (toate cele trei treceri au fost reeditari pure);
totalurile documentului raman 747.96 / 157.06 / 905.02, identice cu starea de la finalul S5.
id_vanzare = 1050 si 1037 — neatinse.
Fisiere atinse
Un singur fisier nou, in COMUN (necomis): COMUN\utile\Teste\editare_factura\test_s7_rotunjire.prg
- logul
test_s7_rotunjire_log.txt. Niciun fisier de productie (.vc2/.sc2/.prgde aplicatie), niciun script de migrare. Zero commit git/SVN.
Stare finala — verificata, nu presupusa
- Tranzactii Oracle deschise: 0 (
v$transactionjoinv$sessionpeMARIUSM_AUTO). - Procese
vfp9.exeramase: 0 (tasklist). - Documentul de test:
id_vanzare=1049,cod=1140906,sters=0, totaluri neschimbate.