236 lines
13 KiB
Markdown
236 lines
13 KiB
Markdown
# 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):
|
|
|
|
```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.
|