# Corespondenta cont de stoc (3xx) -> cont de venit (7xx): ce exista in cod **Context**: continuare a `cont_venit_articol_fara_politica.md`, care stabilise ca `VANZARI_DETALII.CONT` e un cont de **gestiune/stoc** (371, 301-303, 357), fara sa gaseasca un cont de venit pe linia de factura in `pack_facturare`, si lasase neverificat unde se genereaza efectiv contul de venit. Cercetarea de fata raspunde la cele 4 intrebari, cu corectii fata de raportul anterior. ## Raspuns scurt 1. **Nu exista un tabel de corespondenta "3xx -> 7xx"** (nume de forma `CORESPONDENTA*`, `NOM_CONTURI*`, `CONT_VENIT*`, `ARTICOLE_CONTABILE*`) nicaieri in `SCRIPTURI_CLAR`. In schimb exista un **mecanism echivalent functional, dar configurat manual, nu derivat automat din contul de stoc**: tabelul `NOTE_CONTABILE` (coloane `SCD`/`ASCD` = cont+analitic debitor, `SCC`/`ASCC` = cont+analitic creditor), legat de politica de pret a articolului prin `CRM_POLITICI_PRETURI.ID_NOTA -> CRM_NOTE_VANZARI.ID_SET -> NOTE_CONTABILE`. Un contabil configureaza acest tabel dintr-un ecran dedicat (`frm_config_note_contabile[2007]`), nu se calculeaza din `NOM_ARTICOLE.CONT`/`STOC.CONT`. 2. **`NOM_ARTICOLE.CONT` NU e restrans la conturi de stoc (clasa 3).** Validarea la editare (`verific_cont`) verifica doar ca respectivul cod exista in planul de conturi al anului curent (`vplcont_sintetic`), fara filtru pe clasa. UI-ul trimite explicit catre "Planul de conturi" (buton de help general), nu catre un subset de conturi de stoc. Asta confirma afirmatia lui Marius: campul accepta orice cont, inclusiv 6xx/7xx. 3. **Nota contabila a vanzarii SE genereaza in `pack_facturare`** — raportul anterior a cautat literalii `707`/`704`/`706`/`708` (care nu apar hardcodati nicaieri, corect) si a conchis gresit ca lipseste mecanismul. El exista, dar e **indirect**: `pack_facturare.contabilizeaza_articol` (`ff_2026_08_06_10_COMUN_PACK_FACTURARE.sql:7182-7556`) ia `SCD`/`SCC` din `NOTE_CONTABILE` (via politica de pret a articolului) si scrie nota cu `pack_facturare.scrie_nota(...)`. `SCC` (contul creditor) e contul de venit efectiv al liniei — nu vine din `VANZARI_DETALII.CONT` (care ramane contul de gestiune, folosit separat, doar pentru descarcarea de gestiune, in `descarca_gestiune`). 4. **`ID_VENCHELT`/`NOM_VENIT_CHELTUIELI` nu are coloana de cont** (nicio `ALTER TABLE NOM_VENIT_CHELTUIELI ADD ... CONT` in `SCRIPTURI_CLAR`). E o dimensiune analitica separata (clasificare venituri/cheltuieli, posibil pentru raportare/buget), transmisa ca parametru propriu catre `scrie_nota`, in paralel cu `SCD`/`SCC` — nu e sursa contului. ## 1. Nu exista tabel de corespondenta 3xx->7xx; exista `NOTE_CONTABILE` + politica de pret ### Cautare tabel dedicat — negativa Cautari in `D:\ROA\DATABASE\SCRIPTURI_CLAR` (`CREATE TABLE`/`ALTER TABLE`, case-insensitive) pentru `CORESPONDENT*`, `NOM_CONTURI*`, `CONT_VENIT*`, `PLAN_CONTURI*`, `ARTICOLE_CONTABILE*`: niciun rezultat relevant — singurele hituri pe `CORESPONDENT` sunt cuvantul romanesc generic ("banca corespondenta" etc.) in sute de fisiere fara legatura, iar `CONT_VENIT` nu apare deloc ca nume de tabel/coloana. ### Mecanismul real: lant de 4 tabele, configurat pe politica de pret `pack_facturare.contabilizeaza_articol` (`ff_...:7227-7280`) foloseste acest cursor pentru a afla contul debitor/creditor al liniei de vanzare: ```sql CURSOR cursor_articol IS SELECT A.ID_POL_ART, A.ID_POL, A.ID_ARTICOL, A.PRET, ... NVL(pack_facturare.nid_venchelt, NVL(A.ID_VENCHELT, C.ID_VENCHELT)) AS ID_VENCHELT, NVL(pack_facturare.nid_sectie_stoc, C.ID_SECTIE) as ID_SECTIE, C.ID_SET, D.EXPLICATIE, D.SCD, D.ASCD, D.SCC, D.ASCC, D.CU_TVA, ... 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; ``` (`ff_2026_08_06_10_COMUN_PACK_FACTURARE.sql:7227-7280`) Lantul e: **articol + politica de pret** (`CRM_POLITICI_PRET_ART`, deja documentat in raportul anterior ca avand `PRET`/`PROC_TVAV`/`ID_VALUTA`, fara `CONT`) `->` **antetul politicii de pret** (`CRM_POLITICI_PRETURI.ID_POL`, care are `ID_NOTA`) `->` **nota de vanzare CRM** (`CRM_NOTE_VANZARI.ID_NOTA`, care are `ID_SET`) `->` **sablonul de nota contabila** (`NOTE_CONTABILE.ID_SET`, care are `SCD`/`ASCD`/`SCC`/`ASCC`/`EXPLICATIE`/`CU_TVA`/`IN_VALUTA`). Apoi, la scriere (`ff_...:7405-7437`): ```sql CASE WHEN pack_facturare.ntip <= 20 or pack_facturare.ntip IN (...) THEN -- factura, factura roahotel V_SCD := crs_rand_articol.scd; V_ASCD := NVL(crs_rand_articol.ascd, PACK_FACTURARE.GetAnaliticByGrupUtilizatori(...)); WHEN pack_facturare.ntip in (28, 29) THEN -- aviz catre clienti debitori V_SCD := '461'; ... ELSE -- aviz V_SCD := '418'; ... END CASE; V_SCC := crs_rand_articol.scc; V_ASCC := NVL(crs_rand_articol.ascc, PACK_FACTURARE.GetAnaliticByGrupUtilizatori(...)); ``` (`ff_2026_08_06_10_COMUN_PACK_FACTURARE.sql:7407-7437`) Pentru o factura normala (`ntip <= 20`), `V_SCD` e contul debitor din nota (tipic un cont de creante, 411/etc.), iar `V_SCC` e contul creditor din nota — **acesta e efectiv contul de venit** al liniei (707/704/706/708, in functie de cum a configurat contabilul nota respectiva), preluat **direct din `NOTE_CONTABILE.SCC`**, fara nicio derivare din contul de stoc al articolului. Perechea `V_SCD`/`V_SCC` (plus `ID_VENCHELT`, `ID_SECTIE`, `EXPLICATIE`, cota TVA) e trimisa la `pack_facturare.scrie_nota(...)` (`ff_...:7452-7476`), care scrie randul in nota contabila efectiva a vanzarii. **Concluzie fata de ipoteza lui Marius**: mecanismul exista si rezolva exact problema — "de unde stiu contul de venit al unei linii de vanzare, indiferent daca articolul e gestionabil sau nu" — dar **nu e o corespondenta automata cont-stoc -> cont-venit**. E o **configurare manuala per politica de pret**: fiecare politica de pret (`CRM_POLITICI_PRETURI`) e legata la o "nota de vanzare" CRM (`CRM_NOTE_VANZARI`), care la randul ei e legata la un sablon de nota contabila (`NOTE_CONTABILE`) cu perechea SCD/SCC fixata de un contabil. Politica de pret aplicata articolului decide, indirect, contul de venit — nu clasa/valoarea contului de gestiune al articolului. ### Ecranul de configurare (unde se seteaza SCD/SCC) `D:\ROA\ROAFACTURARE\COMUN\ferestre\frm_config_note_contabile.sc2` (+ varianta `frm_config_note_contabile2007.sc2` pentru anii >= 2007, selectata in `COMUN\programe\omeniu_initializari.prg:257-282`) e formularul din meniu "Configurare note contabile". Clasa e `onote_contabile.vc2`, cu un grid `gridInregistrari` avand coloanele `cScd`/`cAscd`/`cScc`/`cAscc` (`onote_contabile.vc2:2401-2435`) legate direct de `cnote_contab.scd`/`.scc`/`.ascd`/`.ascc`, si salvare prin INSERT/UPDATE direct pe `note_contabile(explicatie,scd,ascd,scc,ascc,ordine,cu_tva,ptva,id_set,in_valuta,...)` (`onote_contabile.vc2:315-322`, `:486-493`). Deci **contabilul e cel care scrie manual perechea SCD/SCC** (inclusiv contul de venit `SCC`) pentru fiecare `id_set`/nota, nu exista automatism care sa deriveze `SCC` din contul de gestiune al articolului. ## 2. `NOM_ARTICOLE.CONT` — nu e restrans la clasa 3 - **Camp**: `Clb_tx_cont.Text_simplu1.ControlSource = "porec.cont"`, `MaxLength = 4`, eticheta `"Cont*"` (obligatoriu), buton de help cu tooltip `"Help - Planul de conturi (CTRL+ H)"` — `COMUN\clase\onom_articole.vc2:1058-1087`. Trimiterea catre "Planul de conturi" (nu catre un subset "conturi de stoc") sugereaza ca formularul asteapta orice cont valid, nu doar clasa 3. - **Validare la Valid() al campului** (in alt formular generic de conturi, `onomenclatoare.vc2`, nu in cel de articole, dar foloseste aceeasi functie globala): ``` PROCEDURE clb_cont.Text_simplu1.Valid IF !EMPTY(this.Value) lnVerificat = verific_cont(thisform.orec.cont) IF lnVerificat < 0 RETURN 0 ENDIF ENDIF ENDPROC ``` (`COMUN\clase\onomenclatoare.vc2:3251-3258`) - **`verific_cont`** (`COMUN\programe\oproceduri_comune.prg:2389-2415`): ``` Procedure verific_cont Parameters tcCont, tlNoMessage lcSel = [SELECT cont from ] + GCS + [.vplcont_sintetic WHERE TRIM(cont) = ?pcCont and an = ?gnAn ] ... If Reccount('crs_verific') = 0 lnSucces = -1 Endif If lnSucces < 0 And !tlNoMessage amessagebox('Acest cont nu este definit in planul de conturi!', 0 + 48, 'Atentie') Endif Endproc ``` Singura conditie e ca `cont` sa existe in `vplcont_sintetic` (planul de conturi sintetic al anului curent, `gnAn`) — **fara `LIKE '3%'`, fara `SUBSTR(cont,1,1) = '3'`, fara nicio alta restrictie de clasa**. O varianta identica exista si in `COMUN\programe\ooperatii_comune.prg:1307` (nu am comparat corp cu corp, dar semnatura e aceeasi). - Nu exista `CHECK CONSTRAINT` pe `NOM_ARTICOLE.CONT` in `SCRIPTURI_CLAR` (cautare `CHECK.*CONT`/`constraint.*CONT.*check` — zero rezultate relevante), deci nici la nivel de baza de date nu exista o restrictie de clasa. - Nu am gasit nicaieri in `COMUN` sau `ROAFACTURARE` o ramificare pe `Left(cont,1)`/ `SUBSTR(cont,1,1)` aplicata specific campului `NOM_ARTICOLE.CONT` (cautare in `D:\ROA\ROAFACTURARE` si `D:\ROA\ROAFACTURARE\COMUN`) — singurul loc cu `SUBSTR(cont,1,1)` gasit e in `onomenclatoare.vc2:3647`, un filtru de grid pe planul de conturi general (tab-uri "1", "2", "3"... pentru navigare in plan), fara legatura cu articolele. **Concluzie**: campul e validat generic (orice cont din planul de conturi al anului), fara restrictie de clasa la nivel de UI sau DB. Asta confirma ce a spus Marius: un articol negestionabil poate avea legitim un cont 6xx/7xx in `NOM_ARTICOLE.CONT`. ## 3. Unde se genereaza efectiv nota contabila a vanzarii Raportul anterior cauta gresit literalii `707`/`704`/`706`/`708` (niciunul nu apare hardcodat — corect) si a conchis ca nu exista mecanism in `pack_facturare`. De fapt **exista, dar e in `pack_facturare`, nu intr-un pachet separat de contabilitate**: - **Functia**: `pack_facturare.contabilizeaza_articol(detalii_articol VANZARI_DETALII_TEMP%ROWTYPE)` (`ff_2026_08_06_10_COMUN_PACK_FACTURARE.sql:7182-7556`), apelata pe fiecare rand din `VANZARI_DETALII_TEMP` — vezi apelul `V_INCASAT_CALCUL := V_INCASAT_CALCUL + pack_facturare.contabilizeaza_articol(tab_detalii(i));` in `scrie_aviz_retur` (`ff_...:7148-7150`); acelasi tipar se repeta si in fluxul principal de facturare (nu doar in aviz-retur — semnatura si structura functiei arata ca acopera si `ntip <= 20`, adica factura propriu-zisa, prin `CASE ... WHEN pack_facturare.ntip <= 20 ...` la `ff_...:7409-7421`). - **Sursa `SCD`/`SCC`**: vezi sectiunea 1 — cursorul `cursor_articol` (`ff_...:7227-7280`), pe baza politicii de pret a articolului (`detalii_articol.id_pol`), nu pe `VANZARI_DETALII.CONT`. - **`VANZARI_DETALII.CONT` ramane folosit separat, doar pentru gestiune**: in aceeasi functie, `descarca_gestiune(...)` primeste explicit `detalii_articol.cont` ca parametru (`ff_...:7485-7507`, apelat cand `nscadere_stoc = 1 AND id_gestiune <> -1000 AND in_stoc = 1`) — acesta e contul de gestiune/stoc (371/301-303/357 etc., documentat in raportul anterior), folosit pentru randul de descarcare de gestiune (marfa iesita din stoc), complet independent de `V_SCD`/`V_SCC` calculate mai sus pentru randul de venit al vanzarii. **Cele doua conturi coexista pe aceeasi linie de vanzare, cu surse complet diferite**: unul (gestiune) vine din `NOM_ARTICOLE.CONT`/`STOC.CONT`/`NOM_GESTIUNI.CONT` (cf. raport anterior), celalalt (venit) vine din `NOTE_CONTABILE.SCC` via politica de pret. - **Nu exista fallback/hardcodare** pentru `SCC`: daca `NOTE_CONTABILE` nu are un rand pentru `ID_SET`-ul politicii, `LEFT JOIN`-urile din `cursor_articol` produc `NULL` pe `SCC`/`SCD` (fara eroare explicita in acest cursor — spre deosebire de cazul `V_COMPUS`/politica lipsa la `ff_...:7293-7311`, care ridica `FACT-024`). ## 4. `ID_VENCHELT` / `NOM_VENIT_CHELTUIELI` - **Nu are coloana de cont**: nicio `ALTER TABLE NOM_VENIT_CHELTUIELI ADD ... CONT` in `SCRIPTURI_CLAR` (cautare directa, zero rezultate) si nicio `CREATE TABLE NOM_VENIT_CHELTUIELI` in arhiva (tabelul predateaza 2009, inceputul arhivei `SCRIPTURI_CLAR` — la fel ca `NOTE_CONTABILE`, `CRM_NOTE_VANZARI`, `CRM_POLITICI_PRETURI`, pentru care nu exista `CREATE TABLE` in arhiva din acelasi motiv). - **Structura vazuta din uz**: `NOM_VENIT_CHELTUIELI.ID_VENCHELT%TYPE` (tip declarat repetat in `pack_facturare`, ex. `ff_...:191`) si `ACT.ID_VENCHELT%TYPE` (`ff_...:6725`) — deci `ID_VENCHELT` e o coloana FK pe `ACT` (tabelul de note contabile efective) si pe `CRM_NOTE_VANZARI` / `CRM_POLITICI_PRET_ART` (vezi `NVL(B.ID_VENCHELT, D.ID_VENCHELT)` la `ff_...:7205`, unde `B` = `CRM_POLITICI_PRET_ART`, `D` = `CRM_NOTE_VANZARI` in cursorul comentat din pachet). - **Cine il consuma**: `pack_facturare.contabilizeaza_articol` il rezolva cu prioritate similara contului: `NVL(pack_facturare.nid_venchelt, NVL(A.ID_VENCHELT, C.ID_VENCHELT))` (override global de sesiune -> articol/politica -> nota de vanzare) si il trimite ca parametru propriu catre `scrie_nota(...)` (`ff_...:7461`), **separat** de `SCD`/`SCC`. E deci o **a treia dimensiune** (clasificare venituri/cheltuieli) atasata randului de nota contabila, nu sursa contului insusi — raportul anterior avea dreptate sa il caracterizeze ca "o clasificare, nu un cont", desi nu urmarise consumatorul pana la capat. - Numele `NOM_VENIT_CHELTUIELI` si folosirea alaturi de `SCD`/`SCC`/`ID_SECTIE` sugereaza un centru de venituri/cheltuieli pentru raportare (posibil situatii financiare pe sectii/centre de cost), nu un mecanism alternativ de determinare a contului 7xx. ## Neverificat - **Structura completa (toate coloanele) a `NOTE_CONTABILE`, `CRM_NOTE_VANZARI`, `CRM_POLITICI_PRETURI` si `NOM_VENIT_CHELTUIELI`**: niciuna nu are `CREATE TABLE` in `SCRIPTURI_CLAR` (arhiva incepe 2009, tabelele sunt mai vechi). Coloanele folosite in cod sunt confirmate (`SCD`/`ASCD`/`SCC`/`ASCC`/`EXPLICATIE`/`CU_TVA`/`IN_VALUTA`/`ID_SET` pe `NOTE_CONTABILE`; `ID_NOTA`/`ID_SET` pe `CRM_NOTE_VANZARI`; `ID_NOTA`/`ID_POL` pe `CRM_POLITICI_PRETURI`; `ID_VENCHELT` pe `NOM_VENIT_CHELTUIELI`), dar lista completa ar necesita interogarea schemei Oracle live (`DESC NOTE_CONTABILE` etc.) sau un export DDL mai vechi decat 2009, in afara bugetului acestei cercetari. - **Continutul efectiv al `NOTE_CONTABILE.SCC`** pentru notele configurate curent (adica ce conturi 707/704/706/708 sunt de fapt setate, si daca fiecare politica de pret are o nota configurata) — ar necesita interogarea datelor din schema Oracle live, nu doar codul static. - **Daca `contabilizeaza_articol` e chiar apelata pe fluxul principal de facturare** (nu doar din `scrie_aviz_retur`) — am dedus asta din `CASE ... ntip <= 20 ...` (factura normala tratata explicit in functie), dar nu am urmarit *toti* apelantii ei in fisier (fisierul are 17000+ linii; cautarea `pack_facturare.contabilizeaza_articol` ar trebui repetata exhaustiv daca se doreste certitudine completa pe toate punctele de intrare — facturare avans, deviz, retail etc.). - **Comportamentul cand `NOTE_CONTABILE`/`CRM_NOTE_VANZARI` lipsesc pentru o politica de pret**: cursorul foloseste `LEFT JOIN`, deci `SCD`/`SCC` ar ajunge `NULL` fara eroare explicita in acest punct — nu am verificat daca exista o validare ulterioara (la `scrie_nota` sau la commit-ul notei) care sa blocheze o nota cu cont `NULL`.