# S10 — Pretul re-derivat in `adauga_articol_factura`, ramura cu ramura ## Nota pe sursa folosita `docs\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql` **nu exista** (nici in `docs\`, nici urme in istoricul git — `docs\` e integral netracked). Fisierul cu **acelasi nume** exista insa la `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql` si a fost folosit ca sursa. Continutul `adauga_articol_factura` coincide structural cu ce descrie planul (aceeasi ordine de ramuri, aceleasi coduri de eroare `FACT-012/013/018`, acelasi `DECODE(A.PRET_UNITAR, 0, V_PRET_TEMP, A.PRET_UNITAR)`), dar liniile sunt deplasate cu **+17** fata de citatele din plan (corp `4989-5284` aici vs. `4972-5268` in plan; ramura de contract `5146-5185` aici vs. `:5129-5168` in plan) — probabil diferente de comentarii de antet intre cele doua exporturi. Toate citatele de mai jos sunt pe fisierul din `SCRIPTURI_CLAR`, verificat direct. ## Verdict (raspuns la intrebarea 4 — reemiterea) **Da, exista o ramura care suprascrie tacut pretul la orice apel, inclusiv la o eventuala reemitere: liniile provenite dintr-un contract cu `OPT_FACTURARE = 3` (sau `NULL`, care se implicit-eaza tot la 3).** Procedura nu are nicio notiune de "reemitere" — la fiecare apel cu acelasi `V_ID_CTR`, daca articolul are in `CTR_ARTICOLE.PRET_UNITAR` o valoare diferita de 0, acea valoare **inlocuieste** pretul trimis de VFP (`V_PRET_TEMP`), necontidionat de faptul ca linia a fost sau nu atinsa de utilizator pe ecran. Riscul se materializeaza doar daca pretul din contract s-a schimbat intre emiterea initiala si reemitere — daca n-a scazut, rezultatul e identic si nimeni nu observa diferenta pana cand se schimba. Pe toate celelalte ramuri (implicita, restaurant), pretul trimis de VFP e respectat ca atare. **Nu exista niciun parametru sau flag care sa opreasca re-derivarea** — raspunsul la intrebarea 5 e "nu exista". ## 1. Semnatura completa (corp, nu spec) `PACK_FACTURARE:4989-5015` (spec identica la `:537-563`, verificat doar ca prezenta, nu citat): ``` PROCEDURE adauga_articol_factura(V_ID_TEMP IN NUMBER, V_ID_ARTICOL IN NUMBER, V_SERIE IN VARCHAR2, V_EXPLICATIE IN VARCHAR2, V_ID_POL IN NUMBER, V_ID_GESTIUNE IN NUMBER, V_PRET_ACHIZITIE_TEMP IN NUMBER, V_PRETD IN NUMBER, V_ID_VALUTAD IN NUMBER, V_PRET_TEMP IN NUMBER, V_ID_VALUTA_TEMP IN NUMBER, V_PRETURI_CU_TVA_TEMP IN NUMBER, V_IN_STOC_TEMP IN NUMBER, V_CANTITATE IN NUMBER, V_DISCOUNT_UNITAR IN NUMBER, V_CONT IN VARCHAR2, V_CURS IN NUMBER, V_MULTIPLICATOR IN NUMBER, V_ID_JTVA_COLOANA IN NUMBER, V_ID_PART_REZ IN NUMBER, V_ID_LUCRARE_REZ IN NUMBER, V_PRETV_ORIG IN NUMBER, V_ID_VANZARE_SET IN NUMBER, V_ID_CTR IN NUMBER, V_ID_UTIL IN NUMBER, V_TAXCODE IN NUMBER DEFAULT NULL, V_LOT IN VARCHAR2 DEFAULT NULL) IS ``` Toti parametrii sunt **IN**, niciunul OUT/IN OUT — nu exista un canal de intoarcere a pretului recalculat catre VFP la momentul apelului (linia se citeste ulterior, la re-interogarea grilei). **`V_OPT_FACTURARE` nu e parametru.** E o variabila locala (`:5029`), calculata **in interiorul procedurii** din `CONTRACTE.OPT_FACTURARE`, folosind parametrul `V_ID_CTR` primit de la VFP (`:5039-5050`): ```sql IF pack_facturare.ntip IN (2, 6, 26, 52) THEN BEGIN SELECT NVL(OPT_FACTURARE, 3) INTO V_OPT_FACTURARE FROM CONTRACTE WHERE ID_CTR = V_ID_CTR; EXCEPTION WHEN NO_DATA_FOUND THEN V_OPT_FACTURARE := 4; END; END IF; ``` VFP nu trimite si nu poate influenta `V_OPT_FACTURARE` altfel decat prin `V_ID_CTR` (`poArt.id_ctr`, trimis `NULL` cand linia nu vine de pe contract). Pentru orice `pack_facturare.ntip` in afara lui `(2, 6, 26, 52)`, `V_OPT_FACTURARE` **ramane neinitializat** (blocul IF nu ruleaza deloc) — echivalent cu "nu conteaza", ramura de contract nu se poate nimeri. ## 2. Ce inseamna `V_OPT_FACTURARE` si cum se coreleaza cu VFP Din `PACK_FACTURARE` (alte proceduri, aceeasi coloana `CONTRACTE.OPT_FACTURARE`) si din `COMUN\clase\ofacturare.vc2` / `COMUN\programe\oproceduri_facturare.prg` (proprietatea locala `poArt.opt_facturare`, populata la citirea contractului, in oglinda cu coloana Oracle): | Valoare | Tip facturare | Dovada | |---|---|---| | `0` (sau lipsa contract) | Articol normal, nelegat de contract | `ofacturare.vc2:13055` `If poArticol.opt_facturare = 0` | | `1`, `2` | **Rata** (scadentar contract, `CTR_SCADENTAR`) — linia nu trece prin `adauga_articol_factura`, ci prin `adauga_rata_factura` (`ofacturare.vc2:14041-14050`) | `ofacturare.vc2:14041` `If Inlist(poArt.opt_facturare,1,2)`; `PACK_FACTURARE:2898,2915` (`CTR_SCADENTAR`, doar pt. `OPT_FACTURARE IN (1,2)`) | | `3` | **Articol de pe contract**, pret din `CTR_ARTICOLE` | `PACK_FACTURARE:2699,2820` (`CTR_ARTICOLE` doar pt. `OPT_FACTURARE = 3`); `ofacturare.vc2:14750` (`poDate.tip = 2 And poArticol.opt_facturare = 3`) | | `4` | Fallback intern cand contractul nu (mai) exista (`NO_DATA_FOUND`) | `PACK_FACTURARE:5047-5048` | VFP nu trimite `V_OPT_FACTURARE` ca parametru al `adauga_articol_factura` — coreleaza doar indirect, prin faptul ca proprietatea locala `poArt.opt_facturare` (citita din acelasi `CONTRACTE.OPT_FACTURARE` cand grila s-a populat) decide **ce RPC se apeleaza** (`adauga_rata_factura` pentru 1/2, `adauga_articol_factura` pentru orice altceva, inclusiv 3), nu ce ramura Oracle se executa in interior — aceea o recalculeaza serverul singur, din `V_ID_CTR`. ## 3. Ramura cu ramura pe `V_OPT_FACTURARE` (si pe `pack_facturare.ntip`, care are prioritate) `CASE` la `PACK_FACTURARE:5052-5220`. Ramurile 1-3 sunt selectate dupa `pack_facturare.ntip`, nu dupa `V_OPT_FACTURARE` — ramura 4 (contract) se testeaza **doar daca niciuna din primele trei nu s-a potrivit**. | Selector | Tip facturare | Pretul | Sursa re-derivarii | Citat | |---|---|---|---|---| | `ntip IN (3,21,28,42,47)` | Facturare/aviz din **comenzi** | **Re-derivat, dar constrans sa se potriveasca cu ce a trimis VFP** — `SELECT A.PRET ... WHERE A.PRET = V_PRET_TEMP` | `COMENZI_ELEMENTE` + `CRM_POLITICI_PRETURI`/`PRET_ART`, filtrat pe `A.PRET = V_PRET_TEMP`; daca nu exista rand cu exact acel pret, `NO_DATA_FOUND` **nu e tratat** — procedura pica cu eroare Oracle netratata | `:5053-5078` | | `ntip = 4` | Facturare din **avize** | **Re-derivat necondiționat, din documentul sursa** — `SELECT DISTINCT A.PRET ... INTO V_PRET` fara filtru pe pretul trimis | `VANZARI_DETALII` (linia din avizul sursa), filtrata pe articol/politica/gestiune/discount/cont, dar **nu** pe pret | `:5080-5103` | | `ntip = 45` | Facturare **restaurant** | **Respectat** — `V_PRET := V_PRET_TEMP` setat **inainte** de SELECT (`:5109`); SELECT-ul recalculeaza doar `V_PROC_TVAV` si `V_PRET_ACHIZITIE` (cost, nu pret de vanzare) | n/a pentru pret; TVA din `JTVA_COLOANE`, cost din `CRM_POLITICI_PRET_ART.PRETFTVA` | `:5104-5145` | | `V_OPT_FACTURARE = 3` (deci `ntip IN (2,6,26,52)` **si** contract cu `OPT_FACTURARE=3`/`NULL`) | Facturare/aviz **de pe contract** | **Re-derivat daca contractul are pret setat** — `DECODE(A.PRET_UNITAR, 0, V_PRET_TEMP, A.PRET_UNITAR)`; daca `PRET_UNITAR = 0` sau nu exista rand `CTR_ARTICOLE`/politica potrivita (`NO_DATA_FOUND`), cade pe `V_PRET_TEMP` | `CTR_ARTICOLE.PRET_UNITAR` (prin `CRM_POLITICI_PRET_ART`, `ID_POL_ART`) | `:5146-5185` (branch), `:5181-5184` (fallback `V_PRET_TEMP` in exceptie) | | `ELSE` (implicit — orice altceva, inclusiv linii normale fara contract) | Standard | **Respectat** — `V_PRET := V_PRET_TEMP` | n/a; TVA din `JTVA_COLOANE` dupa `V_ID_JTVA_COLOANA` trimis de VFP | `:5187-5203` | **Observatie de prioritate:** daca o linie e simultan "din comanda" (`ntip IN (3,21,28,42,47)`) si are si `V_ID_CTR` completat, ramura de comenzi castiga — `V_OPT_FACTURARE` nici nu se calculeaza (blocul de la `:5039` ruleaza doar pentru `ntip IN (2,6,26,52)`). Ramurile nu se pot suprapune in productie curenta, dar asta inseamna ca **orice extindere viitoare a lui `ntip`** (de ex. daca #13 introduce un tip nou de document care refoloseste `adauga_articol_factura` pentru reemitere) trebuie verificata explicit fata de acest `CASE` — un `ntip` nou care nu intra in niciuna din listele `(3,21,28,42,47)` / `4` / `45` cade automat fie pe ramura de contract (daca are `V_ID_CTR`), fie pe `ELSE`. ## 4. Reemiterea — detaliu (vezi si verdictul de mai sus) Procedura **nu primeste si nu poate primi** vreun semnal de tip "acesta e un apel de reemitere, nu recalcula". Comportamentul e identic la emiterea initiala si la orice apel ulterior cu aceiasi parametri. Riscul descris in plan (sectiunea H) se confirma integral pentru ramura de contract (`V_OPT_FACTURARE = 3`): daca `CTR_ARTICOLE.PRET_UNITAR` s-a modificat intre emiterea initiala si reemitere, factura reemisa va lua **pretul curent din contract**, nu pretul confirmat pe ecran de utilizator inainte de reemitere — chiar daca utilizatorul n-a atins linia. Pentru ramurile "avize" (`ntip = 4`) si "comenzi" (`ntip IN (3,21,28,42,47)`), acelasi risc structural exista (pretul se re-citeste din documentul sursa la fiecare apel), dar **nu sunt cazul confirmat de #13** — planul S10 spune explicit "se verifica pe factura din contract, care e cazul confirmat" — nu s-a cerut si nu s-a facut inventar suplimentar pentru daca fluxul de reemitere din #13 (etapa II, stergere+regenerare cu aceleasi linii) ar trece vreodata prin aceste doua ramuri. **De retinut daca #13 extinde reemiterea si la facturi/avize provenite din comanda sau din alt aviz** — pe ambele, re-derivarea e chiar mai stricta decat pe contract (ramura de comenzi cade cu eroare netratata daca pretul nu se potriveste exact; ramura de avize suprascrie necondiționat). ## 5. Mecanism de "nu re-deriva" **Nu exista.** Niciun parametru boolean, nicio valoare santinela, nicio ramura in `CASE` (`:5052-5220`) care sa respecte pretul primit *pentru ca i s-a cerut explicit*. Ramurile "implicita" si "restaurant" respecta pretul doar pentru ca structural nu au de unde re-deriva altceva (nu exista document sursa de recitit), nu pentru ca ar exista o comutare intentionata. Orice solutie de tip "pretul vine din formular, nu se re-deriva" (cum sugereaza planul, sectiunea H) **ar trebui implementata in VFP inainte de apel** (de exemplu, nu retrimite `V_ID_CTR` la reemitere daca vrei sa eviti ramura de contract) — nu exista un parametru in pachet pe care VFP l-ar putea seta ca sa dezactiveze re-derivarea, iar pachetul **nu se modifica** (decizia 27-bis, respectata — aceasta e o constatare, nu o propunere). ## 6. Discountul si TVA-ul - **Discountul (`V_DISCOUNT_UNITAR`) nu e niciodata re-derivat.** Parametrul intra direct in `INSERT INTO VANZARI_DETALII_TEMP (..., DISCOUNT_UNITAR, ...) VALUES (..., V_DISCOUNT_UNITAR, ...)` (`:5236`, `:5266`) — nicio ramura din `CASE` il citeste sau il modifica. Tratament **diferit** de pret: discountul e mereu respectat, indiferent de ramura. - **TVA-ul (`V_PROC_TVAV`) e mereu recalculat server-side, pe toate ramurile — dar din surse diferite, nu dintr-un parametru brut.** Nu exista parametru `V_PROC_TVAV_TEMP` in semnatura; VFP trimite doar `V_ID_JTVA_COLOANA` (un identificator de coloana de cota, nu cota insasi). Pe ramura implicita si pe cea de contract-fara-potrivire, cota se cauta in `JTVA_COLOANE` dupa acel ID (`:5188-5198`, `:5169-5179`); pe ramurile comenzi/avize/contract-cu-potrivire/restaurant, cota vine din documentul sursa sau din politica de pret (`:5058`, `:5083`, `:5150`, `:5114`). Deci TVA-ul are un tratament **mai strict** decat pretul: niciodata "pass-through" direct, intotdeauna o cautare, doar sursa cautarii difera pe ramura. ## 7. Cursul valutar si pretul in valuta - **Cursul (`V_CURS`) e mereu respectat ca valoare, pe toate ramurile.** Singura procesare e `DECODE(V_CURS, 0, 1, V_CURS)` la `INSERT` (`:5270`) — inlocuieste 0 cu 1, altfel scrie exact ce a trimis VFP. Procedura **nu interogheaza niciodata tabela `CURS`** pentru un curs "de azi" — nu are de unde sa recalculeze cursul chiar daca ar vrea. - **Identitatea valutei (`V_ID_VALUTA`, variabila locala, nu parametrul `V_ID_VALUTAD`) urmeaza acelasi tipar ca pretul, ramura cu ramura:** re-derivata din sursa pe comenzi (`C.ID_VALUTA`, `:5059`) si avize (`A.ID_VALUTA`, `:5084`), re-derivata din contract pe ramura `V_OPT_FACTURARE=3` (`B.ID_VALUTA`, `:5151`, cu fallback `V_ID_VALUTA_TEMP` in exceptie, `:5182`), respectata pe implicita si restaurant (`V_ID_VALUTA := V_ID_VALUTA_TEMP`, `:5110`, `:5201`). - **Consecinta pentru reemiterea unui document in valuta pe contract:** daca politica de pret a contractului (`CRM_POLITICI_PRET_ART`, prin `CTR_ARTICOLE.ID_POL_ART`) a fost schimbata intre timp la o alta valuta, reemiterea ar scrie articolul in **noua** valuta a politicii, dar cu **cursul** trimis de VFP (posibil cursul valutei vechi, daca VFP nu a fost actualizat sa retrimita cursul corect pentru noua valuta) — o sursa suplimentara de neconcordanta, nesemnalata explicit in plan. Nu s-a gasit nicio validare in procedura care sa verifice ca `V_CURS` corespunde valutei re-derivate `V_ID_VALUTA`. ## Completare: nota contabila a politicii Sursa: aceeasi, `contabilizeaza_articol` la `PACK_FACTURARE:7173-7547` (in fisierul din `SCRIPTURI_CLAR`; corpul relevant pentru articol simplu — nu compus — e la `:7391-7544`), plus `scrie_nota` la `:12329-12561`. ### 1. Cum ajunge de la `id_pol` la nota contabila — ia toate randurile setului, fara distributie `cursor_articol` (`:7218-7271`): ```sql FROM CRM_POLITICI_PRET_ART A LEFT JOIN CRM_POLITICI_PRETURI B ON A.ID_POL = B.ID_POL LEFT JOIN CRM_NOTE_VANZARI C ON B.ID_NOTA = C.ID_NOTA LEFT JOIN NOTE_CONTABILE D ON C.ID_SET = D.ID_SET WHERE A.ID_POL = detalii_articol.id_pol AND A.ID_ARTICOL = detalii_articol.id_articol ``` E un `JOIN` simplu pe `ID_SET`, **fara `ROWNUM`, fara agregare, fara filtru suplimentar pe `NOTE_CONTABILE`**. Daca setul are `N` randuri, cursorul intoarce `N` randuri pentru aceeasi combinatie `id_pol`/`id_articol`. Bucla care il consuma (`:7393-7542`, `OPEN cursor_articol; FETCH ...; WHILE cursor_articol%FOUND LOOP ... FETCH ...; END LOOP;`) executa **intregul corp — `scrie_nota`, `descarca_gestiune`, `scrie_discount` — o data pentru fiecare rand din set**, cu **aceeasi cantitate si acelasi pret intreg de fiecare data**, nu impartite intre randuri. Nu exista nicio coloana `ORDINE` in tot pachetul (cautare `ORDINE` in fisier: zero rezultate) si nicio logica de distributie procentuala intre randurile unui set. **Consecinta directa pentru reteta aprobata (J-quater):** daca politica tehnica pentru contul de venit ar ajunge sa foloseasca o nota al carei `ID_SET` are mai mult de un rand in `NOTE_CONTABILE` (cazul general — pana la 30 de randuri pe unele seturi din baza, per verificarea ta pe date vii), `contabilizeaza_articol` ar scrie **de N ori** aceeasi suma in contabilitate si ar apela `descarca_gestiune` de N ori pentru aceeasi linie de vanzare — dublare de venit si dublare de descarcare de gestiune, nu doar zgomot. Pasul 2 al retetei ("cauta o politica a carei nota are deja `SCC`-ul calculat") **trebuie sa garanteze un singur rand `NOTE_CONTABILE` per `ID_SET` ales**, nu doar un rand cu `SCC`-ul potrivit — verificarea facuta de tine pe cele 7 note active (exact un rand per set) e conditia care face reteta sigura azi, dar nu e impusa de cod, e o coincidenta a datelor curente. ### 2. `NOTE_CONTABILE.PTVA` — nu e citit deloc de `contabilizeaza_articol` Lista de coloane a `cursor_articol` (`:7230-7260`) selecteaza explicit `ID_NOTA, PRETURI_CU_TVA, ID_VENCHELT, ID_SECTIE, ID_SET, EXPLICATIE, SCD, ASCD, SCC, ASCC, CU_TVA, IN_VALUTA` din lantul `CRM_POLITICI_PRET_ART -> CRM_POLITICI_PRETURI -> CRM_NOTE_VANZARI -> NOTE_CONTABILE` — **`D.PTVA` nu apare in acest `SELECT`**. Coloana exista pe tabel (confirmat de datele tale vii — `21`, `5`, `0`), dar `contabilizeaza_articol` n-o citeste niciodata. Cota de TVA folosita efectiv in scriere e alta — vine din apelul catre `scrie_nota` (`:7444-7467`), unde parametrul `V_PTVA` primeste `detalii_articol.proc_tvav * 100 - 100` (`:7464`), adica **cota calculata deja in `adauga_articol_factura`** (din `JTVA_COLOANE` sau din documentul sursa, vezi sectiunea 3 de mai sus), nu din nota. Deci **raspunsul direct la intrebarea ta: daca articolul are 21% dar nota politicii are `PTVA=5`, nu se intampla nimic — `PTVA` de pe nota e complet ignorat, cota folosita e cea a articolului/documentului, nu a notei.** Coloana `NOTE_CONTABILE.PTVA` e moarta din perspectiva acestei proceduri (posibil folosita in alt modul, neverificat aici). ### 3. `CU_TVA` si `IN_VALUTA` de pe nota Ambele se citesc din `NOTE_CONTABILE` (`crs_rand_articol.cu_tva`, `crs_rand_articol.in_valuta`, `:7253`, `:7254-7260`) si se transmit mai departe la `scrie_nota` ca parametri (`V_CU_TVA`, `V_IN_VALUTA`), unde controleaza mecanic, nu semantic tot ce e legat de pret: - **`V_CU_TVA`** (`scrie_nota:12416-12422`): daca `= 0`, suma acumulata in `V_INCASAT_CALCUL` e `V_SUMA_FARA_TVA`; daca `= 1`, e `V_SUMA_CU_TVA`. Separat, la `:12537-12558`, **doar cand `V_CU_TVA = 1` se scrie si o linie separata de TVA** (`pack_facturare.scrie_tva(...)`, cont `4427`/etc.). Deci `CU_TVA` decide daca acest rand din notă genereaza o inregistrare contabila separata pentru TVA sau nu — nu suprascrie si nu recalculeaza cota, doar comuta daca linia de TVA se scrie. - **`V_IN_VALUTA`** (`scrie_nota:12391-12404`, `:12492-12507`): daca `= 1`, se calculeaza si `V_SUMA_VAL`/`V_SUMA_FARA_TVA_VAL`/etc. (sumele in valuta straina) si randul `ACT_TEMP` scrie `ID_VALUTA = V_ID_VALUTA` (valuta reala a articolului) si `CURS = V_CURS`; daca `= 0`, randul scrie `ID_VALUTA = pack_facturare.nid_moneda_nationala` si `CURS = 0`, indiferent de valuta reala a articolului. **Raspuns la "ce se intampla daca `IN_VALUTA=1` pe nota dar documentul e in lei":** nu apare nicio eroare si nicio validare incrucisata intre `IN_VALUTA` de pe nota si valuta reala a documentului — procedura calculeaza pur si simplu `V_SUMA_VAL` folosind `V_ID_VALUTA` si `V_CURS` primite din `detalii_articol` (care, pe un document in lei, sunt deja moneda nationala si curs implicit 1). Rezultatul practic: `ACT_TEMP.SUMA_VAL` se populeaza redundant (cu aceeasi valoare ca `SUMA`, scalata la curs 1) in loc sa ramana `0`, iar `ID_VALUTA` de pe randul contabil ramane oricum moneda nationala (pentru ca asta e `detalii_articol.id_valuta` pe un document in lei) — o inconsistenta cosmetica in `ACT_TEMP` (rand cu `SUMA_VAL` populat desi `CURS` real e 1), nu o eroare de suma. Relevant pentru politicile `SERVICII VALUTA` / `COMISION INTERMEDIERE` (`SCC=704`, candidate la pasul 2 al retetei): daca oricare document in lei ar ajunge sa foloseasca una din ele, ar produce astfel de randuri cosmetic-inconsistente, fara sa strice suma facturata. ### 4. `ASCD`/`ASCC` si `ID_PARTD`/`ID_PARTC` - **`ASCD`/`ASCC` nu sunt obligatorii — au fallback automat cand sunt nule**, exact pe ramura care se aplica pe facturi (`:7409-7428`): ``` V_ASCD := NVL(crs_rand_articol.ascd, PACK_FACTURARE.GetAnaliticByGrupUtilizatori(pack_facturare.nid_util, V_SCD)); ... V_ASCC := NVL(crs_rand_articol.ascc, PACK_FACTURARE.GetAnaliticByGrupUtilizatori(pack_facturare.nid_util, V_SCC)); ``` Cand nota nu are analitic explicit (cazul majoritatii notelor reale, per verificarea ta), se deriva unul din grupul de utilizatori al celui care factureaza, functie de contul `SCD`/`SCC`. Nu s-a verificat in aceasta sesiune ce intoarce `GetAnaliticByGrupUtilizatori` cand nici grupul de utilizatori nu are un analitic configurat (posibil `NULL` mai departe, netratat explicit aici). - **`ID_PARTD`/`ID_PARTC` nu sunt citite de la nota deloc.** `cursor_articol` nu le selecteaza (nu exista `D.ID_PARTD`/`D.ID_PARTC` nicaieri in fisier — verificat). Cele doua coloane de pe `ACT_TEMP` se calculeaza in `scrie_nota`/`scrie_tva` direct din **codul contului** (`V_SCD`, `V_SCC`) si din variabile de sesiune ale pachetului (`pack_facturare.nid_part`, `nid_part_rez`, `nid_partc`), nu din nota: `ID_PARTD` e un `CASE` pe prefixul lui `V_SCD` (`41%`/`46%`/`45%`/`357`) la `:12510-12515`; `ID_PARTC` e un `DECODE` pe `V_SCC` (`419`/`4111`/`357`) la `:12523-12530`. Daca `NOTE_CONTABILE` are coloane `ID_PARTD`/`ID_PARTC`, ele sunt irelevante pentru `contabilizeaza_articol` — partenerul contabil vine intotdeauna din contextul documentului (`pack_facturare.nid_part`), nu din configurarea notei. ### 5. Politica fara `ID_NOTA` (`HOTEL TAXE`, `HOTEL CAZARE`) **Nu exista un cod `FACT-0xx` dedicat pentru acest caz — spre deosebire de articolul care lipseste din politica (`FACT-024`, `:7278-7302`), aici procedura nu detecteaza si nu semnaleaza explicit situatia.** Lantul de `LEFT JOIN` din `cursor_articol` (`:7261-7271`) e construit sa supravietuiasca oricarui inel lipsa: `A` (politica-articol, gasita — altfel s-ar fi luat deja `FACT-024` mai devreme) se pastreaza chiar daca `B.ID_NOTA` e `NULL` — `C` si `D` devin pur si simplu toate `NULL` pe acel rand, cursorul tot intoarce **un rand** (`cursor_articol%FOUND = TRUE`), nu zero. In bucla (`:7396-7541`), asta inseamna: - `crs_rand_articol.scd`, `.ascd`, `.scc`, `.ascc`, `.cu_tva`, `.in_valuta`, `.explicatie` — toate `NULL`. - Ramura de calcul `V_ASCD := NVL(NULL, GetAnaliticByGrupUtilizatori(nid_util, NULL))` — analitic calculat pe un cont `NULL`, deci probabil tot `NULL` (netestat aici ce intoarce functia pe argument `NULL`). - `scrie_nota` e apelata cu `V_SCD = NULL`, `V_SCC = NULL` — insereaza in `ACT_TEMP` un rand cu conturile de debit/credit **nule**. Daca `ACT_TEMP.SCD`/`ACT_TEMP.SCC` au constrangere `NOT NULL` pe schema, `INSERT`-ul ar pica cu o eroare Oracle generica (`ORA-01400`), nu cu un mesaj `FACT-0xx` prietenos ca la celelalte cazuri tratate explicit — **neverificat in aceasta sesiune** (DDL-ul `ACT_TEMP` nu e in exportul `PACK_FACTURARE`). In orice caz, **comportamentul e cel putin la fel de riscant ca lipsa unui articol din politica**, dar fara plasa de siguranta explicita din cod — de tratat cu atentie daca reteta aprobata ajunge sa produca vreodata o politica fara `id_nota` (nu pare sa fie cazul retetei J-quater, care cere explicit gasirea unei note existente, dar `HOTEL TAXE`/`HOTEL CAZARE` arata ca starea "politica fara nota" chiar exista azi in baza vie, pe alte fluxuri). ## Ce nu s-a putut stabili si de ce - **Comportamentul exact al viitorului flux de reemitere din #13** (etapa II) fata de aceasta procedura — planul S10 cere verificarea "pe factura din contract", nu inventarul complet pentru comenzi/avize; nu s-a extins cercetarea acolo (in afara observatiei de la punctul 4, care ramane o constatare structurala, nu un verdict testat pe fluxul de reemitere, care **inca nu exista in cod** — decizia 30, nimic implementat). - **Ce se intampla la eroarea netratata din ramura de comenzi** (`NO_DATA_FOUND` cand `A.PRET = V_PRET_TEMP` nu gaseste rand, `:5057-5078`) — daca propaga ca eroare Oracle bruta pana la utilizator sau daca `goExecutor` o intercepteaza generic; n-a fost verificat (nu era in perimetrul celor 7 intrebari, dar e un risc adiacent gasit din citirea codului). - **Cate contracte reale au azi `CTR_ARTICOLE.PRET_UNITAR` diferit de pretul ultimei facturi emise** — verificare pe date vii, nefacuta (cercetare read-only, fara acces la interogari live in aceasta sesiune). - **Discrepanta de numerotare fata de `docs\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql`** (fisierul cerut in prompt nu exista pe disc) — semnalata la inceputul raportului, nu blocheaza verdictul pentru ca fisierul gasit in `SCRIPTURI_CLAR` are acelasi nume/data si continut structural identic.