Files
roafacturare/docs/cercetare/s11_legaturi_id_vanzare.md
2026-09-09 22:19:22 +03:00

380 lines
29 KiB
Markdown

# S11 — Legaturile care raman pe `ID_VANZARE` la editarea prin regenerare
Stare: **in lucru**. Vezi sectiunea STARE / CE RAMANE la final pentru progres curent.
## Context (dat, nu se rediscuta)
#13 etapa II: editarea unei facturi = regenerare. Documentul vechi e soft-sters (`STERS=1`) si
reemis in aceeasi tranzactie. `ID_FACT`, seria, numarul si data se pastreaza. **`ID_VANZARE` se
schimba** — documentul reemis primeste un `id_vanzare` nou din secventa.
Sarcina: inventarul complet al legaturilor pe `VANZARI.ID_VANZARE` care se rup la aceasta
schimbare, clasificate (A) trebuie remigrat / (B) trebuie sters-refacut / (C) nu conteaza.
## 0. Puncte de plecare (de verificat, nu de preluat pe incredere)
- `docs\plan_13_unificare_formular_facturare.md` — sectiunea `#### S11` (linia ~3024)
- `docs\cercetare\idfact_refolosire_si_documente.md`
- `docs\cercetare\rec_cale_vanzari_detalii.md`
- `COMUN\docs\cercetare\rec_consumatori_vanzari.md`
- `docs\cercetare\cont_venit_corespondente.md`
- `docs\cercetare\legatura_linie_retur.md`
- `docs\cercetare\rec_d42_efactura.md`
- `docs\cercetare\s5c_factura_din_proforma.md` (sectiunea `VANZARI_CORESP`)
- PL/SQL: `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql`
## 0-bis. Constatare centrala care schimba premisa din plan
**Mecanismul S9 (planificat) NU e acelasi cu mecanismul deja existent de editare (#6).** Astea sunt
doua cai distincte, si asta conteaza pentru fiecare consumator de mai jos:
- **#6, "editare directa"** (`frm_modific2024`/`omodificari.vc2`, `afisjurcom.do_modifica`,
`pack_contafin.finalizeaza_modificare_nota`): documentul vechi (identificat prin `cod`) primeste
`STERS=1` in `ACT`/`RUL`, se scrie un document nou cu `cod` nou, apoi
**`pack_facturare.actualizeaza_vanzari(V_COD_VECHI, V_COD_NOU)`**
(`ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql:16012-16022`) face
`UPDATE VANZARI SET COD = V_COD_NOU, STERS = 0 WHERE COD = V_COD_VECHI` —
**randul `VANZARI` e REFOLOSIT, `ID_VANZARE` NU SE SCHIMBA**, doar `COD`. In continuare,
`finalizeaza_modificare_nota` face si `UPDATE atasamente_vanzari SET cod = lnCodNou WHERE cod =
tnCod` (`rec_modific2024.md:126`, confirmat `fisier:linie`). Acesta e mecanismul deja **livrat in
productie** (git log: `#6 editare factura emisa`, changelog 2.11.15/2.11.16).
- **#13 S9 (planificat, subiectul acestei cercetari)**: reemiterea merge **pe drumul normal de
emitere**, `scrie_factura2` -> `finalizeaza_factura` -> `scrie_in_vanzari`, care face
`INSERT INTO VANZARI (...) VALUES (...) RETURNING ID_VANZARE INTO pack_facturare.nid_vanzare`
(`rec_cale_vanzari_detalii.md:99`, confirmat separat in planul S9: „reemiterea scrie prin
`pack_facturare`, pe acelasi drum ca emiterea", `plan_13...md:2936-2937`). Acesta e un rand **nou**,
cu **`ID_VANZARE` nou din secventa** — exact premisa data de team-lead. `oscrie_in_fisiere`
intervine in S9 **doar la stergerea** documentului vechi (`plan_13...md:2938`), nu si la scriere,
deci **`actualizeaza_vanzari`/sincronizarea prin `finalizeaza_modificare_nota` NU se declanseaza
pentru S9** — acel mecanism ramane specific caii #6, nu se mosteneste automat de S9.
**Consecinta directa**: orice legatura tinuta azi prin `cod` (realiniata gratis de mecanismul #6) e
**expusa** la regenerarea din #13, pentru ca S9 nu trece prin `actualizeaza_vanzari`. Fiecare sectiune
de mai jos noteaza explicit daca protectia #6 s-ar fi aplicat sau nu.
## 1. Inventarul exhaustiv al consumatorilor de ID_VANZARE
| # | Tabela/mecanism | Cheie folosita | Scriitor(i) | Cititor(i) | Clasificare |
|---|---|---|---|---|---|
| 1 | `ATASAMENTE_VANZARI` | `ID_VANZARE` (FK real `FK_AT_VANZ001` -> `VANZARI.ID_VANZARE`) + coloana `COD` (legacy, vezi §2) | `ofacturare_comun.prg:466` (VFP INSERT direct), `pack_facturare.scrie_atasamente_factura` (PL/SQL, `ff_...:13955-13988`) | `VATASAMENTE_VANZARI` (view, JOIN pe `id_vanzare`), `ROAGEST`/`ROAIMOB` `oproceduri_atasamente.prg` (`citeste_atasament_vanzari`, `arata_meniu_at_vanz` — cauta pe `cod` via view) | **(A) trebuie remigrat** — vezi §2 |
| 2 | `marcheaza_facturat` -> `VANZARI.FACTURAT`/`ID_UTILFACT` | `VANZARI_CORESP.ID_VANZARE_FACT` (documentul nou) leaga la sursa | `pack_facturare.marcheaza_facturat`, apelata din `finalizeaza_factura` (`ff_...:14827,14831`) | citit la filtrarea avizelor/comenzilor facturabile | **(C) nu conteaza pentru discontinuitatea ID_VANZARE-ului documentului editat** — vezi §3 (releaga sursa, nu documentul editat insusi) |
| 3 | `VANZARI_CORESP` | `ID_VANZARE_FACT`/`ID_VANZARE_AVIZ`, ambele pe `VANZARI.ID_VANZARE` | `pack_facturare.scrie_corespondente_vanzari`, singurul writer (`s5c_factura_din_proforma.md:92-96`) | `sterge_factura` (garda la stergere), afisare "provine din X" | **(A) trebuie remigrat daca documentul editat e parte a unui lant retur/aviz->factura** — vezi §3 |
| 4 | `VANZARI_CANTITATI` | `ID_VANZARE` (a avizului sursa, nu a facturii editate) | `scrie_cantitati_vanzari_avize`, apelata doar `ntip=4` | `marcheaza_facturat(V_VERIFICARE=1)` | **(C) nu conteaza** — vezi §3, tine de sursa, neatinsa de editarea facturii |
| 5 | `DOCUMENTE` | `ID_DOC` = `ID_FACT` (nu `ID_VANZARE`) | `SET_IDFACT`/INSERT in `SCRIE_IN_ACT` | `SET_IDFACT` cautare veche (inactiva) | **(C) confirmat fara legatura cu ID_VANZARE** — vezi §4, acoperit deja de `idfact_refolosire_si_documente.md`, nu se reface |
| 6 | eFactura (`ANAF_EFACTURA`, `EsteInEFactura`) | `VANZARI.ID_FACT` (nu `ID_VANZARE`) | — | `ofacturare_editare.prg`/`omodificari.vc2` | **(C) nu conteaza** — cheia e `ID_FACT`, care se pastreaza — vezi §5 |
| 7 | Listari/rapoarte facturi (`FACT_VFACTURI*`, grid cautare) | `ID_VANZARE` + `ID_FACT`/serie+numar, cautari mixte | — | multiple | **de verificat, vezi §5** — cele care cauta dupa serie+numar/ID_FACT raman corecte; cele care tin un `ID_VANZARE` stocat undeva (ex. favorite, ultima factura deschisa) s-ar rupe |
| 8 | Incasari/plati (`INCASARI`, `PLATI`, `IREG_PARTENERI`) | **de verificat** | — | — | **in lucru, vezi §6** |
## 2. ATASAMENTE_VANZARI
**Nu sunt documente incarcate de utilizator — sunt exporturi PDF AUTO-GENERATE ale documentului
tiparit** (factura/aviz/recapitulatie/invoice), salvate automat dupa listare. Dovada, pas cu pas:
- Scrierea porneste din `frm_facturi.do_listeaza_formular`/fluxul de listare, la
`COMUN\programe\ofacturare.prg:2102-2105`:
```
If poDate.nRelistare = 0 And poDate.eProforma = 0 AND poDate.nEFactura = 0 And poDate.nSalveazaAtasamente = 1
poDate.scrieAtasamente()
Endif
```
imediat dupa exportul PDF al recapitulatiei (`:2068`, `goExport.export2pdf('crsrecapitulatie',
'recapitulatie', .F., poDate.cDocAtasate)`) — `poDate.cDocAtasate` **e** numele cursorului
`crsoDateDocAtasate`, populat de motorul de export PDF, nu de un dialog de upload.
- `crsoDateDocAtasate` se creeaza gol la `ofacturare.prg:233`: `Create Cursor crsoDateDocAtasate
(nume_frx c(50), fisier w)` — nicio referinta la `GETFILE()`/`GETPICT()`/dialog de fisier in tot
`ROAFACTURARE`/`COMUN` legata de acest cursor (cautat explicit, zero potriviri).
- `scrieAtasamente` (`ofacturare_comun.prg:429-475`) clasifica `TIP` dupa numele raportului
(`FACTURA_VAL*`->2, `FACTURA*`->1, `INVOICE*`->3, `RECAPITULATIE`->4, `AVIZ*`->5) si scrie:
`INSERT INTO ATASAMENTE_VANZARI(ID_VANZARE, TIP, FORMAT, DOCUMENT, ID_UTIL) VALUES (?pnId, ...)`
(`:466`) — `pnId = poDate.nid_vanzare` (sau `nid_vanzare_retur` pentru cazul aviz->factura). Deci
scriitorul **foloseste exclusiv `ID_VANZARE`**, niciodata `COD`.
- Cititorii confirmati: `ROAGEST\COMUN\programe\oproceduri_atasamente.prg` (identic in `ROAIMOB`) —
`citeste_atasament_vanzari` (`SELECT document FROM atasamente_vanzari WHERE id_at_vanz=...`) si
`arata_meniu_at_vanz(tnCod,...)` (`SELECT ... FROM vatasamente_vanzari a WHERE a.cod = ...`,
`:56`) — ambele read-only, mecanism de "vezi documentele salvate pentru aceasta factura",
disponibil din ROAGEST/ROAIMOB (alte produse ale suitei, confirmand ca S11 trebuia sa caute in
toata suita, nu doar ROAFACTURARE).
**Structura reala (interogata pe schema vie `MARIUSM_AUTO`)**: `ATASAMENTE_VANZARI(ID_AT_VANZ PK
NOT NULL din secventa, ID_VANZARE NUMBER NULL, DOCUMENT BLOB, TIP, FORMAT, STERS NOT NULL, ID_UTIL,
DATAORA NOT NULL, ID_UTILS, DATAORAS, COD NUMBER NULL)`. FK real: `FK_AT_VANZ001` pe `ID_VANZARE ->
VANZARI.ID_VANZARE` (`PK_VANZARI`). Coloana `COD` **nu e scrisa de niciun cod curent** (scriitorii
gasiti folosesc doar `ID_VANZARE`) — e populata azi doar de mecanismul legacy #6
(`finalizeaza_modificare_nota`'s `UPDATE atasamente_vanzari SET cod = lnCodNou WHERE cod = tnCod`,
care **nu poate seta `cod` pe un rand care nu-l are deja** — e un realiniere, nu o initializare).
Pe schema de test `MARIUSM_AUTO`, toate cele 20 de randuri existente au `COD` populat si
`ID_VANZARE` NULL (probabil date vechi, dinainte ca `ID_VANZARE` sa fie coloana activa) — cf.
memoriei de proiect, **zero cazuri in date nu e dovada**, dar dovada de cod (scriitorii folosesc
doar `ID_VANZARE`) e independenta de date si sta singura.
**Cheia reala de legatura azi e `ID_VANZARE`, prin view**: `VATASAMENTE_VANZARI` (definitie
interogata direct din `ALL_VIEWS`):
```sql
select a.id_at_vanz, a.tip, decode(a.tip,1,'Factura',2,'Factura in valuta',3,'Invoice',
4,'Recapitulatie',5,'Aviz','Alt document') as tip_doc, b.cod
from atasamente_vanzari a
left join vanzari b on a.id_vanzare = b.id_vanzare
where a.sters = 0 and b.sters = 0
```
`cod` in view **nu e coloana stocata pe `atasamente_vanzari`** — e `VANZARI.COD` curent, calculat
live prin JOIN pe `ID_VANZARE`. Consumatorii din alta suita (`ROACONT\Programe\orap_terti.prg:1854`,
`ROACONTRACTE\Programe\oparteneri_contracte.prg:190,229` — `LEFT JOIN vatasamente_vanzari ... ON
a.cod = b.cod`, pentru afisarea unui numar de atasamente pe rand de factura) folosesc de fapt tot
`ID_VANZARE`, indirect prin acest JOIN.
**Ce se rupe la regenerare (S9, calea B din §0-bis)**: `atasamente_vanzari.id_vanzare` al randurilor
vechi ramane neschimbat, aratand spre `VANZARI` cu `STERS=1` dupa stergerea documentului vechi.
`WHERE b.sters = 0` din view **filtreaza acele randuri afara** — atasamentele **dispar tacit** din
orice interogare prin `VATASAMENTE_VANZARI` (inclusiv `arata_meniu_at_vanz` din ROAGEST/ROAIMOB),
desi BLOB-ul ramane fizic in tabel. Documentul nou (`ID_VANZARE` nou) nu are niciun atasament legat.
**Clasificare: (A) trebuie remigrat** — `UPDATE atasamente_vanzari SET id_vanzare = :id_nou WHERE
id_vanzare = :id_vechi AND sters = 0`, in aceeasi tranzactie ca restul regenerarii (acelasi tipar ca
`actualizeaza_vanzari` de la #6, dar pe `id_vanzare` in loc de `cod`, si trebuie scris nou — #6 nu
acopera acest caz, cf. §0-bis).
**Corectie fata de premisa din briefing**: nu e "pierdere de date reala" in sensul de date
introduse de utilizator si irecuperabile — snapshot-ul se poate regenera prin relistare (acelasi
mecanism care l-a creat prima data). Ce s-ar pierde real e **istoricul exact al PDF-ului trimis
clientului la momentul emiterii initiale** (relevant daca factura a fost deja trimisa/tiparita
inainte de editare) — merita remigrare oricum, ca sa nu se piarda urma, dar motivatia corecta e
"pastrarea unui audit trail", nu "date introduse de utilizator".
## 3. marcheaza_facturat / VANZARI.FACTURAT / VANZARI_CANTITATI / VANZARI_CORESP
**Inventarul FK declarat pe `VANZARI.ID_VANZARE`** (interogare directa pe schema `ACN`, cea reala —
`ALL_CONS_COLUMNS`/`ALL_CONSTRAINTS`, `r_constraint_name = PK_VANZARI`), confirma si extinde lista
din briefing:
| Tabela | Coloana | Constraint |
|---|---|---|
| `ATASAMENTE_VANZARI` | `ID_VANZARE` | `FK_AT_VANZ001` |
| `VANZARI_CORESP` | `ID_VANZARE_FACT` | `FK_VANZARI_CORESP_001` |
| `VANZARI_CORESP` | `ID_VANZARE_AVIZ` | `FK_VANZARI_CORESP_002` |
| `VANZARI_CURSURI` | `ID_VANZARE` | `FK_VANZARE_CURS_002` |
| `VANZARI_DETALII` | `ID_VANZARE` | `FK_VANZARE_DET001` |
| `REST_NOTE_PLATA` | `ID_VANZARE` | `FK_REST_NOTE_PLATA_004` |
| `IPS_VOYAGES_VANZARI` | `VZ_ID` | `FK_VOYAGES_VANZARI_2` |
Primele cinci erau asteptate (vezi §1-2 si mai jos). **Ultimele doua nu erau in lista din plan** —
descoperite prin FK, nu prin cautare de text, exact motivul pentru care inventarul trebuia facut pe
schema, nu doar pe cod. Ambele sunt module de business **specifice unui singur tip de document**
(`pack_facturare.ntip`), nu cai generale:
- **`REST_NOTE_PLATA`** — modul restaurant (`PACK_RESTAURANT`, `nTipFacturaRestaurant`). La
stergerea unei vanzari de tip restaurant, `sterge_factura` cheama deja
`pack_restaurant.sterge_vanzare(V_ID_VANZARE, V_ID_UTIL)` (`ff_...:5593`, in `CASE`-ul de la
finalul procedurii) — un hook dedicat, separat de logica generala. **Nu s-a gasit un hook simetric
„re-leaga la reemitere"** in codul citit (nu era in scop sa se citeasca tot `PACK_RESTAURANT` —
pachet separat, mii de linii). Clasificare: **(A) suspecta, needs follow-up dedicat** — afecteaza
doar documentele cu `ntip = nTipFacturaRestaurant`, deci doar daca #13 include si acest tip in
„regenerabile" (de confirmat in `COMUN\docs\tipuri_documente_facturare.md`, cf. S13).
- **`IPS_VOYAGES_VANZARI`** — modul specific schemei `ACN` (`PACK_ACN`, `nTipFacturaACN`), legat de
un tabel `IPS_VOYAGES_VANZARI`/`IPS_VOYAGE_MEMBERS_VANZARI`/`IPS_VVOYAGE_MEMBERS` (confirmat in
`ris_2024_04_09_01_ACN.sql:258-266`, JOIN pe `vz.id_vanzare = vv.vz_id`) — pare o extensie de
business pentru un client specific (calatorii/voiaje), nu parte din suita generica ROA. Acelasi
tipar: `sterge_factura` cheama `pack_acn.sterge_vanzare(...)` la stergere (`ff_...:5596-5600`,
`execute immediate` conditionat de `pack_migrare.ObjectExist('PACK_ACN')` — pachetul exista doar
pe schema ACN). Clasificare: **(A) suspecta, needs follow-up dedicat** — probabil in afara
perimetrului #13 (client unic, tip de factura special), dar trebuie confirmat, nu presupus.
**`VANZARI_CURSURI`** — cursul valutar al documentului. Scris de `pack_facturare.scrie_cursuri(nid_vanzare)`
(`rec_cale_vanzari_detalii.md:102`), apelat **in interiorul aceluiasi `scrie_in_vanzari`** care
genereaza noul `ID_VANZARE` la reemitere (S9 foloseste exact acest drum, cf. §0-bis). Deci un rand
nou `VANZARI_CURSURI` se scrie automat pentru noul `ID_VANZARE`, fara nicio interventie separata.
**Clasificare: (B)** — se reface singur, ca parte a drumului normal de emitere, nimic de adaugat.
**`VANZARI_DETALII`** — liniile facturii. E miezul a ceea ce regenerarea insasi scrie (INSERT direct
pe noul `ID_VANZARE`, cf. `rec_cale_vanzari_detalii.md:105-113`) — nu e un consumator "extern" care
sa se rupa, e obiectul regenerarii. **Clasificare: (B)**, deja acoperit de proiectarea S9/S10, nu se
reface aici.
### VANZARI_CORESP — cazul netratat inca de plan: documentul editat e EL INSUSI parte a unui lant
Planul (S11, `plan_13...md:3024-3027`) trateaza `VANZARI_CORESP` ca pe o lista simpla, dar
`sterge_factura` (apelata de S9 la pasul de stergere) arata ca situatia are **doua fete diferite**,
niciuna simpla:
**(i) Garda de blocare — editarea unui document care e SURSA pentru altul e azi IMPOSIBILA, nu
riscanta.** `sterge_factura` (`ff_...:5450-5494`) verifica, INAINTE de orice stergere:
```sql
SELECT COUNT(*) INTO V_NR_FACT_RETUR FROM VANZARI_CORESP
WHERE STERS=0 AND ID_VANZARE_AVIZ = V_ID_VANZARE AND TIP = 3;
IF V_NR_FACT_RETUR > 0 THEN RAISE_APPLICATION_ERROR(-20000, 'Pentru acesta factura s-au emis facturi
de retur. Trebuie sa stergeti mai intai factura de retur!'); END IF;
```
si analog pentru `TIP IN (1,2)` (aviz cu factura/aviz de retur emise pe el) si pentru avizele-sursa
ale unei „facturi din aviz" (subquery imbricat, `:5478-5494`). **Consecinta pentru S9**: daca
utilizatorul incearca sa editeze (regenereze) o factura care are deja o factura de retur emisa
pe ea, sau un aviz care are deja o factura/aviz de retur emis pe el, **pasul de stergere din
tranzactia S9 arunca `ORA-20000`, tranzactia face rollback, documentul vechi ramane intact** — nu
e coruptie silentioasa, e un esec curat, dar e o **limitare functionala reala**: aceste documente
nu pot fi editate prin regenerare deloc, cat timp garda ramane activa (si nu exista niciun motiv
funcțional sa fie dezactivata — ar contrazice exact protectia pe care garda o ofera azi). *De
verificat de S12*: ca mesajul de eroare Oracle ajunge inteligibil la utilizator prin formularul de
editare, nu ca o eroare tehnica generica.
**(ii) Legaturile in care documentul editat e chiar `ID_VANZARE_FACT`/`ID_VANZARE_AVIZ` — marcate
`STERS=1` la stergere, NU remigrate automat, dar potential rescrise de reemitere daca parametrii
sunt refurnizati corect.** La stergerea documentului vechi, `sterge_factura` executa neconditionat
(`:5582-5585`):
```sql
UPDATE VANZARI_CORESP SET STERS = V_STERS
WHERE ID_VANZARE_FACT = V_ID_VANZARE OR ID_VANZARE_AVIZ = V_ID_VANZARE;
```
— orice legatura in care documentul vechi apare pe oricare parte devine `STERS=1`. **Nu exista cod
care sa recreeze automat legatura pentru noul `ID_VANZARE`.** Dar exista o cale prin care se
recreeaza **corect, de la sine**, daca S9 e proiectat sa refoloseasca drumul normal: `finalizeaza_factura`
(chemata de reemiterea normala) are un `CASE` pe `pack_facturare.ntip` care scrie din nou
corespondenta (`WHEN ntip=4: scrie_corespondente_vanzari(1)`; `WHEN ntip=24:
scrie_corespondente_vanzari(2)`; `WHEN ntip IN (8,9): scrie_corespondente_vanzari(3)`,
`ff_...:14823-14836`) — **daca** S9 seteaza `pack_facturare.ntip` la aceeasi valoare ca documentul
original SI re-populeaza `pack_facturare.clistaid`/`clistaid_avize` cu lista de `id_vanzare` sursa
originala **inainte** de reemitere, corespondenta se scrie natural, cu noul `ID_VANZARE_FACT`.
**Sursa lista originala e recuperabila** din randurile `VANZARI_CORESP` (acum `STERS=1`) ale
documentului vechi, citite INAINTE de stergere in aceeasi tranzactie — un pas suplimentar pe care
proiectarea S9 trebuie sa-l includa explicit, nu e „gratis". **Clasificare: (A) trebuie remigrat
— dar prin re-derivare + refolosirea mecanismului existent, nu prin UPDATE direct pe `VANZARI_CORESP`**
(un UPDATE direct ar trebui sa distinga cu grija cele doua roluri — FACT vs AVIZ — si ar risca sa
resusciteze legaturi catre documente inca sterse din alte motive; re-emiterea naturala prin `ntip`+
`clistaid` e mai sigura, pentru ca refoloseste exact logica deja validata de emiterea normala).
### marcheaza_facturat — pentru sursa documentului editat, nu pentru documentul insusi
`marcheaza_facturat` (`ff_...:15381-15418`) actioneaza pe **sursa** (avizul din care s-a facturat,
sau avizul-parinte al unui aviz de retur), nu pe documentul care se editeaza. La stergerea
documentului vechi (S9, pasul de stergere), pentru `V_TIP=4`/`V_TIP=24`, `sterge_factura` reseteaza
deja `FACTURAT=0`/`ID_UTILFACT=NULL` pe sursa (`:5504-5510`, `:5525-5533`) si marcheaza
`VANZARI_CANTITATI.STERS=1` pentru cantitatile consumate (`:5517-5523`, `:5535-5540`) — sursa e deci
**eliberata** corect de mecanismul EXISTENT, neschimbat. La reemitere, daca `ntip`/`clistaid_avize`
sunt refurnizate corect (acelasi argument ca la VANZARI_CORESP mai sus), `finalizeaza_factura`
cheama din nou `scrie_cantitati_vanzari_avize` + `marcheaza_facturat` (`:14825-14827`,`:14831`),
**reconsumand** sursa sub noul `ID_VANZARE_FACT`. **Clasificare: (C) — mecanismul deja exista si
functioneaza simetric (elibereaza la stergere, reconsuma la scriere), CONDITIONAT de aceeasi
cerinta ca la VANZARI_CORESP: S9 trebuie sa refurnizeze `ntip` si `clistaid`/`clistaid_avize`
originale la reemitere.** Aceasta e exact conditia pe care S12 o testeaza explicit („sursa eliberata
si reconsumata", `plan_13...md:3037`) — S11 confirma DE CE mecanismul poate functiona (nu e nevoie
de cod nou pentru asta), dar nu inlocuieste testul S12.
## 4. DOCUMENTE / ID_DOC — legatura cu ID_VANZARE
**Confirmat: fara legatura.** `DOCUMENTE(ID_DOC, ID_UTIL, DATAORA, TVA_INCASARE, SERIE_ACT, NRACT,
DATAACT, DATAIREG, ID_CTR, ID_SET, STERS, ...)` — INSERT-ul complet citat in
`idfact_refolosire_si_documente.md:143-148` (`PACK_CONTAFIN.pck:788-817`, cod activ) nu are nicio
coloana `ID_VANZARE`. Cheia `ID_DOC = ID_FACT`, care se PASTREAZA la regenerare (decizie E/F, deja
data). Acest raport nu reface analiza — deja acoperita exhaustiv de
`docs\cercetare\idfact_refolosire_si_documente.md` (S9, punctele A-C), care stabileste separat
conditiile pentru pastrarea `ID_FACT` (variabila noua de sesiune in `SET_IDFACT` + upsert real in
`DOCUMENTE`). **Clasificare: (C) — confirmat, fara actiune ceruta de S11.**
## 5. Borderou eFactura si listari
**eFactura: cheia e `ID_FACT`, nu `ID_VANZARE` — confirmat cu dovada proprie, independenta.**
`EsteInEFactura` (`COMUN\programe\ofacturare_editare.prg`, apelata din `ofacturare_comun.vc2:3764`
cu `lnIdFact = crsfacturi.id_fact`) verifica prezenta documentului in `ANAF_EFACTURA` **pe
`VANZARI.ID_FACT`**, nu pe `id_vanzare` — confirmat explicit ca eroare corectata in
`rec_d42_efactura.md:81-109` (implementarea initiala folosea gresit `id_vanzare`, corectata dupa
verificare pe date: `id_fact` si `id_vanzare` sunt spatii de ID complet diferite, 0 coincidente pe
142 facturi testate). **Cum `ID_FACT` se pastreaza la regenerare (decizie deja luata), `EsteInEFactura`
continua sa functioneze corect pe documentul reemis, fara nicio schimbare.** Aceeasi concluzie se
aplica probabil borderoului eFactura insusi (cautarea documentelor de trimis/trimise), dar
**construirea borderoului nu a fost citita in acest raport** (in afara scopului — cheia `ID_FACT`
fiind deja confirmata stabila, riscul e mic, dar afirmatia stricta „borderoul il gaseste corect"
ramane de verificat direct pe cod la implementare, nu doar dedusa). **Clasificare: (C), cu rezerva
de verificare directa a borderoului la implementare.**
**Listari/grid cautare facturi**: cursoarele de grid (`crsFacturi`, `crsFacturiOrd`,
`ofacturare_comun.vc2:3982,4134-4145,4983`) se reconstruiesc live din Oracle la fiecare deschidere
a formularului de listare, filtrate pe `sters=0` — nu tin niciun `id_vanzare` persistat intre
sesiuni. Documentul reemis (nou `id_vanzare`, acelasi `id_fact`/serie/numar) apare normal la
urmatoarea reincarcare a gridului. **Singurul risc identificat, nu confirmat ca problema reala**:
daca undeva in cod exista un `id_vanzare` **retinut pe termen lung** in afara sesiunii curente a
formularului (ex. „ultima factura deschisa", favorite, shortcut) — nu s-a gasit niciun asemenea
mecanism in codul citit (`ofacturare_comun.vc2`, `ofacturare.prg`), dar nici nu a fost cautat
exhaustiv in tot `ROAFACTURARE` (in afara bugetului acestei cercetari). **Clasificare: (C),
neconfirmat ca risc real — verificare suplimentara recomandata daca timpul permite.**
## 6. Incasari/plati si riscuri finale
**Cautare directa (negativa, dar utila): niciun tabel de incasari/plati nu are FK declarat pe
`VANZARI.ID_VANZARE`.** Interogarea exhaustiva `ALL_CONS_COLUMNS`/`ALL_CONSTRAINTS` pe schema `ACN`
(tabelul din §3) e completa pentru FK-uri declarate — `INCASARI`, `PLATI`, `IREG_PARTENERI` nu apar
in acea lista. Cautare text suplimentara (`grep -rn "ID_VANZARE"` filtrat pe fisiere cu
"incasari"/"plati"/"chitant" in nume, in tot `D:\ROA\DATABASE\SCRIPTURI_CLAR`) — **zero rezultate**.
Coerent cu arhitectura deja cunoscuta: incasarile/platile se leaga de facturi prin **`ID_FACT`**
(coloana pe `ACT`/`IREG_PARTENERI`, cf. `idfact_refolosire_si_documente.md`), nu prin `ID_VANZARE`
— `ID_FACT` se pastreaza la regenerare, deci **incasarile/platile nu sunt afectate structural**.
**Clasificare: (C), cu dovada dubla (schema + text), coerenta cu memoria de proiect „zero cazuri in
date nu e dovada" — aici insa e absenta de FK + absenta de text, nu absenta de date, deci e o
dovada structurala, nu doar un data point.**
## Rezumat clasificari
| Consumator | Clasificare | Actiune ceruta |
|---|---|---|
| `ATASAMENTE_VANZARI.ID_VANZARE` | **(A)** | `UPDATE ... SET id_vanzare=:nou WHERE id_vanzare=:vechi AND sters=0`, in tranzactia S9 |
| `VANZARI_CORESP` (documentul editat ca FACT/AVIZ al altui lant) | **(A)**, prin re-emitere naturala | S9 trebuie sa citeasca `ntip`+lista sursa originala INAINTE de stergere si sa le refurnizeze la reemitere |
| `marcheaza_facturat`/`VANZARI_CANTITATI` (sursa documentului editat) | **(C)**, conditionat | functioneaza automat DACA `ntip`/`clistaid` sunt refurnizate (acelasi mecanism ca mai sus) |
| `VANZARI_CURSURI` | **(B)** | se rescrie automat de `scrie_in_vanzari`, nimic de facut |
| `VANZARI_DETALII` | **(B)** | e obiectul regenerarii, acoperit de S9/S10 |
| `DOCUMENTE`/`ID_DOC` | **(C)** | confirmat fara legatura, acoperit de `idfact_refolosire_si_documente.md` |
| eFactura (`EsteInEFactura`, `ANAF_EFACTURA`) | **(C)** | cheie `ID_FACT`, pastrat — verificare directa a borderoului recomandata la implementare |
| Listari/grid facturi | **(C)** | cursoare live, fara stare persistata gasita |
| Incasari/plati | **(C)** | fara FK, fara referinta text — cheie e `ID_FACT` |
| `REST_NOTE_PLATA` (modul restaurant) | **(A)** suspecta | needs follow-up dedicat, `PACK_RESTAURANT` necitit integral |
| `IPS_VOYAGES_VANZARI` (modul ACN specific client) | **(A)** suspecta | needs follow-up dedicat, `PACK_ACN` necitit integral, posibil in afara perimetrului #13 |
## Riscuri si ce ramane de decis de Marius
1. **Editarea documentelor care sunt sursa unui lant retur/aviz e azi BLOCATA, nu doar riscanta.**
`sterge_factura` arunca `ORA-20000` daca documentul editat are deja facturi/avize de retur emise
pe el (§3.i). Nu e o eroare de proiectare — garda protejeaza integritatea lantului — dar
inseamna ca „editare prin regenerare" **nu va functiona deloc** pentru aceste documente, cat timp
utilizatorul nu sterge intai documentele-copil. **De decis**: acceptat ca limitare (cu mesaj
clar in UI, tradus din eroarea Oracle), sau se doreste alt comportament?
2. **Recuperarea `VANZARI_CORESP`/`marcheaza_facturat` la reemitere depinde de un pas pe care planul
nu-l mentioneaza explicit**: citirea listei sursa originale (`ID_VANZARE_AVIZ`/`ID_VANZARE_FACT`
din randurile `VANZARI_CORESP` ale documentului vechi) **inainte** de stergere, si refurnizarea
ei ca `pack_facturare.clistaid`/`clistaid_avize` la reemitere. Fara acest pas, corespondenta si
`marcheaza_facturat` **nu se scriu deloc** pentru documentul reemis (nu eroare, ci scriere lipsa
silentioasa) — de adaugat explicit in proiectarea S9, nu presupus „vine gratis" din drumul normal.
3. **`ATASAMENTE_VANZARI` nu e „date de utilizator pierdute"**, cf. §2 — e un audit trail de
PDF-uri auto-generate la listare. Remigrarea (`UPDATE ... SET id_vanzare`) e simpla si ieftina,
dar motivatia corecta pentru Marius e „pastrarea istoricului tiparit", nu „pierdere de date
introduse manual" — poate schimba prioritatea relativa fata de alte itemi din S11/S12.
4. **`REST_NOTE_PLATA` si `IPS_VOYAGES_VANZARI`** raman needs-investigation — descoperite prin FK,
nu prin text, deci nu erau in raza cautarilor anterioare (nici in planul S11 original). Daca
tipurile de document asociate (`nTipFacturaRestaurant`, `nTipFacturaACN`) nu sunt in domeniul
„regenerabile" al #13 (de confirmat in `tipuri_documente_facturare.md`, S13), riscul dispare de
la sine — dar asta trebuie confirmat, nu presupus.
5. **Borderoul eFactura insusi** (nu doar `EsteInEFactura`) nu a fost citit direct — cheia `ID_FACT`
fiind stabila, riscul e mic, dar afirmatia din *Gata cand* a S11 („documentul reemis se regaseste
corect in borderoul eFactura") merita o verificare punctuala pe cod la implementare, nu doar
dedusa din `EsteInEFactura`.
## STARE / CE RAMANE
**Cercetare incheiata pentru toate cele 7 puncte cerute de briefing**, cu dovada `fisier:linie` pe
fiecare afirmatie portanta: inventar exhaustiv (via FK Oracle + cod), `ATASAMENTE_VANZARI` (sectiune
proprie, cu corectia premisei „date de utilizator"), `marcheaza_facturat`/`VANZARI.FACTURAT`/
`VANZARI_CANTITATI`, `DOCUMENTE`/`ID_DOC` (confirmat, fara redeschidere), borderou eFactura si
listari, riscuri finale.
**Constatare centrala**: mecanismul S9 planificat (regenerare cu `ID_VANZARE` nou, pe drumul normal
de emitere) e **diferit** de mecanismul #6 deja livrat (`actualizeaza_vanzari`, reutilizeaza acelasi
`ID_VANZARE`, doar `COD` se schimba) — deci nicio protectie construita pentru #6 nu se mosteneste
automat de S9. Singurul consumator care chiar are nevoie de un `UPDATE` explicit nou este
`ATASAMENTE_VANZARI` (clasificare A simpla). `VANZARI_CORESP`/`marcheaza_facturat` se pot rezolva
**fara cod PL/SQL nou**, refolosind mecanismul existent (`finalizeaza_factura`'s `CASE` pe `ntip`),
**daca** S9 e proiectat sa citeasca si sa refurnizeze parametrii sursei originale — asta e o cerinta
de design care trebuie scrisa explicit in S9, nu deductibila implicit.
**Neverificat, ramas pentru follow-up** (declarat, nu ascuns): corpul complet al `PACK_RESTAURANT`/
`PACK_ACN` (pentru `REST_NOTE_PLATA`/`IPS_VOYAGES_VANZARI`), borderoul eFactura citit direct (nu doar
`EsteInEFactura`), o cautare exhaustiva de „id_vanzare retinut pe termen lung" in tot codul VFP
(favorite/shortcut-uri), si confirmarea in `tipuri_documente_facturare.md` a caror tipuri intra
efectiv in perimetrul „regenerabile" al #13 (ar elimina sau confirma riscurile 1 si 4).
Zero modificari de cod, zero write-back, zero `git_sync.ps1`/`txt2vcx.ps1`, zero commit. Pe Oracle
doar `SELECT` (schema `MARIUSM_AUTO`, interogari pe `ALL_TAB_COLUMNS`/`ALL_CONSTRAINTS`/`ALL_VIEWS`/
`ALL_SOURCE`, plus `SELECT` de numarare pe date de test — niciuna cu efect de scriere).