# 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:`); - 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:`). **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): ```sql 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.