Files
roafacturare/docs/cercetare/garda_aviz_facturat.md
Marius Mutu d9f5ca4226 docs: planurile, proiectarile si rapoartele de lucru intra in versionare
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
2026-08-11 22:17:17 +03:00

13 KiB

Garda "aviz deja facturat" — verificare pe cod

Verificare pe cod, fara nicio modificare de fisier. Sursele citate:

  • export pachet: D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql (mai jos: EXPORT:<linie>);
  • corpul desfasurat pe DB (MARIUSM_AUTO@ROA_CENTRAL, all_source), citit ca sa se confirme ca ce e in export e si ce ruleaza (mai jos: DB PACK_FACTURARE:<linie>). Numerotarea difera: sterge_factura incepe la EXPORT:5432, dar la DB PACK_FACTURARE:4192. Nu exista offset constant; textul insa e identic cuvant cu cuvant pe zona gardelor.

1. Blocheaza garda de azi si un AVIZ care are deja factura generata din el?

DA. Nu e nevoie de nicio garda noua pentru cazul asta — este exact ce testeaza a doua garda din sterge_factura, prin TIP IN (1, 2).

EXPORT:5464-5476 = DB PACK_FACTURARE:4224-4236:

    -- ptr. un aviz normal:
    --  verific daca exista facturi sau avize de retur pe avizul resp.
    SELECT COUNT(*)
      INTO V_NR_AVIZE_FACT
      FROM VANZARI_CORESP
     WHERE STERS = 0
       AND ID_VANZARE_AVIZ = V_ID_VANZARE
       AND TIP IN (1, 2);

    IF V_NR_AVIZE_FACT > 0 THEN
      RAISE_APPLICATION_ERROR(-20000,
                              'Pe acest aviz s-au emis facturi / aviz de retur. Trebuie sa stergeti mai intai facturile / avizul de retur!');
    END IF;

Cheia e semantica lui TIP, citita din singurul scriitor al tabelei, ramura cu ramura (finalizeaza_factura, EXPORT:14818-14839):

VANZARI_CORESP.TIP scris cand ID_VANZARE_FACT ID_VANZARE_AVIZ e retur?
1 ntip = 4 — facturare din aviz (EXPORT:14823-14826) factura avizul-sursa NU
2 ntip = 24 — aviz de retur (EXPORT:14828-14830) avizul de retur avizul original DA
3 ntip in (8, 9) — factura de retur (EXPORT:14834-14836) factura de retur factura originala DA

Deci TIP = 1 este corespondenta aviz -> factura normala, nu retur. Garda de la EXPORT:5473 prinde ambele cazuri; textul mesajului chiar o spune ("s-au emis facturi / aviz de retur"). Formularea din brief ("garda de azi blocheaza documentul care are facturi/avize de retur") vine dintr-o citire a comentariului -- verific daca exista facturi sau avize de retur in care "de retur" se distribuie si peste "facturi"; codul zice altceva.

Deci: la ora asta, exact regula ceruta de decizia 50 este deja implementata pentru avize (document cu urmasi = blocat; capatul lantului = liber).

Ce NU citeste garda

  • VANZARI.FACTURAT nu e citit de nicio garda. Pe calea de stergere e doar scris (EXPORT:5504-5510 pentru V_TIP = 24, EXPORT:5527-5533 pentru V_TIP = 4 — resetare la 0 cand dispare factura/avizul de retur), iar la facturare e pus de marcheaza_facturat (EXPORT:15381-15418). Niciun IF / RAISE nu il interogheaza. Semnalul autoritar este VANZARI_CORESP, FACTURAT e derivat redundant.
  • ID_VANZARE_SURSA / ID_VANZARE_DEST nu exista. VANZARI_CORESP are exact 5 coloane (interogare pe all_tab_columns): ID_VANZARE_CORESP, ID_VANZARE_FACT, ID_VANZARE_AVIZ, STERS, TIP. Nici VANZARI nu are coloane *_SURSA / *_DEST (aceeasi interogare).

2. Exista alte garzi pe calea de stergere / modificare?

2a. Oracle — nu exista alta, dar garda e atinsa pe ambele ramuri de stergere

Interogare pe all_source (owner curent): singurele obiecte care contin VANZARI_CORESP sunt PACK_FACTURARE (package body) si TRG_VANZARI_CORESP_BEFOINS. Deci nu exista o a doua garda ascunsa in alt pachet.

Triggerele nu contin garzi (sursa citita integral din all_source):

trigger tabela eveniment ce face
TRG_VANZARI_BEFOUPD VANZARI UPDATE 4 apeluri pack_audit.verifica_val (NR_ACT, SERIE_ACT, DATA_ACT, DATA_SCAD) — audit, nu blocare
TRG_VANZARE_BEFOINS VANZARI INSERT —
TRG_VANZARI_DET_BEFOINS VANZARI_DETALII INSERT —
TRG_VANZARI_CORESP_BEFOINS VANZARI_CORESP INSERT doar SEQ_VANZARI_CORESP.nextval

Punct important de verificat, pentru ca la prima citire pare o portita: in frm_facturi.do_sterge apelul direct pack_facturare.sterge_factura e comentat pe ramura documentelor cu note contabile — ofacturare_comun.vc2:4807-4809 (*!* modificare v 2.2.5), iar ramura activa (:4810-4811) cheama numai pack_contafin.finalizeaza_stergere_nota. Nu e o portita: lantul se inchide in Oracle.

PACK_CONTAFIN:8322-8326   SELECT COUNT(*) INTO lnEInVanzari FROM vanzari WHERE cod = tnCod;
                          IF lnEInVanzari > 0 THEN
                            pack_facturare.sterge_din_vanzari(tnCod, tnAn, tnLuna, tnIdUtil);
PACK_FACTURARE:14996-14998  SELECT ID_VANZARE INTO V_ID_VANZARE FROM VANZARI WHERE COD = V_COD;
                            pack_facturare.sterge_factura(V_ID_VANZARE, V_LUNA, V_AN, V_ID_UTIL);

Apelantii lui sterge_factura in baza (cautare pe all_source) sunt exact doi: PACK_FACTURARE.sterge_din_vanzari (DB PACK_FACTURARE:14998) si procedura standalone STERGE_DOCUMENT (DB STERGE_DOCUMENT:416). Ambele cai trec prin garda.

2b. VFP — pe calea de stergere: nicio garda pe urmasi

frm_facturi.do_sterge (COMUN\clase\ofacturare_comun.vc2:4661-4877) verifica, inainte de apel: luna inchisa (:4676), sters = 1 (:4689), confirmare (:4694), luna curenta (:4701) si referinte de incasari/plati (ReferinteDocumenteNota, :4723-4727). Nimic despre FACTURAT, VANZARI_CORESP sau urmasi — verificarea lantului e delegata integral Oracle-ului.

2c. VFP + Oracle — pe calea de modificare: nicio garda, nici pe urmasi, nici pe lant

frm_facturi.do_modifica (ofacturare_comun.vc2:4541-4640) blocheaza doar doua lucruri (:4590, :4635):

			If poRec.sters = 0 AND NVL(m.pnEFactura,0) = 0
			...
				amessagebox("Nu puteti face modificari pe inregistrarile sterse sau facturile trimise in eFactura!", 48, "Atentie")

pack_facturare.modifica_date_factura (EXPORT:14439-14509) e un lant de UPDATE-uri fara niciun IF de validare si fara niciun RAISE_APPLICATION_ERROR. Ceea ce e coerent cu ce modifica azi (ruta, delegat, agent, masina, dataora exp., text aditional, tip SAFT, eFactura, serie/numar/data act, data scadenta) — campuri de antet care nu ating lantul aviz -> factura.


3. Concluzia operationala pentru decizia 50 / S7

Regula ceruta de decizia 50 exista deja, si nu are gol pe aviz. sterge_factura implementeaza azi, in trei garzi consecutive, exact "documentul cu urmasi e blocat, capatul lantului e liber":

garda EXPORT ce blocheaza
1 5452-5462 factura care are facturi de retur peste ea (TIP = 3)
2 5466-5476 aviz care are factura (TIP = 1) sau aviz de retur (TIP = 2) peste el
3 5480-5494 factura din aviz ale carei avize-sursa au primit intre timp aviz de retur

A treia garda merita subliniata pentru decizia 50: factura din aviz e editabila doar cat timp niciunul dintre avizele ei nu are aviz de retur; nu e "capat de lant" neconditionat.

Deci S7 nu are nevoie de o garda noua ca regula — dar are nevoie de o citire noua a aceleiasi conditii, ca moment. Garda de azi e in interiorul lui sterge_factura, adica se manifesta ca ORA-20000 in mijlocul pasului de stergere din regenerare, dupa ce utilizatorul a completat formularul si dupa ce s-a deschis tranzactia. Pentru un flux de editare asta e o esuare tarzie. Ce lipseste e un pre-flight read-only, inainte de intrarea in formular, pe exact aceeasi conditie (fara reimplementarea regulii):

select count(*) from vanzari_coresp
 where sters = 0 and id_vanzare_aviz = :id_vanzare and tip in (1, 2, 3)

plus, pentru cazul "factura din aviz", subinterogarea din garda 3 (EXPORT:5480-5488). Garda din sterge_factura ramane pe loc ca plasa de siguranta — nu se muta, nu se slabeste.

Interogarea se face pe VANZARI_CORESP, nu pe VANZARI.FACTURAT: FACTURAT e un marcaj redundant, derivat, scris/resetat de marcheaza_facturat / sterge_factura, si necitit de nicio garda; VANZARI_CORESP e semnalul autoritar.


4. Inventar: ce tipuri de documente-parinte produc urmasi prin VANZARI_CORESP?

Doar trei, toate scrise din acelasi CASE din finalizeaza_factura (EXPORT:14818-14839), prin singurul scriitor scrie_corespondente_vanzari (EXPORT:15481-15516, singurul INSERT INTO VANZARI_CORESP din tot pachetul — si din toata baza, cf. all_source).

parinte urmas TIP de unde vine lista parintilor
aviz (VANZARI.TIP in 21, 22, 26, 42) factura din aviz (ntip = 4) 1 clistaid_avize, setat la EXPORT:7037 in scrie_factura_avize; lista o construieste VFP prin caut_avize, filtrata a.tip in (21,22,26,42) and a.facturat = 0 — COMUN\programe\oproceduri_facturare.prg:2036-2038
aviz aviz de retur (ntip = 24) 2 clistaid
factura factura de retur (ntip in 8, 9) 3 clistaid

Ce NU produce urmasi prin VANZARI_CORESP (deci decizia 50 nu are acoperire acolo prin garda existenta):

  • proforma -> factura. Proforma sta in VANZARI cu EPROFORMA = 1; finalizeaza_factura nu are ramura care sa scrie corespondenta pentru ea. TIP = 4 este o propunere de la S5c, nu cod existent. Mai mult, pack_facturare.sterge_proforma (EXPORT:5610-5635) nu are nicio garda — corpul ei e doar doua UPDATE ... SET STERS = 1 pe VANZARI si VANZARI_DETALII. O proforma din care s-a emis factura se poate sterge azi fara niciun avertisment. (Calea VFP: ofacturare_comun.vc2:4707-4719, care iese din do_sterge inainte de restul verificarilor.)
  • comanda -> factura. Legatura e VANZARI.ID_COMANDA + pack_facturare.inchide_comanda (EXPORT:5769), nu VANZARI_CORESP. COMENZI nu are coloana FACTURAT (verificat pe all_tab_columns) — flagul facturat din grid vine din view-ul de incarcare. Garda exista, dar e in VFP si pe comanda, nu pe factura: COMUN\clase\ocomenzi.vc2:1806-1807 la modificare ("Aceasta comanda a fost facturata si nu mai poate fi modificata!") si :2065-2066 la stergere.
  • contract -> factura. Legatura e VANZARI.ID_CTR + CTR_RATE_FACTURI (atinsa de sterge_factura la EXPORT:5566-5580 pentru V_TIP IN (2, 6, 52)); nicio linie in VANZARI_CORESP, nicio garda de tip "are urmasi".

5. Ce am verificat direct vs. ce am dedus

Verificat direct pe cod / pe metadate:

  • textul celor trei garzi din sterge_factura, in export si desfasurat din all_source (identice);
  • CASE-ul din finalizeaza_factura care da semantica lui TIP, ramura cu ramura;
  • corpul lui scrie_corespondente_vanzari si marcheaza_facturat;
  • ca INSERT INTO VANZARI_CORESP exista intr-un singur loc (grep pe export + all_source pe toata baza);
  • sursa integrala a celor 4 triggere de pe VANZARI / VANZARI_DETALII / VANZARI_CORESP;
  • lista completa a apelantilor lui sterge_factura (all_source), inclusiv lantul finalizeaza_stergere_nota -> sterge_din_vanzari -> sterge_factura;
  • coloanele reale ale VANZARI_CORESP, PROFORME, si absenta lui FACTURAT din COMENZI (all_tab_columns);
  • frm_facturi.do_sterge si frm_facturi.do_modifica integral, plus modifica_date_factura;
  • filtrul caut_avize din oproceduri_facturare.prg.

Dedus / cu limite declarate:

  • Ca TIP = 1 inseamna "factura normala din aviz" e o deductie din singurul punct de scriere (ntip = 4 -> scrie_corespondente_vanzari(1)) — solida, dar e deductie, nu o eticheta declarata intr-un nomenclator.
  • Ca setul tipurilor-parinte pentru TIP = 1 e {21, 22, 26, 42} vine din filtrul VFP caut_avize, nu dintr-o restrictie in Oracle. Pachetul insereaza orice ID_VANZARE primit in clistaid_avize, fara filtru pe tip (EXPORT:15494-15504). Alt apelant (alt produs ROA, un import) ar putea introduce alte tipuri.
  • Nu am verificat daca vreun alt produs ROA (ROACONT / ROAGEST / ...) are o cale proprie de stergere care ocoleste sterge_factura. Am verificat doar ca in Oracle nu exista alt apelant si ca in ROAFACTURARE ambele ramuri din do_sterge ajung acolo.

Din date, deci nedovaditor: interogarea pe VANZARI_CORESP din baza de dev arata TIP=1 cu parinti de tip 21 si 22, TIP=2 cu parinte 22, TIP=3 cu parinte 1 — consistent cu tabelul de mai sus, dar volumul e de ordinul unitatilor (8 randuri in total). Nu e dovada; concluziile de mai sus vin din cod.

6. Ce nu s-a putut stabili

Nimic din cele 4 intrebari nu a ramas nedeterminat. Singurul punct pe care l-as lasa explicit deschis pentru S7 este cel de la §4: golul real nu e pe aviz, e pe proforma — sterge_proforma nu are absolut nicio garda, iar daca S5c chiar introduce TIP = 4 (proforma -> factura), garda din sterge_factura nu se aplica automat, pentru ca sterge_proforma e o procedura complet separata care nu o apeleaza.