# Cercetare: `pack_auto.actualizeaza_deviz` si riscul asupra devizului ROAAUTO la #13 Scop: `plan_13_unificare_formular_facturare.md` vrea sa permita adaugarea unei linii noi pe o factura deja emisa, inclusiv pe facturile ROAAUTO (`tip = -12`). Intrebarea: ce se intampla cu **devizul** din ROAAUTO cand factura primeste o linie pe care devizul nu o stie. Punctul de plecare a fost `pack_auto.actualizeaza_deviz`, apelat din `D:\ROA\ROAAUTO\Programe\oproceduri_devize.prg:1310`, al carei corp nu fusese citit inainte de aceasta cercetare. Continua `roaauto_facturi.md` si `roaauto_articole_lista_preturi.md` (deja citite, nu reiau constatarile lor: acelasi `PACK_FACTURARE`, `VANZARI_DETALII_TEMP` -> `VANZARI_DETALII`, `tip=-12`, liniile sintetice `-100000..-100008` plus liniile reale "Alte servicii", editorul `frm_modific2024` read-only, `oviz_devize.vc2:4536` blocheaza modificarea dupa `nrfact`). ## 1. Unde e definit `PACK_AUTO` `D:\ROA\DATABASE\SCRIPTURI_CLAR\\\ff_..._AUTO_PACK_AUTO.sql` — 14 versiuni istorice gasite (2013-2026). Sursa de adevar folosita (cea mai recenta, dupa conventia deja aplicata in `roaauto_facturi.md` pentru `PACK_FACTURARE`): **`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\03\ff_2026_03_31_02_AUTO_PACK_AUTO.sql`** (1804 linii, antet "17.03.2026 / robert / creare procedura setOptiuneInchidere"). Semnatura in spec: `:74-76`. Corp: `:692-733`. ## 2. Ce face `actualizeaza_deviz`, pas cu pas Corpul complet (`ff_2026_03_31_02_AUTO_PACK_AUTO.sql:692-733`): ```sql procedure actualizeaza_deviz(tnProcTvav IN NUMBER, tcSirIdOrdl IN VARCHAR2, tnIdSet IN NUMBER) is lcSeparator VARCHAR2(1) := ','; lnIdFact DOCUMENTE.ID_DOC%TYPE; begin -- nu iau pack_contafin.get_idfact pentru ca s-ar putea sa am id_fact de la incasare, nu de la factura SELECT MAX(ID_FACT) INTO lnIdFact FROM ACT WHERE COD = pack_contafin.get_cod() AND SCD NOT LIKE '5%'; UPDATE DEV_ORDL SET PROC_TVAV = tnProcTvav WHERE ID_ORDL IN (SELECT X FROM table(charn2collection(tcSirIdOrdl, lcSeparator))); UPDATE /*+ INDEX(RUL IDX_RUL_001) */ RUL SET ID_FACT = lnIdFact WHERE ID_SET <> 229 AND ID_LUCRARE IN (SELECT ID_LUCRARE FROM DEV_ORDL WHERE ID_ORDL IN (SELECT X FROM table(charn2collection(tcSirIdOrdl, lcSeparator)))); IF tnIdSet IN (31003, 31004, 31005, 31006, 31007, 31011) THEN UPDATE NOM_LUCRARI SET ID_FACT = lnIdFact WHERE ID_LUCRARE IN (SELECT ID_LUCRARE FROM DEV_ORDL WHERE ID_ORDL IN (SELECT X FROM table(charn2collection(tcSirIdOrdl, lcSeparator)))); END IF; end actualizeaza_deviz; ``` Trei pasi, toti indexati pe `ID_ORDL`/`ID_LUCRARE` (comanda/lucrarea din ROAAUTO), **niciunul pe `VANZARI`/`VANZARI_DETALII`**: 1. Citeste `lnIdFact` = cel mai mare `ID_FACT` din `ACT` pentru "codul" curent de sesiune (`pack_contafin.get_cod()`), excluzand notele de incasare (`SCD NOT LIKE '5%'`) — comentariul din cod explica de ce: la momentul apelului pot exista in `ACT` atat o nota de incasare cat si nota/factura propriu-zisa, si vrea explicit factura. 2. `UPDATE DEV_ORDL SET PROC_TVAV = tnProcTvav` — scrie cota de TVA pe comenzile din `tcSirIdOrdl` (lista CSV de `ID_ORDL`, despartita cu `charn2collection`). 3. `UPDATE RUL SET ID_FACT = lnIdFact WHERE ID_SET <> 229 AND ID_LUCRARE IN (...)` — leaga inapoi randurile din `RUL` (jurnalul de manopera/materiale al lucrarii, folosit si la `frm_inchidere_productie.do_executa` pentru totalul pe sectii, vezi §4) de documentul creat. 4. Doar daca `tnIdSet` e unul din `{31003,31004,31005,31006,31007,31011}`, acelasi `ID_FACT` se scrie si pe `NOM_LUCRARI` (nomenclatorul de lucrari). **Nu exista niciun `SELECT`/`UPDATE` pe `VANZARI` sau `VANZARI_DETALII` in `actualizeaza_deviz`** si, verificat suplimentar, **in tot pachetul `PACK_AUTO`** (grep pe `VANZARI` in cele 1804 linii ale fisierului: 0 potriviri). Deci raspunsul direct la intrebarea din brief: procedura **nu recalculeaza niciun total al devizului din liniile facturii** — nu citeste liniile facturii deloc. Ce face e sa "stampileze" `ID_FACT` (documentul de vanzare/nota abia creat) pe randurile din `RUL` si `NOM_LUCRARI` legate de comenzile din `tcSirIdOrdl`, plus sa actualizeze cota TVA pe `DEV_ORDL`. E o legatura *deviz -> document*, nu un recalcul *document -> total deviz*. ## 3. Ce se intampla cu o linie de factura pe care devizul nu o are Raspunsul e neted, pentru ca premisa intrebarii (un `SUM` peste `VANZARI_DETALII`) nu exista in cod: **procedura nu vede deloc liniile facturii**, nici cele cunoscute (sintetice `-100000..-100008`), nici cele reale (nomenclator, cazul "Alte servicii" din raportul anterior), nici una noua adaugata din afara. Ea opereaza exclusiv pe `ID_ORDL`/`ID_LUCRARE` (identitatea comenzii ROAAUTO), primite ca parametru `tcSirIdOrdl` — nu deriva niciodata acest identificator din continutul `VANZARI_DETALII`. Precedentul "Alte servicii" (articole reale, `id_articol` pozitiv, cf. `roaauto_articole_lista_preturi.md` §2) confirma exact acest comportament pe date deja live: acele linii coexista cu liniile sintetice in `VANZARI_DETALII` de multa vreme, fara ca `actualizeaza_deviz` sa faca vreo distinctie — pentru ca nu se uita la `VANZARI_DETALII` deloc. **Consecinta pentru #13**: adaugarea unei linii noi pe `VANZARI_DETALII` pentru o vanzare `tip=-12` nu poate "dezechilibra" ce scrie `actualizeaza_deviz`, pentru simplul motiv ca aceasta procedura nu depinde de continutul `VANZARI_DETALII`. Nu exista *eroare*, nu exista *ignorare explicita* — e o absenta totala de citire. Important insa (nuanta pe care intrebarea din brief o presupune implicit gresit): asta **nu** inseamna ca "devizul" (asa cum e prezentat operatorului in ROAAUTO) ar reflecta automat noua linie. Totalul devizului afisat in `oviz_devize.vc2` e calculat client-side din `RUL` (vezi `crsTotaluri`, construit cu un `SELECT SUM(...) FROM RUL ... GROUP BY ID_SECTIE` in `oviz_devize.vc2:7816-7823`, in `frm_inchidere_productie.do_executa`) si din cursoarele `crsdeviz`/`crsalteserv` calculate in `oproceduri_devize.prg` la momentul facturarii — niciodata din `VANZARI_DETALII`. Deci o linie adaugata ulterior pe factura **nu va aparea niciodata** in totalul devizului asa cum il calculeaza ROAAUTO, indiferent daca `actualizeaza_deviz` mai ruleaza sau nu — pur si simplu acel total nu are o sursa care sa citeasca `VANZARI_DETALII`. ## 4. Cand e apelata Cautare in ROAAUTO (`Grep` pe `actualizeaza_deviz`, cele trei aparitii de cod, plus istoric `.??2`) si in tot `D:\ROA\DATABASE\SCRIPTURI_CLAR` (niciun alt pachet Oracle nu o apeleaza — grep pe `actualizeaza_deviz` in tot arborele SCRIPTURI_CLAR gaseste doar fisierele care *definesc* `PACK_AUTO`/vechiul `PACK_DEVIZE`, nu vreun apel extern): Trei puncte de apel, toate in VFP, niciunul intr-un trigger/job Oracle: 1. **La emiterea facturii** — `oproceduri_devize.prg:1310`, in acelasi bloc `lcSql` cu `pack_facturare.scrie_in_vanzari` (linia 1302), cu `tnIdSet` dinamic (`lnIdSet`, calculat mai sus in `factureaza_deviz`). Comentariu la linia 1311: *"am scos apelul catre `pack_devize.dev_completeaza_rul`; e inclus in `actualizeaza_deviz`"* — confirma ca functia a inlocuit o procedura mai veche cu acelasi scop (legare RUL -> document). 2. **`frm_inchidere_productie.do_executa`** (`oviz_devize.vc2:7896`, clasa la `:7143`) — cu `tnIdSet` **fix, 31007** — apelata dupa ce formularul de **inchidere productie** scrie o *nota contabila* (`oscrie_in_fisiere()` peste cursorul `actactan`, `:7889`), **nu** o factura; nu apeleaza `pack_facturare.scrie_in_vanzari`, deci nu atinge `VANZARI` deloc pe acest drum. 3. **`frm_inchidere_regie.do_executa`** (`oviz_devize.vc2:8907`, clasa la `:8093`) — identic, `tnIdSet` fix **31006**, pentru inchiderea de **regie** (overhead), tot printr-o nota contabila, nu o factura. Deci `actualizeaza_deviz` nu e specifica facturarii — e o operatie generica *"leaga comenzile/lucrarile astea de ultimul document contabil creat pentru codul curent"*, refolosita si la doua fluxuri de inchidere interna care nu produc facturi de vanzare. In niciunul din cele trei cazuri nu e re-declansata mai tarziu (nu exista un al patrulea apel, nici din UI, nici din schedule/trigger Oracle) — deci editarea ulterioara a unei facturi deja emise (obiectivul #13) nu ar re-invoca automat aceasta procedura, pentru ca nimic din codul citit o cheama in afara celor 3 puncte de mai sus. ## 5. Alte proceduri din `PACK_AUTO` care citesc `VANZARI`/`VANZARI_DETALII` pentru un deviz **Niciuna.** Grep pe `VANZARI` in intregul fisier `ff_2026_03_31_02_AUTO_PACK_AUTO.sql` (1804 de linii, tot pachetul, nu doar `actualizeaza_deviz`) — 0 potriviri. `PACK_AUTO` nu are nicio dependenta de tabelele de vanzari/facturare; toata legatura cu partea financiara trece prin `ACT` (note contabile) si `DEV_ORDL`/`RUL`/`NOM_LUCRARI` (structura proprie ROAAUTO). Singurul loc care **citeste** liniile facturii pentru re-listarea unui deviz e in afara `PACK_AUTO`, pe partea VFP: `relisteaza_factura_deviz` (`D:\ROA\ROAAUTO\Programe\oproceduri_devize.prg:1516-1576`, mentionata in raportul anterior). Verificat acum sursa: interogheaza direct view-urile COMUN `fact_vfacturi` (`:1531`, filtrat `WHERE cod = ...`) si **`fact_vfacturi_detalii`** (`:1564`, `select * from fact_vfacturi_detalii where id_vanzare = ` — fara alt filtru). View-ul e definit in `D:\ROA\DATABASE\SCRIPTURI_CLAR\2024\06\ff_2024_06_04_01_COMUN_FACTURARE.sql:8-94`: `create or replace view fact_vfacturi_detalii as select ... from vanzari_detalii a left join nom_articole b ... ` — un simplu wrapper peste `VANZARI_DETALII` cu join-uri de denumire, **fara nicio clauza `WHERE`** care sa restranga la id-uri de articol cunoscute sau la liniile "originale" ale devizului. **Consecinta**: o linie noua inserata in `VANZARI_DETALII` pentru acel `id_vanzare` **va aparea automat** la o re-listare/re-tiparire ulterioara prin `relisteaza_factura_deviz` — comportament asteptat de la un view neconditionat, nu o stricare. Nu exista risc de eroare sau de excludere pe acest drum; riscul (daca exista) e doar de **asteptare a utilizatorului**: factura retiparita va arata linia noua, dar ecranul de deviz din ROAAUTO (total calculat din `RUL`, §3) nu o va arata niciodata, pentru ca nu deriva din `VANZARI_DETALII`. ## 6. Concluzie operationala pentru #13 **Da, se poate adauga o linie pe o vanzare `tip=-12` fara sa "strice" `pack_auto.actualizeaza_deviz` sau vreo alta procedura din `PACK_AUTO`** — pentru ca niciuna din ele nu citeste `VANZARI`/ `VANZARI_DETALII`; nu exista mecanism Oracle-side care sa recalculeze/verifice totalul devizului din liniile facturii, deci nu exista nimic de dezechilibrat la acel nivel. Nu e nevoie de niciun apel Oracle suplimentar din partea ROAFACTURARE ca sa "anunte" ROAAUTO despre linia noua — `actualizeaza_deviz` n-ar face nimic util cu acea informatie oricum (opereaza pe `ID_ORDL`, nu pe linii de factura). Ce **nu** rezolva aceasta concluzie, si ramane responsabilitatea planului #13, nu a acestei proceduri: - **Desincronizare de afisare, nu de date**: totalul devizului aratat in ROAAUTO (`oviz_devize.vc2`, calculat din `RUL`/cursoarele de facturare) nu va reflecta niciodata o linie adaugata ulterior direct pe `VANZARI_DETALII` — nici azi (cu liniile "Alte servicii"), nici cu o linie noua din editorul unificat. Daca produsul vrea ca devizul sa "stie" de linia noua vizual, ar trebui cod nou in ROAAUTO (nu exista azi), nu un apel catre `actualizeaza_deviz`. - **Reprintarea** (`relisteaza_factura_deviz`) va include automat linia noua (§5) — de verificat daca asta e comportamentul dorit de produs sau o suprindere pentru operatorul ROAAUTO. - Confirmat si direct in cod ROAFACTURARE: `Grep` pe `pack_auto` in `D:\ROA\ROAFACTURARE` (inclusiv `COMUN`) nu gaseste nicio referinta in cod, doar in `docs\` (planul #13 si aceste rapoarte) — azi ROAFACTURARE nu apeleaza deloc `PACK_AUTO`, confirmand ca nu exista deja o presupunere ascunsa de sincronizare intre cele doua. ## Neverificat - Ce reprezinta exact tabelele `ACT`/`RUL`/`NOM_LUCRARI`/`DEV_ORDL` la nivel de schema completa (DDL/comentarii) — inteles doar din felul in care sunt folosite in cod, nu dintr-un dictionar de date citit explicit. - Daca vreun raport fiscal/SAF-T (mentionat generic in `ff_2022_03_24_01_COMUN_SAFT.sql`, nedeschis) agrega `VANZARI_DETALII` intr-un mod care ar fi afectat de o linie noua pe `tip=-12` — in afara ariei `PACK_AUTO` cerute, nu a fost investigat. - Daca `frm_incasare_finala.do_recalculeaza_total`/`calculeaza_total` (`oviz_devize.vc2:6494,6700`) ar putea fi reconciliate manual de un operator ca sa "vada" o linie adaugata ulterior — nu am citit corpul acestor metode, doar semnalul ca exista. - Istoricul complet al celorlalte 13 versiuni `AUTO_PACK_AUTO.sql` nu a fost comparat linie cu linie cu cea din 2026-03 — presupun (conform conventiei deja aplicate pentru `PACK_FACTURARE`) ca cea mai recenta e sursa de adevar pentru comportamentul curent din productie.