docs: planurile, proiectarile si rapoartele de lucru intra in versionare

Folderul docs\ era pana acum in afara oricarui control de versiuni - nici git,
nici SVN - desi contine planurile pe puncte, proiectarile si rapoartele de
cercetare pe care se sprijina modificarile din cod. O stergere acolo era
definitiva.

Fisierele intermediare (handoff-uri intre sesiuni, diff-uri deja aplicate) au
fost sterse inainte, nu versionate: ce era durabil in ele a intrat in antetele
fisierelor de test la care se refereau.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
This commit is contained in:
2026-08-11 22:17:17 +03:00
parent 40933df3c8
commit d9f5ca4226
145 changed files with 43431 additions and 0 deletions

View File

@@ -0,0 +1,240 @@
# 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`.