# Verificare adversariala — golul ntip=4 si "ramurile de aviz" (contabilizeaza_articol) Verifica raportul `docs/cercetare/gol_ntip4_factura_din_avize.md`. Rol: incercare de infirmare, nu confirmare. Toate citatele de mai jos sunt re-verificate direct in aceasta runda pe `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql` (17217 linii) si pe `COMUN\clase\ofacturare.vc2` (ambele copii, `frm_facturare_articole` ~13967-14500 si `frm_facturare_articole2` ~18003-18500). Status: **TERMINAT**. ## Corectie structurala prealabila — cei "3 apelanti" ai `contabilizeaza_articol` sunt gresit numiti Toate rapoartele anterioare (`canal_cont_venit_fara_politica.md:67`, `nota_contabila_fara_politica.md:103`, si implicit raportul verificat) numesc cei 3 apelanti interni `scrie_factura2`, **`scrie_factura_avize_retur`**, `scrie_aviz_retur`. **Gresit pentru al doilea.** Verificare directa pe granitele reale (`PROCEDURE ...` / `END ...`): ``` ff_...:6264 PROCEDURE scrie_factura_avize_retur(... ff_...:6657 END scrie_factura_avize_retur; ff_...:6692 PROCEDURE scrie_factura_avize(... ff_...:7058 END scrie_factura_avize; ff_...:7085 PROCEDURE scrie_aviz_retur(... ff_...:7171 END scrie_aviz_retur; ``` Apelul de la `ff_...:6858` (`pack_facturare.contabilizeaza_articol(tab_detalii(i));`, in interiorul `IF articole_aviz(j).custodie = 1 THEN`) cade **intre 6692 si 7058** — deci apartine lui **`scrie_factura_avize`** (fara `_retur`), nu lui `scrie_factura_avize_retur` (care se termina la 6657, cu 200+ linii inainte). `scrie_factura_avize_retur` **nu cheama deloc** `contabilizeaza_articol` — corpul ei (6264-6657) insereaza direct in `VANZARI_DETALII_TEMP` din `VANZARI_DETALII` (randurile avizului sursa deja existente), fara sa treaca prin `adauga_articol_factura` sau `contabilizeaza_articol`. **De ce conteaza**: `scrie_factura_avize` e exact handler-ul Oracle pentru `ntip=4` ("facturare din aviz") — apelat din VFP la `ofacturare.vc2:14318` (`Case poDate.Tip = 4`). Deci al doilea apel real catre `contabilizeaza_articol` **e in interiorul propriului handler `ntip=4`** (pentru randurile `custodie=1`), nu intr-un flux separat "avize+retur". Cei 3 apelanti reali sunt: | Apel | Procedura reala | Cand se ajunge la ea din VFP | |---|---|---| | `ff_...:6141` | `scrie_factura2` | `Case Inlist(poDate.Tip,3,21,25,28,42,47)` sau `Otherwise` (`ofacturare.vc2:14332,14361`, identic la `:18330,18361`) — calea principala pentru aproape toate tipurile, inclusiv avizele | | `ff_...:6858` | `scrie_factura_avize` | `Case poDate.Tip = 4` (`:14301,14318`) — doar pentru randurile `custodie=1` ale unei facturi din aviz | | `ff_...:7140` | `scrie_aviz_retur` | **Niciun apel gasit in `COMUN\` din VFP** (`Grep` pe tot `COMUN` si pe tot proiectul — zero rezultate in cod, doar in rapoarte). Posibil cod mort/apelat din alt produs; nu afecteaza verdictele de mai jos, pentru ca `scrie_factura2` singura e suficienta sa dovedeasca A1a. | Corectia nu schimba verdictul general al A1a (avizele *ajung* la `contabilizeaza_articol`), dar schimba **prin ce drum** — relevant pentru oricine ar urma sa scrie cod pe baza acestor rapoarte. ## A1. Ramurile de AVIZ raman atinse si ramura noua le-ar scrie SCD gresit **Verdict: CONFIRMAT, dar mai ingust decat sustine raportul.** ### A1a. Ajunge `contabilizeaza_articol` sa fie apelata pe un AVIZ? **DA, confirmat**, prin `scrie_factura2`. Ruta VFP (`ofacturare.vc2:14282-14389`, identic la `:18enable...`, verificata in ambele copii ale formularului): ``` Case poDate.eProforma = 1 -> scrie_proforma Case poDate.Tip = 4 -> scrie_factura_avize && facturare din aviz Case Inlist(poDate.Tip,3,21,25,28,42,47) -> scrie_factura2 && din comenzi / avize din comenzi Otherwise -> scrie_factura2 && tot restul (incl. 29, 22, 24, 27...) ``` In interiorul `scrie_factura2` (`ff_...:6072-6142`), CASE-ul propriu **intercepteaza unele `ntip` inainte** de a ajunge la `contabilizeaza_articol`: ``` WHEN ntip IN (23,25,30,41) THEN transfera_articol(...) -- NU contabilizeaza_articol WHEN ntip IN (42,47) THEN descarca_gestiune(...) direct -- NU contabilizeaza_articol WHEN ntip IN (2,6,52) AND id_rata<>0 THEN contabilizeaza_rata(...) ELSE contabilizeaza_articol(...) -- aici ajung 28, 29, 21, 22, 24, 27, 3, ... ``` Deci `ntip=28` si `ntip=29` **chiar ajung** la `contabilizeaza_articol` (prin `scrie_factura2`, ramura `ELSE`) — asta confirma miezul A1a. Dar `ntip IN (23,25,30,41,42,47)`, desi trec prin `scrie_factura2` (sunt in lista VFP `Inlist(3,21,25,28,42,47)`), **nu ajung niciodata** la `contabilizeaza_articol` — sunt deviate mai devreme, in CASE-ul propriu al lui `scrie_factura2`, spre `transfera_articol`/ `descarca_gestiune`. Vezi corectia la sectiunea 3 (tabelul per-`ntip`). ### A1b. Poate un articol fara politica sa fie adaugat pe un aviz? **DA, confirmat structural**, pe doua cai distincte in `adauga_articol_factura` (`ff_...:5052-5203`): - `WHEN ntip IN (3,21,28,42,47)` (`:5053-5078`): cauta in `COMENZI_ELEMENTE` dupa `ID_COMANDA + ID_ARTICOL + PRET` — **fara nicio referinta la `V_ID_POL`** in `WHERE`. Un articol fara politica poate gasi potrivire aici daca exista elementul de comanda corespunzator (comanda + articol + pret identice), indiferent de politica. **Fara handler `EXCEPTION`** — la fel ca ramura `ntip=4`, dar aici absenta handler-ului nu conteaza pentru `id_pol`, pentru ca filtrul nu-l foloseste. - `ELSE` (`:5187-5203`, bucket-ul implicit pentru orice `ntip` neacoperit de ramurile speciale — include `29` si restul avizelor "simple"): **nicio interogare legata de politica** — ia direct `V_PRET_TEMP`/`V_ID_VALUTA_TEMP`/`V_PRETURI_CU_TVA_TEMP`/`V_IN_STOC_TEMP` (valorile deja calculate de VFP), plus o singura `SELECT` pe `JTVA_COLOANE` dupa `V_ID_JTVA_COLOANA` (nimic legat de `id_pol`). **Zero obstacol** pentru un articol fara politica pe aceasta ramura. Nu am gasit (si nu am cautat exhaustiv, la fel ca raportul original) formularul VFP concret care ar adauga azi un articol ad-hoc fara politica pe un aviz — premisa ramane, ca si in raportul original, mostenita din proiectul #13 (`canal_cont_venit_fara_politica.md`), nu re-derivata aici. Ce am putut confirma exhaustiv e partea Oracle: **daca** VFP trimite `V_ID_POL=NULL` pe aceste `ntip`, Oracle nu pune nicio piedica. ### A1c. `SCD` in blocul `:7398-7423` — hardcodat sau derivat? Citit integral (`ff_...:7398-7423`), confirmat identic cu citatul raportului, **linie cu linie**: ``` ff_...:7400-7406 WHEN ntip<=20 OR ntip IN (nTipFacturaHotel,nTipFacturaRestaurant, nTipNotaPlata,nTipVanzareRetail,48,49,51,52) THEN V_SCD := crs_rand_articol.scd; -- din politica (NOTE_CONTABILE.SCD) ff_...:7413-7417 WHEN ntip IN (28,29) THEN V_SCD := '461'; -- HARDCODAT, aviz catre clienti debitori ff_...:7418-7422 ELSE V_SCD := '418'; -- HARDCODAT, aviz generic ``` `V_SCC` (linia 7425) vine mereu din `crs_rand_articol.scc` (coloana notei de vanzari), **indiferent de ramura** — CASE-ul de mai sus decide doar `V_SCD`. Confirmat: hardcodarea exista exact cum spune raportul, fara offset de linie. **Nuanta importanta, omisa de raport**: proiectarea `canal_cont_venit_fara_politica.md:146` (sursa ramurii noi) **flagheaza deja, printr-o paranteza**, ca "ramurile aviz raman `'418'`/`'461'`, deja hardcodate azi la `ff_...:7415,7420`, independent de politica" — deci designul **e constient** de existenta acestor hardcodari si de faptul ca ar trebui pastrate, dar **nu da structura de cod concreta** (niciun `IF`/`CASE` pe `ntip` in tabelul "Continutul ramurii noi", sectiunea 3) care sa implementeze efectiv acea pastrare. Raportul verificat prezinta acest lucru ca pe o **descoperire noua** ("Gol sora... gasit in aceasta cercetare") — de fapt designul deja stia de riscul general, dar nu-l rezolvase in cod. Concluzia practica ramane aceeasi (ramura noua, asa cum e descrisa azi in proiectare, chiar ar hardcoda `SCD='4111'` fara conditionare pe `ntip` daca ar fi implementata literal dupa tabelul din sectiunea 3), dar caracterizarea "gol nou, neconsemnat" e inexacta. ### Corectie la tabelul per-`ntip` din raport (sectiunea 3) Raportul marcheaza `IN (28,29)` **si** "toate celelalte (`21,22,23,24,25,27,30,41,42,47,...`)" ca "Atinsa: DA". Pe baza rutarii reale prin `scrie_factura2` (A1a de mai sus): | `ntip` | Ajunge la `contabilizeaza_articol`? | Motiv | |---|---|---| | `28`, `29` | **DA** | `scrie_factura2` -> `ELSE` -> CASE intern `ntip IN(28,29)` -> `SCD='461'` | | `21`, `22`, `24`, `27`, `3` si alte "otherwise" nespeciale | **DA** (probabil) | cad in `ELSE` al lui `scrie_factura2` -> `ELSE` intern -> `SCD='418'` | | `23`, `25`, `30`, `41` | **NU** | interceptate in `scrie_factura2` de `WHEN ntip IN(23,25,30,41) THEN transfera_articol(...)` — nu ajung niciodata la `contabilizeaza_articol` prin acest apelant | | `42`, `47` | **NU** | interceptate de `WHEN ntip IN(42,47) THEN descarca_gestiune(...) direct` — la fel, nu ajung | Golul real e deci mai ingust decat "orice aviz": se limiteaza la avizele care cad in ramura `ELSE` a lui `scrie_factura2` (28, 29, si restul avizelor "simple" neexcluse), nu la `23,25,30,41,42,47`, care sunt structural neatinse de `contabilizeaza_articol` prin singurul apelant confirmat. (Nu exclud ca `scrie_aviz_retur`, al carei apelant VFP nu l-am gasit, sa trateze si aceste `ntip` — dar cum nu exista dovada ca e apelata deloc, nu pot confirma nici infirma pentru ea.) ## A2. Golul `ntip=46` (`nTipNotaPlata`) — `scrie_nota` sarita azi **Verdict: CONFIRMAT.** - Constanta: `ff_...:84 nTipNotaPlata VANZARI.TIP%TYPE := 46;` — **exact 46**, verificat direct, nu presupus. - Garda: `ff_...:7441 IF pack_facturare.nTip <> pack_facturare.nTipNotaPlata THEN` — inainte de apelul `scrie_nota` (`:7443-7467`) — citat exact, linie identica cu raportul. - Poate un `ntip=46` sa primeasca un articol fara politica? **DA**, prin acelasi bucket `ELSE` (`ff_...:5187-5203`) al `adauga_articol_factura` verificat la A1b — `nTipNotaPlata` nu e in niciuna din ramurile speciale (`3,21,28,42,47`, `4`, `45`, `V_OPT_FACTURARE=3`), deci cade in `ELSE`, care nu cere `id_pol` deloc. - Ajunge la `contabilizeaza_articol`? **DA** — `ntip=46` nu e proforma, nu e `Tip=4`, nu e in `Inlist(3,21,25,28,42,47)` -> `Otherwise` -> `scrie_factura2` -> nu e in `(23,25,30,41)`/`(42,47)`/ `(2,6,52)` -> `ELSE` -> `contabilizeaza_articol`. - Ramura noua (per `canal_cont_venit_fara_politica.md` sectiunea 3, pasul 1 "Apeluri, o singura data fiecare") descrie apelul `scrie_nota` **fara** sa mentioneze garda `ntip<>nTipNotaPlata` — deci, asa cum e scrisa azi proiectarea, ar apela necondiționat `scrie_nota` pentru un document `NotaPlata` cu linie `cont_venit`. Gol real, bine argumentat de raport. ## A3. `ntip=4` exclus prin `NO_DATA_FOUND` neprins la `adauga_articol_factura` **Verdict: CONFIRMAT**, cu toate liniile citate verificate exact, fara offset: - `ff_...:5080-5103` — ramura `WHEN ntip=4`, `WHERE A.ID_POL = V_ID_POL` (linia 5096 exact), fara `EXCEPTION`. Confirmat caracter cu caracter identic cu citatul raportului. - Semantica SQL `NULL = NULL` -> `UNKNOWN`, niciodata `TRUE`: standard, corect. - **Ordinea de apel confirmata direct pe VFP**: `do_scrie_articole` (`ofacturare.vc2:13967`) cheama `initializeaza_date_factura` (seteaza `ntip`), apoi in bucla `Scan` peste `crsfactura` cheama `adauga_articol_factura` (`:14069-14091`) pentru fiecare rand — **toate acestea ruleaza inainte** de `Do Case` (`:14282`) care alege `scrie_factura_avize`/`scrie_factura2`/etc. Deci un articol cu `V_ID_POL=NULL` pe `ntip=4` cade la `adauga_articol_factura` **inainte** ca `scrie_factura_avize` sa fie chemata — linia nu ajunge niciodata la `contabilizeaza_articol`. Confirma independent concluzia raportului. - **Semantica VFP `Nvl(Alltrim(Str(poArt.id_pol)),[NULL])`** (`ofacturare.vc2:14072`, identic `:18107`): in Visual FoxPro, `Str()` si `Alltrim()` **propaga `.NULL.`** cand primesc `.NULL.` ca argument (comportament standard, documentat al limbajului — orice functie "null-aware" aplicata pe `.NULL.` intoarce `.NULL.`, nu eroare si nu `"0"`). `Nvl(.NULL., [NULL])` inlocuieste explicit cu literalul caracter `NULL` (4 caractere), care ajunge **necotat** in textul SQL generat (concatenare directa, fara ghilimele in jur) — deci Oracle il interpreteaza ca si cuvantul-cheie `NULL`, nu ca string. Rezultat: `V_ID_POL` ajunge `NULL` in Oracle exact cand `poArt.id_pol` e `.NULL.` in VFP. Verificare bazata pe semantica standard VFP (nu am putut rula VFP live — masina partajata, conform interdictiei) — consistenta si cu tiparul deja folosit identic pentru alti parametri opționali pe acelasi apel (`id_gestiune`, `id_valuta_d`, `id_part_rez` etc., toate cu acelasi `Nvl(Alltrim(Str(...`). - **Neverificat** (nici in raportul original, nici aici): cum ajunge efectiv `poArt.id_pol` sa fie `.NULL.` pentru un articol fara politica — ramane premisa mostenita din proiectul #13, nu re-derivata in aceasta runda. ## A4. Numerele de linie — offset +17 sau identice? **Verdict: NICIUNA din cele doua afirmatii e o regula generala — depinde de setul de citate comparat.** - **Pentru citatele proprii ale raportului verificat** (re-testate direct aici): `adauga_articol_factura` header `:4989-5015`, ramura `ntip=4` `:5080-5103`, `contabilizeaza_articol` header `:7173`, CASE `:7398-7423`, hardcode `:7413-7422`, garda `:7441`, `nTipNotaPlata:=46` la `:84` — **toate identice**, zero offset. Raportul are dreptate pentru propriile sale citate. - **Dar exista un offset real, doar ca nu e +17 ci +9**, intre citatele mai vechi din `nota_contabila_fara_politica.md:100-104` (`ff_...:6150`, `:6867`, `:7149` pentru cele 3 apeluri `contabilizeaza_articol`) si pozitiile reale confirmate in aceasta runda pentru **aceleasi** apeluri (`6141`, `6858`, `7140`) — diferenta consecventa de **9 linii**, nu 17, si in directia opusa (citatul vechi e mai mare, nu mai mic). - Concluzia corecta: fisierul `PACK_FACTURARE.sql` a fost re-exportat de mai multe ori pe parcursul proiectului (cod adaugat/sters intre versiuni), asa ca **fiecare set de citate vechi are propriul offset fata de exportul curent — nu exista o constanta universala (nici 0, nici +17, nici +9)**. `handoff_13_formular_unificat.md:190` ("+17") si acest raport ("identic, fara offset") sunt ambele adevarate **doar pentru seturile de citate pe care le-au verificat fiecare** — nu se pot generaliza una peste alta. Disciplina corecta, pe care ambele rapoarte au respectat-o, e re-verificarea directa pe fisierul curent inainte de orice citare — nu presupunerea unui offset fix. ## Text de plan corectat (sectiunea 4 din raportul verificat, rescris) ``` **Ramura `ntip=4` (facturare din avize, handler real `scrie_factura_avize:6692-7058`, nu `scrie_factura_avize_retur` cum apare gresit in rapoartele anterioare) — exclusa structural, nu necesita cod suplimentar.** `adauga_articol_factura`, ramura `WHEN ntip=4` (`:5080-5103`), cauta randul sursa din `VANZARI_DETALII` prin `A.ID_POL = V_ID_POL`, fara handler de exceptie — cu `V_ID_POL=NULL` (exact cazul liniei fara politica), comparatia nu se poate potrivi niciodata, deci apelul cade cu `ORA-01403` la adaugarea articolului, in bucla `do_scrie_articole` (`ofacturare.vc2: 13967-14106`), care ruleaza intotdeauna inaintea `Do Case`-ului (`:14282`) ce ar chema `scrie_factura_avize`. Un articol fara politica nu poate fi, structural, adaugat pe un document `ntip=4`; ramura noua `cont_venit` nu are nimic de tratat aici. **Gol confirmat, de acoperit inainte de implementare — mai ingust decat s-a crezut initial**: ramurile de aviz care **efectiv** ajung la `contabilizeaza_articol` prin singurul apelant confirmat functional (`scrie_factura2`, apelat pentru `Inlist(3,21,25,28,42,47)` si pentru toate celelalte tipuri prin `Otherwise`) sunt cele care cad in `ELSE`-ul CASE-ului propriu al `scrie_factura2`: `ntip IN (28,29)` -> `SCD='461'`, restul (`21,22,24,27` si alte "otherwise" avize) -> `SCD='418'` (`:7413-7422`). **`ntip IN (23,25,30,41,42,47)` NU ajung la `contabilizeaza_articol`** prin acest apelant — sunt deviate mai devreme, in `scrie_factura2` insasi, spre `transfera_articol`/ `descarca_gestiune`, deci golul nu li se aplica (contabilizeaza_articol si ramura ei noua nu se executa niciodata pentru ele). `adauga_articol_factura` nu cere `id_pol` pentru niciunul din aceste `ntip` (foloseste calea "din comenzi", fara filtru pe `id_pol`, sau calea implicita `ELSE`, fara nicio interogare legata de politica) — deci un articol fara politica poate ajunge pe oricare din avizele `28,29,21,22,24,27` cu `cont_venit` populat. Designul deja semnalase acest risc printr-o paranteza (`canal_cont_venit_fara_politica.md:146`, "ramurile aviz raman 418/461"), dar nu-l implementase: ramura noua trebuie sa aleaga `SCD` in functie de `ntip` (pastrand `'461'` pentru `IN(28,29)`, `'418'` pentru restul avizelor atinse), nu sa hardcodeze `'4111'` necondiționat. **Gol confirmat separat**: ramura noua trebuie sa pastreze garda `IF ntip <> nTipNotaPlata` (`ntip=46`, `ff_...:7441`) inainte de a apela `scrie_nota` — azi sarita intentionat pentru documentele de tip "nota de plata", iar un articol fara politica poate fi adaugat si pe acest tip de document (`adauga_articol_factura`, bucket `ELSE`, fara cerinta de `id_pol`). **Defensiv (opțional)**: se poate adauga o garda explicita `IF cont_venit IS NOT NULL AND ntip = 4 THEN RAISE_APPLICATION_ERROR(...)`, dar e demonstrat redundanta — cazul e deja imposibil pe caile VFP cunoscute, blocat cu doua straturi independente inainte de a ajunge la `contabilizeaza_articol`. ``` ## Ce nu s-a putut stabili in aceasta runda (mostenit din raportul original, nu re-rezolvat) - Cum ajunge `poArt.id_pol` sa fie `.NULL.` in VFP pentru un articol fara politica pe un aviz — premisa proiectului #13, nu re-derivata. - Cine cheama `scrie_aviz_retur` (daca cineva) — cautare exhaustiva in `COMUN\` si in tot proiectul, zero rezultate; posibil cod mort sau apelat din alt produs al suitei ROA. - Comportamentul exact `goExecutor`/`oPrelucrareEroare()` la o exceptie Oracle neprinsa — nu urmarit in aceasta runda (mostenit ca gol si in raportul original). ## Handoff Verificare incheiata, toate cele 4 afirmatii + corectia structurala preliminara sunt in sectiunile de mai sus. Zero cod atins, zero write-back, doar `SELECT`/`Read`/`Grep` pe SQL si VFP text. Context consumat substantial (citire extinsa pe `ff_...sql` si `ofacturare.vc2`), dar verificarea s-a incheiat inainte de pragul de predare. --- ## Propagarea `CONT_VENIT` prin cei trei apelanti — verificare Intrebare noua de la team-lead: argumentul central al proiectarii (`canal_cont_venit_fara_politica.md`, sectiunea 1, `:63-69`) — "orice coloana noua pe `VANZARI_DETALII_TEMP` ajunge automat in `detalii_articol`, fara sa atingi cei 3 apelanti, pentru ca fac `SELECT * BULK COLLECT` intr-un `TABLE OF ...%ROWTYPE`" — se bazeaza pe lista de nume deja corectata mai sus. Verificat acum pe numele **reale** ale celor 3 apelanti (`scrie_factura2`, `scrie_factura_avize`, `scrie_aviz_retur`), fiecare citit direct, linie cu linie, in aceasta runda. ### 1-2. `scrie_factura2` (`:6020-6223`) ``` ff_...:6039-6040 TYPE tab_detalii_type IS TABLE OF vanzari_detalii_temp%ROWTYPE; tab_detalii tab_detalii_type; ff_...:6063 SELECT * BULK COLLECT INTO tab_detalii FROM VANZARI_DETALII_TEMP; ff_...:6141 pack_facturare.contabilizeaza_articol(tab_detalii(i)); ``` **`SELECT *` intr-un `TABLE OF VANZARI_DETALII_TEMP%ROWTYPE`, confirmat.** `CONT_VENIT` curge automat. ### 1-2. `scrie_factura_avize` (`:6692-7058`, handler-ul real `ntip=4`) ``` ff_...:6708-6709 TYPE tab_detalii_type IS TABLE OF vanzari_detalii_temp%ROWTYPE; tab_detalii tab_detalii_type; ff_...:6749 SELECT * BULK COLLECT INTO tab_detalii FROM VANZARI_DETALII_TEMP; ff_...:6858 pack_facturare.contabilizeaza_articol(tab_detalii(i)); -- doar pt. custodie=1 ``` **Acelasi tipar: `SELECT *` in `TABLE OF VANZARI_DETALII_TEMP%ROWTYPE`, confirmat.** Intre populare (`:6749`) si apelul catre `contabilizeaza_articol` (`:6858`), randul `tab_detalii(i)` e modificat doar pe doua campuri (`.cantitate`, `.id_rata`, `:6855-6856`) — `CONT_VENIT` ramane neatins, curge automat. Chiar daca numele apelantului real difera de ce credea proiectarea, **concluzia ei ("nu se ating deloc") ramane corecta pentru acest apelant**, doar numele era gresit. ### 3. `scrie_aviz_retur` (`:7085-7171`) ``` ff_...:7097-7098 TYPE tab_detalii_type IS TABLE OF vanzari_detalii_temp%ROWTYPE; tab_detalii tab_detalii_type; ff_...:7106 SELECT * BULK COLLECT INTO tab_detalii FROM VANZARI_DETALII_TEMP; ff_...:7140 pack_facturare.contabilizeaza_articol(tab_detalii(i)); -- doar pt. custodie=0 (ELSE la :7115) ``` **Acelasi tipar, confirmat.** Nu conteaza ca nu i-am gasit apelant VFP (ramane nedovedit ca se executa vreodata) — *daca* s-ar executa, `CONT_VENIT` ar curge automat si aici, deci nu schimba suprafata diff-ului indiferent de raspuns. ### Verdict pe argumentul proiectarii **Se salveaza.** Toti cei 3 apelanti reali (nu cei numiti gresit in rapoartele anterioare) folosesc identic `SELECT * BULK COLLECT INTO FROM VANZARI_DETALII_TEMP` — zero lista explicita de coloane, zero `%ROWTYPE` pe alta tabela, zero constructie camp-cu-camp. Concluzia proiectarii ("adaugi coloana pe `VANZARI_DETALII_TEMP`, `contabilizeaza_articol` o vede automat prin toti apelantii, fara sa atingi `scrie_factura2`/`scrie_factura_avize`/`scrie_aviz_retur`") **e corecta ca mecanism**, chiar daca doua din cele trei nume citate pentru ea erau gresite. Corectia de nume nu schimba nimic la suprafata de regresie a schemei — schimba doar la ce trebuie sa te uiti daca vreodata unul dintre cei trei apelanti isi schimba modul de populare a lui `tab_detalii`.