28 KiB
S10 — Se re-deriva valorile liniei pe calea de REEMITERE?
Stare: TERMINAT.
Surse:
D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql(17217 linii;versiune_db.txt=2026_08_09_02) — prescurtatPF:<linie>;- corpul viu din
all_source(MARIUSM_AUTO.PACK_FACTURARE,PACKAGE BODY, VALID,last_ddl_time = 2026-08-09 20:03:50) — prescurtatLIVE:<linie>; COMUN\clase\ofacturare.vc2,COMUN\programe\ofacturare_editare.prg.
Exportul = ce ruleaza. Verificat pe cinci ancore; in zona relevanta offsetul e constant,
LIVE + 1240 = PF: LIVE:3749↔PF:4989, LIVE:3840↔PF:5080, LIVE:3909↔PF:5149,
LIVE:3982↔PF:5222, LIVE:4044↔PF:5284, LIVE:12466↔PF:13706, LIVE:13735↔PF:14975.
Nu generalizez offsetul in afara zonei masurate — il dau doar ca dovada de identitate.
1. Unde sta SELECT-ul de la PACK_FACTURARE:5149-5166 si cine il cheama
Numarul de linie e corect, verificat direct pe fisier. PF:5149-5166:
5149 SELECT DECODE(A.PRET_UNITAR, 0, V_PRET_TEMP, A.PRET_UNITAR),
5150 B.PROC_TVAV,
5151 B.ID_VALUTA,
5152 A.PRET_CU_TVA,
5153 C.IN_STOC
5154 INTO V_PRET, V_PROC_TVAV, V_ID_VALUTA, V_PRETURI_CU_TVA, V_IN_STOC
5159 FROM CTR_ARTICOLE A
5160 LEFT JOIN CRM_POLITICI_PRET_ART B ON A.ID_POL_ART = B.ID_POL_ART
5162 LEFT JOIN NOM_ARTICOLE C ON B.ID_ARTICOL = C.ID_ARTICOL
5164 WHERE B.ID_ARTICOL = V_ID_ARTICOL AND A.ID_CTR = V_ID_CTR AND B.ID_POL = V_ID_POL;
Procedura: adauga_articol_factura — spec PF:537, corp PF:4989,
END adauga_articol_factura; PF:5284. Deci DA, e adauga_articol_factura.
CORECTIE fata de raportul rundei 9: procedura nu scrie in VANZARI_DETALII. Se termina cu un
singur INSERT, PF:5222, in VANZARI_DETALII_TEMP:
5222 INSERT INTO VANZARI_DETALII_TEMP (... PRET, PRET_CU_TVA, PROC_TVAV, ... ID_VALUTA, ... IN_STOC ...)
5252 VALUES (... V_PRET, V_PRETURI_CU_TVA, V_PROC_TVAV, ... V_ID_VALUTA, ... V_IN_STOC ...)
Re-derivarea se produce deci pe drumul catre temp, nu dupa el. Afirmatia „scrie_in_vanzari
copiaza PRET neschimbat din temp" e adevarata (vezi 3) si totusi irelevanta ca protectie:
valoarea din formular e inlocuita inainte sa intre in temp.
Cine cheama procedura: numai VFP-ul, din metoda de salvare a formularului:
COMUN\clase\ofacturare.vc2:14069—frm_facturare_articole.do_scrie_articoleCOMUN\clase\ofacturare.vc2:18104—frm_facturare_articole2.do_scrie_articole
(:14054 si :18089 sunt variante comentate, cu bind ?, ale aceluiasi apel.)
In pachet nu exista apelant intern: grep 'adauga_articol_factura\b' da doar PF:537 (spec),
PF:4989 (corp), PF:5284 (END) si doua comentarii de antet (PF:22, PF:1497).
Traseul complet pe calea de scriere (frm_facturare_articole):
ofacturare.vc2:13981—pack_facturare.initializeaza_date_factura(...), care primesteAlltrim(Str(poDate.Tip))(ofacturare.vc2:13994) si il pune in variabila de pachet:PF:1882 pack_facturare.ntip := V_TIP;(corpPF:1808,ENDlaPF:1917).ntip= tipul documentului din formular — acelasi care ajunge inVANZARI.TIP(PF:13670). Tot aici,PF:1835 DELETE FROM VANZARI_DETALII_TEMP;siPF:1836 nid_act := 0;.ofacturare.vc2:14036-14115—SCANpe cursorul de gridcrsfactura, cate unpack_facturare.adauga_articol_factura(...)per linie (:14069), executat pringoExecutor.oExecute(:14105).frm_facturare_articole.do_scrie_factura—scrie_factura2(ofacturare.vc2:14345,:14373),scrie_factura_avize(:14318) sauscrie_factura_avize_retur(:14434,:14497), care ajung lapack_facturare.scrie_in_vanzari(PF:13488).
Raspuns Q1: e adauga_articol_factura, si e pe calea de scriere a documentului (nu pe cea de
creare/incarcare din sursa) — dar tinta insertului e VANZARI_DETALII_TEMP, iar re-derivarea se
aplica inainte de insert, deci nimic de dupa temp nu o mai poate repara.
Poarta care decide re-derivarea
adauga_articol_factura are un singur CASE (PF:5052-5220), pe pack_facturare.ntip:
WHEN |
linii | conditie |
|---|---|---|
| comenzi | PF:5053-5078 |
ntip IN (3, 21, 28, 42, 47) |
| avize | PF:5080-5103 |
ntip = 4 |
| restaurant | PF:5104-5145 |
ntip = 45 |
| contract | PF:5146-5185 |
V_OPT_FACTURARE = 3 |
ELSE |
PF:5187-5218 |
restul |
V_OPT_FACTURARE se seteaza numai daca ntip IN (2, 6, 26, 52) (PF:5039-5050):
SELECT NVL(OPT_FACTURARE, 3) INTO V_OPT_FACTURARE FROM CONTRACTE WHERE ID_CTR = V_ID_CTR;, cu
NO_DATA_FOUND -> V_OPT_FACTURARE := 4. Pentru orice alt ntip ramane NULL, iar WHEN NULL = 3
e NULL -> fals -> se merge pe ELSE. Implicitul e ramura care re-deriva: NVL(OPT_FACTURARE, 3).
Tipurile (COMUN\docs\tipuri_documente_facturare.md): 2 = factura pe contract, 6 = contract in
valuta, 26 = aviz pe contract, 52 = contract factura valuta; 4 = factura din avize;
3/21/28/42/47 = din comenzi; 45 = restaurant.
2. Cele cinci valori, una cate una
Intai maparea parametrilor — ce trimite formularul (apel ofacturare.vc2:14069-14091 confruntat
cu semnatura PF:4989-5015; 27 de parametri, pozitional, potrivire completa):
formular (crsfactura -> poArt) |
parametru |
|---|---|
poArt.pretftva/pretctva/vpretftva/vpretctva |
V_PRET_TEMP |
poArt.id_valuta |
V_ID_VALUTA_TEMP |
poArt.cu_tva |
V_PRETURI_CU_TVA_TEMP |
poArt.gestionabil |
V_IN_STOC_TEMP |
poArt.id_jtva_coloana |
V_ID_JTVA_COLOANA |
poArt.id_pol |
V_ID_POL |
poArt.id_ctr |
V_ID_CTR |
PROC_TVAV nu e parametru. Nu exista V_PROC_TVAV_TEMP in semnatura — cota de TVA a liniei se
calculeaza intotdeauna pe server, in toate ramurile. Formularul trimite ID_JTVA_COLOANA, din
care ramura ELSE deriva PROC_TVAV. Pentru PROC_TVAV intrebarea „vine din temp?" nu are raspuns
„da" pe nicio ramura; intrebarea reala e din ce se deriva.
Ramura contract (V_OPT_FACTURARE = 3, PF:5146-5185)
PRET—DECODE(A.PRET_UNITAR, 0, V_PRET_TEMP, A.PRET_UNITAR)(PF:5149). Se re-deriva dinCTR_ARTICOLE.PRET_UNITARori de cate ori aceasta e<> 0, indiferent daca linia a fost atinsa pe ecran. Numai cand contractul arePRET_UNITAR = 0trece valoarea din formular. Capcana NULL:CTR_ARTICOLE.PRET_UNITARenullable=Y(verificat pe DB); un NULL nu potriveste literalul0inDECODE, deci rezultatul e NULL, nuV_PRET_TEMP— pretul din formular se pierde si linia intra in temp cuPRETNULL. (dedus din semanticaDECODE, nu rulat.)PROC_TVAV—B.PROC_TVAVdinCRM_POLITICI_PRET_ART(PF:5150). Se re-deriva din politica de preturi, nu dinID_JTVA_COLOANAtrimis de formular. Diferit deELSE.ID_VALUTA—B.ID_VALUTAdinCRM_POLITICI_PRET_ART(PF:5151). Se re-deriva;V_ID_VALUTA_TEMPe ignorat.PRET_CU_TVA—A.PRET_CU_TVAdinCTR_ARTICOLE(PF:5152). Se re-deriva;V_PRETURI_CU_TVA_TEMP(poArt.cu_tva) e ignorat.IN_STOC—C.IN_STOCdinNOM_ARTICOLE(PF:5153). Se re-deriva din nomenclatorul curent;V_IN_STOC_TEMP(poArt.gestionabil) e ignorat.
Cele cinci nu merg impreuna nici macar aici: PRET are un DECODE care uneori lasa valoarea din
formular sa treaca, celelalte patru sunt inlocuite neconditionat, din trei tabele diferite
(CTR_ARTICOLE, CRM_POLITICI_PRET_ART, NOM_ARTICOLE).
Iesirea de siguranta: EXCEPTION WHEN NO_DATA_FOUND (PF:5167-5185) deriva PROC_TVAV din
JTVA_COLOANE si pune toate celelalte patru pe valorile din formular (PF:5181-5184):
V_PRET := V_PRET_TEMP; V_ID_VALUTA := V_ID_VALUTA_TEMP; V_PRETURI_CU_TVA := V_PRETURI_CU_TVA_TEMP; V_IN_STOC := V_IN_STOC_TEMP;. Adica daca linia nu mai are corespondent in contract, formularul
castiga — exact comportamentul cerut de decizia 54, existent deja in cod, dar numai pe calea de
exceptie.
Ramura ELSE (PF:5187-5218) — cazul „bun"
PROC_TVAV din JTVA_COLOANE pe ID_JTVA_COLOANA trimis de formular (PF:5189-5192), iar
PF:5200-5203 pune explicit V_PRET := V_PRET_TEMP, V_ID_VALUTA := V_ID_VALUTA_TEMP,
V_PRETURI_CU_TVA := V_PRETURI_CU_TVA_TEMP, V_IN_STOC := V_IN_STOC_TEMP.
Patru din cinci vin din formular; PROC_TVAV se deriva, dar din date trimise de formular.
Ramura comenzi (ntip IN (3,21,28,42,47), PF:5053-5078)
5057 SELECT A.PRET,
5058 NVL2(A.PTVA, ROUND((A.PTVA + 100) / 100, 2), C.PROC_TVAV),
5059 C.ID_VALUTA, B.PRETURI_CU_TVA, D.IN_STOC
5075 WHERE A.ID_COMANDA = V_ID_COMANDA AND A.ID_ARTICOL = V_ID_ARTICOL
5077 AND A.PRET = V_PRET_TEMP AND A.STERS = 0;
PRET— formalA.PRETdinCOMENZI_ELEMENTE, darWHERE ... A.PRET = V_PRET_TEMP(PF:5077) fixeaza rezultatul pe pretul din formular. Practic nu se schimba.PROC_TVAV,ID_VALUTA,PRET_CU_TVA,IN_STOC— se re-deriva dinCOMENZI_ELEMENTE.PTVA/CRM_POLITICI_PRET_ART/CRM_POLITICI_PRETURI/NOM_ARTICOLE.- Ramura nu are bloc
EXCEPTION. UnSELECT INTOgol daNO_DATA_FOUND(ORA-01403) netratat, care urca pringoExecutorin VFP. Deci daca la reemitere pretul liniei a fost modificat pe ecran (sau linia nu mai e in comanda), scrierea cade cu eroare — nu se re-deriva tacit. Este o a doua ramura de re-derivare, pe care raportul rundei 9 nu o numara.
Ramura restaurant (ntip = 45, PF:5104-5145)
PF:5109-5112 pune explicit V_PRET := V_PRET_TEMP, V_ID_VALUTA := V_ID_VALUTA_TEMP,
V_PRETURI_CU_TVA := V_PRETURI_CU_TVA_TEMP, V_IN_STOC := V_IN_STOC_TEMP; SELECT-ul de la
PF:5114-5139 deriva doar V_PROC_TVAV (din JTVA_COLOANE) si V_PRET_ACHIZITIE.
Patru din cinci vin din formular.
Ramura avize (ntip = 4) — la punctul 5
3. UPDATE / recalcul care suprascrie valorile DUPA insertul din temp
Nu exista, pentru cele cinci valori.
Scrierea temp -> definitiv, in scrie_in_vanzari (PF:13488-13953), e o copiere 1:1:
13705 INSERT /*+ APPEND */
13706 INTO VANZARI_DETALII (... PRET, PROC_TVAV, ... ID_VALUTA, ... PRET_CU_TVA, DIFERENTA, ...)
13732 SELECT V_ID_VANZARE as ID_VANZARE, ... PRET, PROC_TVAV, ... ID_VALUTA, ... PRET_CU_TVA, DIFERENTA, ...
13757 FROM VANZARI_DETALII_TEMP;
Capcana de cautare platita aici:
grep 'INSERT INTO VANZARI_DETALII'da zero potriviri — hint-ul/*+ APPEND */rupe cuvintele pe doua randuri. Cautarea corecta eINTO VANZARI_DETALII.
IN_STOC nu apare in lista de coloane (PF:13707-13731), si VANZARI_DETALII nu are coloana
IN_STOC (verificat pe DB: all_tab_columns -> 0 randuri). Traieste doar in
VANZARI_DETALII_TEMP, unde decide descarcarea de gestiune. Re-derivarea lui nu murdareste
documentul salvat, dar schimba comportamentul de stoc al reemiterii.
Toate scrierile pe VANZARI_DETALII din pachet:
| linie | procedura | ce face |
|---|---|---|
PF:13705 |
scrie_in_vanzari (PF:13488) |
INSERT 1:1 din temp |
PF:14974 |
finalizeaza_avize_lucrare (PF:14854) |
INSERT 1:1 din temp (cale avize de lucrare) |
PF:5560 |
sterge_factura (PF:5432) |
SET STERS, ID_UTILS, DATAORAS |
PF:5630 |
sterge_proforma (PF:5610) |
SET STERS, ID_UTILS, DATAORAS |
PF:14516 |
modifica_explicatie_articol (PF:14511) |
SET EXPLICATIE, TAXCODE |
PF:16017 |
actualizeaza_vanzari (PF:16012) |
SET STERS = 0 |
Niciun UPDATE nu atinge PRET, PROC_TVAV, ID_VALUTA, PRET_CU_TVA.
Confirmat si pe DB: all_source are exact doua INTO VANZARI_DETALII (LIVE:12466, LIVE:13735).
Mutatiile pe VANZARI_DETALII_TEMP intre adauga_articol_factura si scrie_in_vanzari:
| linie | procedura | ce schimba |
|---|---|---|
PF:5297 |
adauga_diferente_pret |
numai DIFERENTA (PF:5344: UPDATE SET DIFERENTA = B.DIFERENTA) |
PF:6860, PF:6864 |
scrie_factura_avize |
numai CANTITATE (split pe custodie); in MERGE, PRET, PRET_CU_TVA, PROC_TVAV, ID_VALUTA, IN_STOC sunt in clauza ON, nu in UPDATE SET |
PF:14020 |
scrie_seturi |
numai ID_VANZARE_SET |
PF:14057 |
scrie_seturi_proforma |
numai ID_VANZARE_SET (cale proforma) |
PF:12266 |
transfera_articol |
cale de transfer, in afara scrierii de factura |
pack_auto.actualizeaza_deviz (D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\03\ff_2026_03_31_02_AUTO_PACK_AUTO.sql:692-733)
atinge DEV_ORDL.PROC_TVAV, RUL.ID_FACT, NOM_LUCRARI.ID_FACT — nu atinge VANZARI_DETALII.
Recalculele de totaluri (PF:13760+, recalculeaza_totaluri_vanzari PF:16021) si rotunjirile
lucreaza pe VANZARI, agregat — nu rescriu linia.
Raspuns Q3: nu. Dupa insertul in temp, cele cinci valori nu mai sunt suprascrise nicaieri.
DIFERENTA si CANTITATE da, restul nu.
4. Verdict: ajung valorile din formular neatinse in VANZARI_DETALII?
NU, pentru trei familii de tipuri. DA, pentru restul.
Se pierd intr-un singur loc: PACK_FACTURARE.adauga_articol_factura, in CASE-ul de la
PF:5052-5220, adica inainte de INSERT INTO VANZARI_DETALII_TEMP (PF:5222). Precis:
- contract (
ntip IN (2,6,26,52)cuCONTRACTE.OPT_FACTURARENULL sau 3) —PF:5149-5153: se pierdPRET(candCTR_ARTICOLE.PRET_UNITAR <> 0),PROC_TVAV,ID_VALUTA,PRET_CU_TVA,IN_STOC; - aviz (
ntip = 4) —PF:5082-5086: se pierd toate cinci, inclusivPRET, neconditionat; - comenzi (
ntip IN (3,21,28,42,47)) —PF:5057-5061: se pierd patru;PRETe fixat deWHERE, dar la nepotrivire scrierea cade cu ORA-01403 in loc sa treaca.
Pentru toate celelalte tipuri (1, 5, 10, 22, 45, ...) valorile din formular ajung neatinse:
ramurile ELSE (PF:5200-5203) si restaurant (PF:5109-5112) le copiaza explicit, iar traseul de
dupa (PF:13705-13757) e copiere 1:1.
Exceptie transversala, valabila pe TOATE tipurile: PROC_TVAV nu vine niciodata din formular —
nu e parametru al procedurii. Pe calea „buna" se deriva din JTVA_COLOANE pe ID_JTVA_COLOANA-ul
trimis de formular, deci reproduce documentul atat timp cat cota din JTVA_COLOANE nu s-a
schimbat. La o modificare legala de cota, reemiterea schimba TVA-ul chiar si pe ramura ELSE.
5. Sursa AVIZ (ntip = 4) — calea difera, si e mai grava
Verbatim, PF:5080-5103 (confirmat identic pe DB, LIVE:3840-3863):
5080 WHEN pack_facturare.ntip = 4 THEN
5081 -- facturare din avize
5082 SELECT DISTINCT A.PRET,
5083 A.PROC_TVAV,
5084 A.ID_VALUTA,
5085 A.PRET_CU_TVA,
5086 B.IN_STOC
5087 INTO V_PRET, V_PROC_TVAV, V_ID_VALUTA, V_PRETURI_CU_TVA, V_IN_STOC
5092 FROM VANZARI_DETALII A
5093 LEFT JOIN NOM_ARTICOLE B ON A.ID_ARTICOL = B.ID_ARTICOL
5095 WHERE A.ID_ARTICOL = V_ID_ARTICOL
5096 AND A.ID_POL = V_ID_POL
5097 AND NVL(A.ID_GESTIUNE, -1000) = V_ID_GESTIUNE
5098 AND A.DISCOUNT_UNITAR = V_DISCOUNT_UNITAR
5099 AND NVL(A.CONT, 'XXXX') = V_CONT
5100 AND A.ID_VANZARE IN
5101 (SELECT X AS ID_VANZARE
5102 FROM table(cast(CHARN2COLLECTION(pack_facturare.clistaid, ',') AS num_tab)));
Diferentele fata de contract, toate in defavoarea deciziei 54:
PRETse re-deriva neconditionat, direct dinVANZARI_DETALIIal avizului sursa. Nu existaDECODE(..., 0, V_PRET_TEMP, ...)si nu existaAND A.PRET = V_PRET_TEMPinWHERE(spre deosebire de ramura comenzi,PF:5077). Un pret modificat pe ecran la reemitere e inlocuit tacit cu pretul din aviz. Aceasta e ramura cea mai agresiva din totCASE-ul.- Nu are bloc
EXCEPTION. Ramura contract areNO_DATA_FOUNDcare cade inapoi pe formular (PF:5167-5185); aici, orice modificare pe ecran aDISCOUNT_UNITAR,CONT,ID_GESTIUNEsauID_POLscoate randul dinWHERE-> ORA-01403 urcata in VFP.SELECT DISTINCTpeste mai multe avize cu preturi diferite pe acelasi articol poate da si ORA-01422 (TOO_MANY_ROWS). - Nu filtreaza
A.STERS = 0, desiVANZARI_DETALIIare coloanaSTERS(verificat pe DB) sisterge_facturao foloseste (PF:5560). Linii sterse ale avizului sursa pot fi citite. - Depinde de
pack_facturare.clistaid— lista de avize sursa, trimisa de VFP prininitializeaza_date_factura(poDate.listaid,ofacturare.vc2:13992). La reemitere,clistaidtrebuie repopulata cu aceleasi avize, altfelWHEREnu potriveste nimic -> ORA-01403.
Ce nu difera: dupa CASE traseul e identic (INSERT in temp PF:5222, apoi copiere 1:1
PF:13705), iar scrie_factura_avize (PF:6692) modifica in temp numai CANTITATE
(PF:6860, PF:6864) — nu re-deriva nimic in plus.
Raspuns Q5: calea difera, si e mai stricta. Pe contract exista o portita (PRET_UNITAR = 0
si NO_DATA_FOUND) prin care valorile din formular trec; pe aviz nu exista niciuna — ori se
re-deriva tot, ori pica cu eroare.
6. Consecinta pentru decizia 54, la nivel de contract
6.1 Se poate curat VFP? Nu.
Confirm afirmatia rundei 9 — dar acum cu dovada, nu prin absenta:
- Semnatura nu are flag.
PF:4989-5015: 27 de parametri, toti date de linie; ultimii doi (V_TAXCODE,V_LOT) suntDEFAULT NULL, niciunul nu e comutator. - Globalele pachetului nu au flag.
PF:126-212— stare de sesiune (ntip,clistaid,nid_part, ...), niciun comutator de comportament pe re-derivare. - Poarta nu e influentabila legitim din VFP.
ntipajunge inVANZARI.TIP(PF:13670) — a-l falsifica inseamna a schimba tipul documentului.CONTRACTE.OPT_FACTURAREe date de contract, nu parametru de apel. - Singurele parghii VFP care ar devia pe calea
NO_DATA_FOUNDsunt, ambele, de aceeasi natura ca varianta (d) deja respinsa:V_ID_CTR = NULL— respinsa;PF:5280duceV_ID_CTRintemp.ID_CTR, iarPF:13755inVANZARI_DETALII.ID_CTR, deci legatura se pierde permanent;V_ID_POL = NULL— acelasi defect, alta coloana:PF:5258duceV_ID_POLintemp.ID_POL,PF:13737inVANZARI_DETALII.ID_POL; in plus ar rupe ramura aviz, care potriveste peA.ID_POL = V_ID_POL(PF:5096). Nu o propun — o mentionez ca sa nu fie redescoperita ca „solutie" intr-o runda urmatoare.
Concluzie: decizia 54 cere obligatoriu modificare in pack_facturare.
6.2 Ce forma trebuie sa aiba semnalul
Doua forme sunt inerte pentru apelantii de azi:
- (i) variabila noua de pachet („regenerare in curs"), implicit
0= comportamentul actual, scrisa de VFP dupainitializeaza_date_facturasi inainte de bucla deadauga_articol_factura; - (ii) parametru
DEFAULT 0adaugat dupaV_LOTin semnatura — apelantii de azi trimit 27 de argumente pozitional si raman valizi.
Recomand (i), din trei motive concrete: se potriveste cu stilul existent al pachetului (care e deja
o punga de stare de sesiune); se scrie o data pe document, nu o data pe linie, in toate produsele; si
punctul de resetare exista deja — initializeaza_date_factura (PF:1808-1917) reinitializeaza
~40 de globale si face DELETE FROM VANZARI_DETALII_TEMP (PF:1835), deci flag-ul nu poate scapa in
documentul urmator din aceeasi sesiune. Atentie la ordine: VFP il seteaza dupa apelul de la
ofacturare.vc2:13981, nu inainte. Ambele variante modifica spec-ul, deci ambele forteaza
recompilarea dependentilor — nu e un criteriu de departajare.
6.3 Ce face semnalul, cand e pornit
Nimic nou — forteaza ramura care exista deja. Cea mai mica forma: un WHEN nou, primul in
CASE-ul de la PF:5052, cu acelasi corp ca ELSE-ul de azi (PF:5189-5203): PROC_TVAV din
JTVA_COLOANE pe V_ID_JTVA_COLOANA, si V_PRET/V_ID_VALUTA/V_PRETURI_CU_TVA/V_IN_STOC din
parametrii *_TEMP. INSERT-ul de la PF:5222 ramane neatins. Acopera dintr-o data toate trei
ramurile problematice (contract, aviz, comenzi), pentru ca toate sunt in acelasi CASE.
6.4 Trei consecinte de acceptat explicit, nu ocolite
IN_STOCar veni din formular (poArt.gestionabil) in loc deNOM_ARTICOLE. Nu e o problema de fidelitate a documentului —VANZARI_DETALIInu are coloanaIN_STOC(verificat pe DB) — ci de comportament de stoc la reemitere. Ca reemiterea sa fie identica, incarcarea (S8) trebuie sa dea valoarea cu care s-a scris documentul initial. Azi nu o da: loader-ul lui #6 o citeste din nomenclatorul curent —ofacturare_editare.prg:302-303,left join nom_articole na on na.id_articol = v.id_articol, cu comentariul care spune ca view-ul n-o expune. Flag-ul singur nu rezolva asta.- Se pierde o validare pe ramura comenzi.
A.PRET = V_PRET_TEMP(PF:5077) plus lipsa luiEXCEPTIONfac azi ca o linie care nu se mai potriveste cu comanda sa opreasca scrierea. Cu flag-ul pornit, reemiterea unei „facturi din comanda" nu mai verifica linia fata de comanda. Decizia 54 pare sa vrea exact asta, dar e o schimbare de comportament care trebuie spusa, nu descoperita la S12. PROC_TVAVramane derivat, nu preluat. Reproducerea exacta a documentului cere ca S8 sa pastrezeID_JTVA_COLOANAsi caJTVA_COLOANE.COTA_TVAsa nu se fi schimbat intre timp. Daca se cere reproducere exacta si peste o modificare de cota,PROC_TVAVtrebuie sa devina parametru — schimbare mai mare decat flag-ul, de decis separat.
6.5 Un obstacol de incarcare, gasit in treacat (pentru S8, nu pentru S10)
View-ul pe care se sprijina incarcarea de azi, VVANZARI_ARTICOLE, expune (interogat pe DB):
ID_VANZARE, ID_VANZARE_DET, ID_ARTICOL, CANTITATE, PRET, PRET_CU_TVA, PROC_TVAV, DISCOUNT_UNITAR, ID_GESTIUNE, CONT, ID_VALUTA, ID_JTVA_COLOANA, SERIE, EXPLICATIE, TAXCODE, LOT, STERS, ID_VANZARE_SET, PRET_ACHIZITIE, DENUMIRE, CODMAT, NUME_GESTIUNE, NUME_VAL.
Nu expune ID_POL si nu expune ID_CTR — exact cei doi pe care adauga_articol_factura ii cere
(V_ID_POL, V_ID_CTR) si pe care VANZARI_DETALII ii pastreaza. Reemiterea S9 nu poate folosi
acest view ca atare; ori se completeaza view-ul, ori loader-ul citeste direct din
VANZARI_DETALII. Nu e in perimetrul S10, dar blocheaza S9 daca nu e prins din timp.
Tabel sintetic — cele cinci valori pe ramura
„temp" = valoarea trimisa de formular; „re-derivat" = citita din alta sursa si suprascrisa.
| valoare | contract (2/6/26/52, OPT_FACTURARE NULL sau 3) |
aviz (ntip = 4) |
comenzi (3/21/28/42/47) | restaurant (45) | ELSE |
|---|---|---|---|---|---|
PRET_UNITAR (PRET) |
re-derivat din CTR_ARTICOLE.PRET_UNITAR daca <> 0; temp daca = 0; NULL daca e NULL (PF:5149) |
re-derivat din VANZARI_DETALII al avizului, neconditionat (PF:5082) |
temp de facto — WHERE A.PRET = V_PRET_TEMP (PF:5077); nepotrivire = ORA-01403 |
temp (PF:5109) |
temp (PF:5200) |
PROC_TVAV |
re-derivat din CRM_POLITICI_PRET_ART (PF:5150) |
re-derivat din avizul sursa (PF:5083) |
re-derivat din COMENZI_ELEMENTE.PTVA / politica (PF:5058) |
re-derivat din JTVA_COLOANE (PF:5114) |
derivat din JTVA_COLOANE pe ID_JTVA_COLOANA din formular (PF:5189) |
ID_VALUTA |
re-derivat din CRM_POLITICI_PRET_ART (PF:5151) |
re-derivat din avizul sursa (PF:5084) |
re-derivat din politica (PF:5059) |
temp (PF:5110) |
temp (PF:5201) |
PRET_CU_TVA |
re-derivat din CTR_ARTICOLE (PF:5152) |
re-derivat din avizul sursa (PF:5085) |
re-derivat din CRM_POLITICI_PRETURI (PF:5060) |
temp (PF:5111) |
temp (PF:5202) |
IN_STOC |
re-derivat din NOM_ARTICOLE (PF:5153) |
re-derivat din NOM_ARTICOLE (PF:5086) |
re-derivat din NOM_ARTICOLE (PF:5061) |
temp (PF:5112) |
temp (PF:5203) |
PROC_TVAV nu vine din temp pe nicio ramura — nu e parametru al procedurii.
IN_STOC nu ajunge in VANZARI_DETALII (coloana nu exista) — traieste doar in temp, unde decide
descarcarea de gestiune.
Pe ramura contract, EXCEPTION WHEN NO_DATA_FOUND (PF:5167-5185) muta toate cele cinci pe
coloana „temp"; ramurile aviz si comenzi nu au un asemenea bloc.
Verificat direct vs. dedus
Verificat direct pe fisier SI confirmat pe DB (all_source, MARIUSM_AUTO.PACK_FACTURARE,
PACKAGE BODY, VALID, last_ddl_time = 2026-08-09 20:03:50):
granitele lui adauga_articol_factura; toate cele cinci ramuri ale CASE-ului, ramura cu ramura;
textul integral al ramurii aviz; faptul ca insertul procedurii merge in VANZARI_DETALII_TEMP; ca
exista exact doua INTO VANZARI_DETALII in tot pachetul.
Verificat direct pe fisier (nereconfirmat separat pe DB, dar in aceeasi zona cu offset masurat):
copierea 1:1 temp -> VANZARI_DETALII (PF:13705-13757); cele patru UPDATE VANZARI_DETALII si ce
coloane ating; mutatiile pe temp intre adauga_articol_factura si scrie_in_vanzari; corpul lui
pack_auto.actualizeaza_deviz.
Verificat pe metadatele DB: VANZARI_DETALII nu are IN_STOC, are STERS;
CTR_ARTICOLE.PRET_UNITAR e nullable=Y; lista de coloane a lui VVANZARI_ARTICOLE.
Verificat direct in VFP: apelantii lui adauga_articol_factura; maparea celor 27 de parametri;
ntip := poDate.Tip; loader-ul IncarcaArticoleFactura (ofacturare_editare.prg:292-327).
Dedus, nerulat: comportamentul DECODE cu PRET_UNITAR NULL (semantica Oracle, nu test);
ORA-01403 / ORA-01422 pe ramurile fara EXCEPTION (din absenta blocului, nu din reproducere).
Din date de dev — NU e dovada, nu extrapolati: CTR_ARTICOLE are 27 de randuri
(0 NULL, 10 cu PRET_UNITAR = 0, 17 cu <> 0) — deci cazul NULL nu apare in dev, ceea ce nu
spune nimic despre productie. CONTRACTE.OPT_FACTURARE: 176 NULL, 53 = 0, 9 = 1, 3 = 3, 1 = 4 —
adica pentru 176 + 3 din 242 de contracte NVL(OPT_FACTURARE, 3) da 3 si ramura re-deriva.
Neacoperit: n-am rulat niciun flux real (nici VFP, nici o reemitere efectiva) — totul e analiza
statica plus interogari SELECT pe metadate. N-am citit corpurile scrie_factura2 si
finalizeaza_factura integral, doar punctele in care ating VANZARI_DETALII / temp.
Corectii la rapoartele anterioare
docs\cercetare\s10_pret_rederivat.md (runda 9)
- „exista exact o ramura care suprascrie pretul — contractul" — FALS. Ramura aviz
(
ntip = 4,PF:5080-5103) suprascriePRETneconditionat, faraDECODEsi fara filtru pe pretul din formular — mai agresiv decat contractul. Ramura comenzi (PF:5053-5078) nu suprascriePRET, dar suprascrie celelalte patru si arunca ORA-01403 la nepotrivire. Ramurile care re-deriva sunt trei, nu una. - „pe calea de scriere" — corect ca moment, gresit ca destinatie. Se intampla la salvare, dar
insertul e in
VANZARI_DETALII_TEMP(PF:5222), nu inVANZARI_DETALII. Diferenta conteaza: explica de ce copierea „neschimbata" de mai tarziu nu protejeaza nimic. - „nu exista niciun parametru sau flag care sa opreasca re-derivarea" — CONFIRMAT, acum cu dovada
pozitiva (semnatura
PF:4989-5015, globalelePF:126-212), nu prin absenta.
docs\cercetare\s10_pret_contract_reemitere.md (runda 13)
- „acelasi
SELECTalimenteaza cinci valori" — corect (PF:5149-5166), dar de completat: nu merg impreuna —PRETareDECODE, celelalte patru sunt neconditionate, si vin din trei tabele diferite. - „
IN_STOCdin nomenclatorul curent" — corect, de completat cu faptul decisiv:VANZARI_DETALIInu are coloanaIN_STOC(verificat pe DB). Nu ajunge in document; efectul e pe descarcarea de gestiune. - „
scrie_in_vanzaricopiazaPRETneschimbat din temp" — corect (PF:13705-13757), de marcat insa ca nu e o protectie: dauna e amonte de temp. - Varianta „avertizare + confirmare" ramane respinsa (decizia 54) — nu am reargumentat-o.
docs\plan_13_unificare_formular_facturare.md
- Trimiterea „
initializeaza_date_factura(PACK_FACTURARE:1808-1846)" — corpul incepe laPF:1808dar se termina laPF:1917. Citarile:1835/:1836din plan sunt corecte.