Files
roafacturare/docs/cercetare/canal_cont_venit_fara_politica.md
Marius Mutu d9f5ca4226 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
2026-08-11 22:17:17 +03:00

516 lines
37 KiB
Markdown

# Exista un canal fara politica de pret catre ACT_TEMP.SCC? (proiect #13)
Cercetare read-only. Continua `cont_venit_articol_fara_politica.md`, `nota_contabila_fara_politica.md`,
`coresp_cont_venchelt.md`, `verif_baza_vie_cont_venit.md`.
**Mandat schimbat pe parcurs — vezi sectiunea imediat de mai jos.** Sectiunile de la
"Verdict, in cinci randuri" incolo sunt cercetarea rundei cu mandatul vechi ("gaseste un canal
ocolitor, nu se atinge `pack_facturare`") si raman ca input de proiectare (harta intrarilor spre
`SCD`/`SCC`, DDL, ce face `V_CONT`) — nu mai sunt raspunsul principal.
**HANDOFF (predare de context, nu sarcina noua):** o a treia sarcina a fost primita de la team-lead
dupa livrarea proiectarii de mai jos — verificarea celor 37 de linii de comanda cu articol nemembru
al politicii lor (proiectul #13, decizia 32). **Nu a fost inceputa** — sesiunea a evaluat contextul
consumat pana la acel punct ca fiind aproape de pragul de predare (lectura extinsa de rapoarte mari +
export Oracle in aceasta sesiune) si a predat inainte de a deschide o interogare noua, conform Regula
zero. Livrabilul cerut pentru acea sarcina e alt fisier,
`docs\cercetare\linii_comanda_articol_nemembru.md` — **neinceput, nescris**. Nimic din
sesiunea curenta nu e intr-o stare periculoasa: doar `SELECT`-uri Oracle rulate (toate terminate),
niciun fisier de cod atins, niciun proces/tranzactie ramas deschis. Urmatorul agent poate porni
curat pe sarcina celor 37 de linii, cu contextul din mesajul team-lead-ului (re-confirma cifra,
extrage cele 37 de linii cu id_comanda/id_articol/id_pol/data/stare facturare, verifica daca vreuna
s-a facturat fara eroare, cauza daca se poate citi din audit, si validarea pe cod a conditiei
FACT-024 aplicata pe forma lor).
---
## Proiectarea parametrului de cont contabil (mandat nou, Marius 10.08.2026)
Marius a autorizat explicit modificarea punctuala a `pack_facturare` ("poți să adaugi parametrul
contul contabil la `contabilizeaza_articol`") — decizia 27-bis e relaxata. **Aceasta e o proiectare,
nu o implementare — niciun fisier de cod nu a fost atins.** Sursa Oracle:
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql` (17217 linii,
verificat `wc -l`); toate liniile citate mai jos sunt din **acest fisier**, citite direct in aceasta
runda (nu preluate din rapoarte anterioare).
### Verdict proiectare, in sase randuri
**Fezabil, cu o precizare importanta fata de formularea lui Marius**: `contabilizeaza_articol`
primeste azi un **singur parametru**, `detalii_articol VANZARI_DETALII_TEMP%ROWTYPE` — un rand
intreg, nu o lista de scalari. Deci "parametrul de cont" **nu intra ca parametru nou pe
`contabilizeaza_articol` insasi** (asta ar fi cosmetic, fara efect, pentru ca cei 3 apelanti interni
ii dau deja randul intreg dintr-un `TABLE OF VANZARI_DETALII_TEMP%ROWTYPE`) — intra pe drumul real:
**o coloana noua pe `VANZARI_DETALII_TEMP`, populata printr-un parametru nou pe
`adauga_articol_factura`** (procedura chemata direct din VFP), pe care `contabilizeaza_articol` o
citeste automat prin `detalii_articol.<coloana>`, **fara nicio modificare la `scrie_factura2`,
`scrie_factura_avize_retur` sau `scrie_aviz_retur`**. Efectul practic e exact ce a cerut Marius — un
cont de venit calculat de VFP ajunge in `ACT_TEMP.SCC` fara politica — doar mecanica de livrare e
alta decat "parametru pe `contabilizeaza_articol`" literal. Restul (SCD, CU_TVA, IN_VALUTA,
EXPLICATIE, ID_VENCHELT, ID_SECTIE, `descarca_gestiune` o singura data, FACT-024 ocolit doar pe
ramura noua) au surse identificate mai jos, cu 2 hardcodari explicite care cer confirmarea lui
Marius (`SCD='4111'`, `CU_TVA=1`).
### 1. Lantul real de apel — de ce parametrul trebuie sa intre pe `adauga_articol_factura`, nu pe `contabilizeaza_articol`
```
ff_...:7173 FUNCTION contabilizeaza_articol(detalii_articol VANZARI_DETALII_TEMP%ROWTYPE) RETURN NUMBER IS
```
Singurul parametru. Apelata de exact **3 locuri**, toate interne pachetului, toate ii dau un element
dintr-un array populat integral din tabel:
```
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 V_INCASAT_CALCUL := V_INCASAT_CALCUL + pack_facturare.contabilizeaza_articol(tab_detalii(i)); -- scrie_factura2
ff_...:6858 pack_facturare.contabilizeaza_articol(tab_detalii(i)); -- scrie_factura_avize_retur
ff_...:7140 pack_facturare.contabilizeaza_articol(tab_detalii(i)); -- scrie_aviz_retur
```
`SELECT * BULK COLLECT` (nu o lista explicita de coloane) inseamna: **orice coloana noua adaugata pe
`VANZARI_DETALII_TEMP` ajunge automat in `tab_detalii(i)` si deci in `detalii_articol` in
`contabilizeaza_articol`, fara sa atingi aceste 3 proceduri.** Asta e drumul cu cea mai mica
suprafata de risc posibila — nu exista un drum mai mic care sa duca un cont calculat de VFP pana in
`contabilizeaza_articol`.
Intrarea reala din VFP e `adauga_articol_factura` (nu `contabilizeaza_articol`):
```
ff_...:4989-5015 PROCEDURE adauga_articol_factura(V_ID_TEMP IN NUMBER,
V_ID_ARTICOL IN NUMBER,
... (23 parametri) ...
V_ID_UTIL IN NUMBER,
V_TAXCODE IN NUMBER DEFAULT NULL,
V_LOT IN VARCHAR2 DEFAULT NULL) IS
```
**Precedent direct pentru "adauga parametru nou la coada, cu `DEFAULT NULL`"**: `V_TAXCODE` si
`V_LOT` sunt deja exact asta — doi parametri adaugati ulterior, la finalul listei, cu `DEFAULT NULL`,
fara sa oblige la rescrierea apelantilor existenti. Propunerea de mai jos repeta acelasi tipar, nu
inventeaza unul nou.
Apelantul VFP confirmat (singurul gasit in sursa, dublat identic in doua locuri din aceeasi clasa —
vezi "Ce nu s-a putut stabili"):
```
COMUN\clase\ofacturare.vc2:14069-14091 (si identic la :18089-18114)
lcSql = lcSql + [pack_facturare.adauga_articol_factura(] + Alltrim(Str(poArt.id_temp)) + [,] + ;
... (pozitional, 26 de argumente) ... + ;
NVL(ALLTRIM(STR(poArt.taxcode)),[NULL]) + ;
[,'] + OracleSpecialCharacters(Alltrim(Nvl(poArt.lot,[]))) + ['] + ;
[);]
```
Apel **pozitional**, se opreste la `V_LOT` (ultimul parametru existent azi). Oracle permite ca un
apel pozitional sa se opreasca inainte de parametri opționali de la coada — deci un parametru nou
**dupa** `V_LOT` nu afecteaza acest apel existent (ramane identic, echivalent cu "trimite `NULL`" pe
noul parametru).
### 2. Schema propusa
**Coloana noua**: `VANZARI_DETALII_TEMP.CONT_VENIT VARCHAR2(4) NULL` (fara `NOT NULL`, fara `CHECK`
— acelasi tipar ca `ACT_TEMP.SCC`, vezi DDL mai jos). Recomandat, dar nu strict necesar pentru
mecanismul de nota (doar pentru trasabilitate/raportare ulterioara): aceeasi coloana pe
`VANZARI_DETALII`, plus adaugarea ei in `INSERT /*+ APPEND */ INTO VANZARI_DETALII (...) SELECT ...
FROM VANZARI_DETALII_TEMP` din `scrie_in_vanzari` (citat in `nota_contabila_fara_politica.md`
sectiunea 4 ca avand lista explicita de coloane — **linia exacta nu a fost re-verificata in aceasta
runda**, vezi "Ce nu s-a putut stabili"). Fara acest pas secundar, nota contabila tot se scrie corect
— doar `VANZARI_DETALII` nu ar pastra, dupa fapt, cu ce cont s-a facturat linia.
**Parametru nou pe `adauga_articol_factura`**, la coada, dupa `V_LOT`:
```
V_CONT_VENIT IN VARCHAR2 DEFAULT NULL
```
Plumbing identic cu `V_CONT`/`V_CONT2` (`ff_...:5004,5035-5037,5238,5268` — acelasi tipar de
"copiaza daca nu e sentinela/gol, altfel NULL"), adaugat langa `INSERT INTO VANZARI_DETALII_TEMP`
(`ff_...:5222-5282`): o coloana in plus in lista, o valoare in plus in `VALUES`.
**Niciun rand de cod nou in `scrie_factura2` / `scrie_factura_avize_retur` / `scrie_aviz_retur`** —
confirmat la sectiunea 1, `SELECT *` + `%ROWTYPE` absoarbe coloana automat.
### 3. Ramura noua in `contabilizeaza_articol`
Corpul complet citit `ff_...:7173-7547`. Structura propusa: un `IF detalii_articol.cont_venit IS NOT
NULL THEN <ramura noua> ELSE <tot codul de azi, neschimbat> END IF;` care **infasoara inclusiv
blocul FACT-024**, plasat imediat dupa declaratiile locale (inainte de `ff_...:7278`). Cand
parametrul e `NULL` (toti apelantii de azi, nemodificati), executia cade in `ELSE` si comportamentul
e identic bit-cu-bit cu azi.
**Continutul ramurii noi** (doar pentru "articol simplu" — articolele compuse, `V_COMPUS=1`, raman
in afara scopului, ca azi):
| Camp | Sursa in ramura noua | Argumentatie |
|---|---|---|
| `SCC` | `detalii_articol.cont_venit` | Chiar parametrul primit — asta e intreg scopul modificarii. |
| `SCD` | **hardcodat `'4111'`** pentru cazul "factura" (ramurile aviz raman `'418'`/`'461'`, deja hardcodate azi la `ff_...:7415,7420`, independent de politica) | **Hardcodare explicita, de confirmat cu Marius.** Azi, pentru factura normala, `V_SCD := crs_rand_articol.scd` (`ff_...:7409`) — vine din `NOTE_CONTABILE.SCD`. Pe baza vie (`verif_baza_vie_cont_venit.md` tabel sectiunea 4), **toate cele 7 note de vanzari active au `SCD='4111'`** (contul de clienti, standard pentru vanzare pe credit) — zero exceptii masurate. Decizia 31 (nu generaliza de pe datele din Dev) se aplica la *numere*, nu la *structura contabila* — `4111` = clienti e conventie standard de plan de conturi, nu un artefact al datelor de test, dar tot ramane o presupunere care trebuie confirmata explicit, nu deja "descoperita". |
| `ASCD` | `PACK_FACTURARE.GetAnaliticByGrupUtilizatori(pack_facturare.nid_util, V_SCD)` | Exact fallback-ul deja folosit necondiționat pentru ramurile de aviz azi (`ff_...:7416-7417,7421-7422`) — functioneaza fara cursor, deja verificat ca nu depinde de politica (`coresp_cont_venchelt.md` sectiunea 7). |
| `ASCC` | `PACK_FACTURARE.GetAnaliticByGrupUtilizatori(pack_facturare.nid_util, V_SCC)` | Acelasi tipar ca `V_ASCC` de azi (`ff_...:7426-7428`), care oricum e `NVL(crs_rand_articol.ascc, GetAnaliticByGrupUtilizatori(...))` — fallback-ul e calea normala, nu exceptia. |
| `EXPLICATIE` | `detalii_articol.explicatia` (coloana `EXPLICATIA` din `VANZARI_DETALII_TEMP`, populata de `V_EXPLICATIE` — parametru deja existent pe `adauga_articol_factura`, `ff_...:4992,5227,5257`) | **Mai buna decat sursa de azi**, nu doar un fallback — azi `crs_rand_articol.explicatie` vine dintr-un sablon static configurat pe nota; textul introdus de utilizator la adaugarea articolului e deja disponibil pe rand, fara politica. |
| `ID_VENCHELT` | `pack_facturare.nid_venchelt` | Acelasi fallback de sesiune pe care cursorul de azi il foloseste oricum ca prioritate (`NVL(pack_facturare.nid_venchelt, NVL(A.ID_VENCHELT, C.ID_VENCHELT))`, `ff_...:7244-7245`) — poate ramane `NULL` daca variabila de sesiune nu e setata, exact ca azi in acelasi caz. |
| `ID_SECTIE` | `pack_facturare.nid_sectie_stoc` | Acelasi tipar (`ff_...:7246`). |
| `IN_VALUTA` | `pack_facturare.nin_valuta` | **Nu e o presupunere noua** — e valoarea pe care cursorul de azi o **substituie deja** peste `D.IN_VALUTA` intr-un caz analog (`ff_...:7254-7260`, cand `A.ID_POL = pack_facturare.nid_politica_stoc AND pack_facturare.nin_valuta = 1`). Fiindca fara politica nu exista `D.IN_VALUTA` de citit, se foloseste direct flagul de document — acelasi flag pe care codul existent il trateaza deja ca sursa de incredere. |
| `CU_TVA` | **hardcodat `1`** | **Hardcodare explicita, de confirmat cu Marius.** `CU_TVA` (parametrul `V_CU_TVA` al `scrie_nota`, `ff_...:12347`) controleaza daca se scrie **separat** o linie de TVA (`ff_...:12537-12558`, `pack_facturare.scrie_tva(...)`) — nu trebuie confundat cu `V_PRET_ARE_TVA` (mapat pe `detalii_articol.pret_cu_tva`, deja disponibil independent de politica, controleaza doar interpretarea pretului). Pe baza vie, **toate cele 7 note de vanzari active au `CU_TVA=1`** (`verif_baza_vie_cont_venit.md` sectiunea 4) — nicio nota de vanzare reala cu `CU_TVA=0`. Semantic, `1` = comportamentul standard pentru o vanzare taxabila (TVA scrisa separat, necesar pentru raportarea de TVA); `0` n-are niciun exemplu real observat. Daca cota TVA a articolului e 0% (scutit), `scrie_tva` scrie oricum o linie cu suma 0 — inofensiv, nu gresit, dar de confirmat ca e acceptabil. |
**Apeluri, o singura data fiecare** (nu in bucla — nu exista cursor in aceasta ramura):
1. `pack_facturare.scrie_nota(...)` — aceiasi parametri ca la `ff_...:7443-7467`, cu valorile de mai
sus in locul celor din `crs_rand_articol`; restul (`cantitate`, `pret`, `discount_unitar`,
`pret_cu_tva`, `id_valuta`, `curs/multiplicator`, `id_ctr`, `proc_tvav`, `id_jtva_coloana`,
`taxcode`) vin din `detalii_articol`, exact ca azi — independente de politica.
2. `pack_facturare.descarca_gestiune(...)` — **aceeasi garda ca azi**
(`pack_facturare.nscadere_stoc=1 AND detalii_articol.id_gestiune<>-1000 AND
detalii_articol.in_stoc=1`, `ff_...:7473-7475`), cu `crs_rand_articol.id_sectie`/`.id_venchelt`
inlocuite de `pack_facturare.nid_sectie_stoc`/`.nid_venchelt` direct (fara cursor). **Ruleaza
exact o data, prin constructie** — nu exista `WHILE cursor%FOUND LOOP` in aceasta ramura, deci
defectul de "set multi-rand" (punctul urmator) nu poate aparea aici, fara sa fi fost nevoie sa se
repare nimic pe ramura veche.
3. Discount (`ff_...:7501-7518`), aceeasi garda (`discount_unitar<>0 AND ndiscount_evidentiat=1`),
cu `V_ASCD` si `V_CU_TVA` calculate mai sus in loc de cele din cursor.
4. `RETURN V_INCASAT_CALCUL;` — identic.
### 4. FACT-024 — ocolit doar pe ramura noua, garda neschimbata pe ramura veche
Blocul (`ff_...:7278-7302`) ramane **litera cu litera identic** in `ELSE`. Nu se slabeste nimic — o
linie fara politica **si** fara `cont_venit` continua sa primeasca FACT-024 exact ca azi. Bypass-ul
e strict conditionat de faptul ca VFP a trimis explicit un cont (`cont_venit IS NOT NULL`), nu de
absenta politicii in sine.
### 5. Bug-ul de set multi-rand — nemostenit, netratat
Documentat deja (`nota_contabila_fara_politica.md`, `verif_baza_vie_cont_venit.md` sectiunea 6.1):
`cursor_articol` face `LEFT JOIN NOTE_CONTABILE D ON C.ID_SET = D.ID_SET` fara `ROWNUM`/agregare, iar
bucla scrie venitul si descarca gestiunea o data per rand din set. **Ramura noua nu are cursor deloc**
— rezolva structural aceeasi clasa de bug, dar **nu e propusa ca reparatie a ramurii vechi**; ramane
un defect separat, de tratat separat, cum a cerut explicit team-lead-ul.
### 6. Suprafata de regresie
- **`contabilizeaza_articol`**: 3 apelanti, toti interni `pack_facturare` (`scrie_factura2`,
`scrie_factura_avize_retur`, `scrie_aviz_retur`) — **zero schimbari** la niciunul (sectiunea 1).
- **`adauga_articol_factura`**: **un singur apelant confirmat** in sursa citita,
`COMUN\clase\ofacturare.vc2:14069-14091`, duplicat identic la `:18089-18114` in aceeasi clasa
(posibil doua metode gemene, nu doua clase — neconfirmat, vezi mai jos). Apel pozitional, se
opreste la `V_LOT` — **neafectat** de un parametru nou dupa `V_LOT` cu `DEFAULT NULL`, pe acelasi
tipar deja folosit de `V_TAXCODE`/`V_LOT` insele.
- **Restul suitei** (ROAGEST, ROAAUTO, ROAACNPRO, ROAIMOB): pe baza cercetarilor anterioare
(`nota_contabila_fara_politica.md` sectiunea 4, `coresp_cont_venchelt.md` sectiunea 9b), aceste
produse folosesc `adauga_articol_factura_deviz`/`_stoc` (proceduri **separate**, semnaturi diferite,
**neatinse** de aceasta propunere) sau `pack_acn.salveaza_regdoc` (alt pachet complet). O cautare
directa, in aceasta runda, pentru apeluri catre `adauga_articol_factura(` (fara `_deviz`/`_stoc`) in
`COMUN`-urile celorlalte produse **nu s-a terminat in timp util** (comanda de fond nu a raspuns) —
vezi "Ce nu s-a putut stabili". Pe baza dovezilor deja existente (nimeni altcineva nu are un flux
documentat prin `adauga_articol_factura` simplu), riscul asteptat e **zero**, dar nu e demonstrat
exhaustiv pentru toata suita in aceasta runda.
- **Teste minime recomandate**: (a) factura normala cu politica, parametru `NULL` — verifica ACT
identic cu azi (regresie); (b) articol fara politica, `cont_venit` populat — un singur rand `ACT`,
`SCC`=valoarea data, `SCD='4111'`, linie TVA scrisa separat; (c) articol negestionabil
(`id_gestiune=-1000`) cu `cont_venit` populat — `descarca_gestiune` NU ruleaza; (d) discount pe
linie cu `cont_venit` populat; (e) document in valuta (`nin_valuta=1`) cu `cont_venit` populat —
`IN_VALUTA=1` pe nota, `SUMA_VAL` completat; (f) linie fara politica **si** fara `cont_venit` —
FACT-024 tot apare (regresie negativa, garda nu s-a slabit).
### 7. Alternativa mai mica — nu exista una reala
Propunerea de mai sus **e** deja varianta minimala: un singur parametru `VARCHAR2(4) DEFAULT NULL`,
zero schimbare de comportament cand e `NULL`, zero atingere a celor 3 apelanti interni. O varianta
"doar un flag care opreste FACT-024, fara sa transporte contul" tot ar avea nevoie ca `SCC` sa vina
de undeva — nu reduce suprafata, doar muta numele. Nu recomand separarea in doi parametri
(flag + cont) — complexitate in plus fara beneficiu; un singur camp nenul e semnalul suficient.
### Ce nu s-a putut stabili in aceasta runda, si de ce
- **Daca `ofacturare.vc2:14069-14091` si `:18089-18114` sunt doua metode/clase distincte sau o
duplicare literala a aceleiasi metode** — nu am identificat clasele-container ale celor doua
blocuri (ar necesita indexul de simboluri `vfp_symbols.ps1`, nefolosit in aceasta runda din lipsa
de timp). Nu schimba verdictul (ambele se opresc la `V_LOT`), dar conteaza pentru a sti cate locuri
VFP trebuie atinse ca sa se **foloseasca** efectiv noul parametru dupa ce va exista in Oracle.
- **Daca alte produse (ROAGEST/ROAAUTO/ROAACNPRO/ROAIMOB) apeleaza `adauga_articol_factura` simplu**
undeva neexaminat — comanda de cautare pe `COMUN`-urile celorlalte produse a ramas fara raspuns in
timp util in aceasta sesiune; de re-rulat separat inainte de implementare.
- **Linia exacta a `INSERT ... INTO VANZARI_DETALII ... SELECT ... FROM VANZARI_DETALII_TEMP`** din
`scrie_in_vanzari` — citata doar din raportul anterior (`nota_contabila_fara_politica.md`), nu
re-verificata pe fisierul curent in aceasta runda; necesara doar daca se decide sa se persiste si
`CONT_VENIT` pe `VANZARI_DETALII` (pasul optional de la sectiunea 2).
- **Comportamentul `scrie_tva` cu cota 0%** (linie scutita) cand `CU_TVA` e hardcodat la `1` — nu am
citit corpul `scrie_tva` in aceasta runda pentru a confirma ca o suma 0 nu produce vreun efect
secundar (ex. impact pe `nproc_tva_max`/`nid_jtva_coloana` la `ff_...:12538-12541`, care se
actualizeaza necondiționat de valoarea sumei).
- **Confirmarea explicita a lui Marius pe cele doua hardcodari** (`SCD='4111'`, `CU_TVA=1`) — sunt
presupuneri argumentate din date reale si din tiparul de cod existent, nu descoperiri; raman
decizii de proiectare deschise.
---
## Verdict runda anterioara (canal ocolitor, mandat vechi — pastrat ca input de proiectare)
**DA, exista un canal real, deja cablat si deja folosit in productie pentru categoria de document
"facturi emise"** — complet independent de `pack_facturare` si de politica de pret. E cursorul VFP
generic `actactan`/`tact` -> `oscrie_in_fisiere.prg` (INSERT generic in `ACT_TEMP` din campurile
oricarui cursor VFP) -> `pack_contafin.SCRIE_IN_ACT`/`STERGE_DIN_ACT` (nu `pack_facturare`!). Cel mai
relevant: **fluxul de editare a facturii emise, `ofacturare_comun.vc2:3796-3821` (proiectul #6
insusi), foloseste exact acest canal** ca sa lase utilizatorul sa editeze `SCD`/`ASCD`/`SCC`/`ASCC`
direct pe randul notei prin `frm_modific2024` (`omodificari.vc2`, fisier **nerestrictionat**), apoi
rescrie `ACT_TEMP` cu valorile din cursorul VFP editat. **Limitarea majora**: canalul e cablat pe
**editarea unei note deja scrise** (sterge + rescrie), nu pe **emiterea** unei facturi noi — emiterea
trece azi exclusiv prin `pack_facturare.scrie_factura2 -> contabilizeaza_articol`, care nu are nicio
ramura alternativa (confirmat in rundele anterioare, FACT-024). Pistele 1, 2, 4, 5 din cerere sunt
**toate NU** — niciuna nu ofera un canal catre `SCC`. DDL-ul `ACT_TEMP` nu blocheaza nimic din asta:
`SCD`/`SCC` sunt `VARCHAR2(4) NULL`, fara `CHECK`.
Sursa principala pentru citatele Oracle: **`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql`**
(17217 linii — confirmat `wc -l`). Fisierul din `docs\` nu mai exista, cum a semnalat cererea.
---
## Pistele cerute, in ordine
### 1. `V_CONT IN VARCHAR2` (parametru `adauga_articol_factura`) — **NU e canal pentru SCC**
Confirmat pe cod, nu doar preluat din raportul anterior (a carui concluzie pe acest punct era deja
corecta): `V_CONT` e contul de **gestiune/stoc** (clasa 3xx), nu de venit. E scris ca atare in
`VANZARI_DETALII_TEMP.CONT` (`adauga_articol_factura`, semnatura la
`ff_...:4989-5015` `V_CONT IN VARCHAR2`, folosire la `:5044-5046` `V_CONT2 := V_CONT`, `INSERT` la
`:5277`). **Niciodata folosit ca `SCD`/`SCC`** — `contabilizeaza_articol` isi ia `V_SCC` exclusiv din
`cursor_articol` (`D.SCC`, lantul `CRM_POLITICI_PRET_ART -> CRM_POLITICI_PRETURI -> CRM_NOTE_VANZARI
-> NOTE_CONTABILE`, `ff_...:7248-7253,7259-7260`), fara nicio ramura care sa citeasca `V_CONT`.
`V_CONT` alimenteaza doar `descarca_gestiune` (contul de iesire din gestiune, SCC pe nota de
**stoc**, nu de venit), nu nota de venit.
### 2. Variabile de sesiune `pack_facturare` — **NU exista setter pentru cont**
Am listat toate variabilele publice de pachet cu prefix `nid_` din specificatia `pack_facturare`
(`ff_...:72-211`, citat exhaustiv, cautare `grep -n "^ nid_"`):
```
nid_tipnir, nid_tipbon, nid_tipfactura, nid_tipaviz, nid_act, nid_serie, nid_fdoc, nid_part,
nid_part_rez, nid_lucrare, nid_sectie_stoc, nid_gestiune_sursa, nid_responsabil, nid_ordl, nid_set,
nid_util, nid_moneda_nationala, nid_fact, nid_factc, nid_partc, nid_jtva_coloana, nid_comanda,
nid_valuta, nid_politica_stoc, nid_sucursala, nid_venchelt, nid_vanzare, nid_beneficiar
```
Niciuna tipata pe un cont (`VARCHAR2(4)`/cod de cont) — toate sunt FK-uri numerice
(`%TYPE` pe alte tabele: `ID_SECTIE`, `ID_VENCHELT`, `ID_POL`, etc.). Cautare directa
`nid_scc`/`nid_scd`/`nid_cont` in tot fisierul: **zero rezultate**. `nid_venchelt` (folosit ca
fallback la `ID_VENCHELT` in `cursor_articol`, `ff_...:7244-7245`, deja documentat in
`coresp_cont_venchelt.md` sectiunea 7) e o clasificare dimensionala
(`NOM_VENIT_CHELTUIELI.ID_VENCHELT%TYPE`), nu un cont — **nu am gasit consumator care sa-l foloseasca
drept `SCC`**. Cautare separata `PROCEDURE SET_` in tot pachetul: zero rezultate — nu exista niciun
setter public de tip `SET_...` pentru cont. **Concluzie: NU.**
### 3. `ACT_TEMP` scris direct din VFP — **DA, canal real, dar pe fluxul de editare, nu de emitere**
Confirmat de `COMUN\docs\oracle_export.md:64-65`: *"Pachetul central de scriere a documentelor —
clientul VFP populeaza tabelele temporare `ACT_TEMP`/`RUL_TEMP` (prin `oscrie_in_fisiere`-ul din
COMUN), apoi pachetul distribuie"*. Mecanismul e generic si complet independent de `pack_facturare`:
**Mecanismul** (`COMUN\programe\oscrie_in_fisiere.prg`):
- `sql_temp_insert('actactan','ACT_TEMP')` (`oscrie_in_fisiere.prg:127`) face, pentru fiecare rand al
oricarui cursor VFP numit `actactan`, un `INSERT INTO ACT_TEMP (<coloanele care exista si in
cursor si in tabel>) VALUES (...)` construit dinamic din `user_tab_columns`
(`oscrie_in_fisiere.prg:190-280`) — **orice camp `SCD`/`ASCD`/`SCC`/`ASCC` prezent in cursorul VFP
ajunge direct in `ACT_TEMP`, indiferent de valoare, fara nicio validare de cont**.
- Scrierea efectiva in `ACT` se face prin `pack_contafin.init_scriere_act_rul_local` +
`final_scriere_act_rul_local` -> `SCRIE_IN_ACT`/`STERGE_DIN_ACT` (`oscrie_in_fisiere.prg:121-147`)
— **`pack_contafin`, nu `pack_facturare`**. Confirmat si in
`COMUN\docs\flux-modificare-stergere-nota-jurnal.md:20-28`.
**Cine populeaza `actactan` cu valori calculate/editate de VFP** — cele doua cazuri gasite, ambele
active in productie:
**(a) Registrul Jurnal — editare/stergere manuala de nota, orice document, generic**
(`COMUN\clase\comun.vc2`, clasa `afisjurcom`):
- `do_modifica` (`comun.vc2:2222-2562`): incarca nota existenta
(`Select * From v_act Into Cursor actactan`, `comun.vc2:2363`), instantiaza
`frm_modific2024` (`comun.vc2:2439`, `omodificari.vc2:6375`) — formular in care utilizatorul poate
edita direct `scd`/`ascd`/`scc`/`ascc` pe fiecare rand al notei (grid legat pe `tact`, verificare
prin `verific_analitic`/`do_verifica`, tipar prezent si in `omodificari.vc2:1714-1788` — comentat
azi, dar acelasi tipar activ e in `frm_modific2024`, vezi mai jos (b)). Dupa editare:
`oscrie_in_fisiere(2,...)` = sterge nota veche (`comun.vc2:2454`), apoi
`oscrie_in_fisiere(0,...)` = scrie nota noua **cu valorile din cursorul editat**
(`comun.vc2:2482`), apoi `pack_contafin.finalizeaza_modificare_nota(...)`
(`comun.vc2:2484-2486`). **Niciun apel catre `pack_facturare` in acest flux.**
- Documentat integral, cu aceleasi citate, in `COMUN\docs\flux-modificare-stergere-nota-jurnal.md`.
- E generic pe orice document din `ACT` (nu doar facturi) — daca o factura emisa are deja o nota,
poate fi editata de aici.
**(b) Editarea facturii emise — acelasi mecanism, scop specific "facturi emise" (proiectul #6
insusi)**, `COMUN\clase\ofacturare_comun.vc2:3769-3838` (functia `do_editare_factura`, citita
integral, **nu modificata**):
```
ofacturare_comun.vc2:3769 If IncarcaCursoareModificareNota(lnCod, pnAn, pnLuna, .F.) && ofacturare_editare.prg
...
ofacturare_comun.vc2:3787 Select a.*, Iif(Nvl(id_jtva_coloana,0)=0,0,1) As cu_Tva From tact a Into Cursor tact Readwrite
...
ofacturare_comun.vc2:3796 Omodif = Createobject([frm_modific2024], lnIdSet)
ofacturare_comun.vc2:3797 Omodif.Show()
ofacturare_comun.vc2:3799 If buton = 1
ofacturare_comun.vc2:3800 If Thisform.do_deschide_tranzactie()
ofacturare_comun.vc2:3801 Select actactan
ofacturare_comun.vc2:3802 lnSucces = OSCRIE_IN_FISIERE(2,.T.,.T.) && sterge nota veche
ofacturare_comun.vc2:3803 If lnSucces > 0
...
ofacturare_comun.vc2:3807 Select tact
ofacturare_comun.vc2:3808 Replace id_jtva_coloana With Null, proc_tva With 0 For cu_Tva = 0
ofacturare_comun.vc2:3809 Select * From tact Into Cursor actactan Readwrite && re-materializeaza tact (inclusiv orice SCD/SCC editat) in actactan
ofacturare_comun.vc2:3810 Replace All id_util With gnIdUtil, sters With 0
...
ofacturare_comun.vc2:3821 lnSucces = OSCRIE_IN_FISIERE(0,.T.,.T.) && scrie nota noua, direct din actactan, in ACT_TEMP
ofacturare_comun.vc2:3823 If lnSucces > 0
ofacturare_comun.vc2:3824 lcSql = [begin pack_contafin.finalizeaza_modificare_nota(...); end;]
ofacturare_comun.vc2:3828 If lnSucces > 0 And "OFACTURARE_EDITARE" $ Upper(Set("Procedure")) And Used('tvanz')...
ofacturare_comun.vc2:3829 lnSucces = Iif(ScrieArticoleFacturaEditate(tvanz.id_vanzare), 1, -1) && scrie si VANZARI_DETALII
```
`IncarcaCursoareModificareNota` (`COMUN\programe\ofacturare_editare.prg:32-71`) incarca nota
existenta a facturii (`vact_tot -> v_act -> actactan -> tact`, toate **READWRITE**) inainte de a
arata `frm_modific2024`. Linia `:3809` **rescrie `actactan` direct din `tact`** — orice valoare
aflata pe `tact.scd`/`tact.scc` in acel moment (editata manual prin `frm_modific2024`, sau setata
programatic de orice cod VFP inainte de linia 3809) devine noua nota, scrisa in `ACT_TEMP` prin
`OSCRIE_IN_FISIERE(0,...)` la linia 3821 — **fara niciun apel `pack_facturare`, fara politica de
pret**. `pack_contafin.finalizeaza_modificare_nota` (linia 3824) doar re-leaga `cod`-ul nou de
`VANZARI`; `ScrieArticoleFacturaEditate` (linia 3829) scrie separat `VANZARI_DETALII`.
**Aceasta e dovada cea mai puternica posibila pentru intrebarea pusa**: canalul nu e teoretic — e
**exact mecanismul pe care proiectul #6 il foloseste azi** ca sa permita editarea contului unei
facturi deja emise, complet in afara `pack_facturare`.
**Limitarea reala**: mecanismul opereaza pe **o nota deja existenta** (sterge randul vechi din `ACT`,
scrie unul nou cu acelasi `id_fact`) — presupune ca factura a fost deja scrisa o data (prin
`pack_facturare`, cu politica). Nu e (azi) un canal pentru **emiterea** initiala a unei facturi noi
cu un articol fara politica — `scrie_factura2 -> contabilizeaza_articol` (calea de emitere) nu are
nicio ramura care sa ocoleasca politica si nu apeleaza acest mecanism.
**Alte doua confirmari ale aceluiasi tipar, tot pentru categoria "facturi"**:
- `COMUN\ferestre\frm_initializare_facturi_balanta.sc2:458` — `CREATE CURSOR actactan (id_set I, an
N(4), luna N(2), Dataact D, datascad D, dataireg D, serie_act C(20), nract N(20), proc_tva N(5,2),
id_jtva_coloana I NULL, scd C(4), ascd C(4), scc C(4), ascc C(4), ...)` — cursor creat de la zero
in VFP, cu `scd`/`scc` campuri simple, editabile liber, fara nicio derivare Oracle. Foloseste tot
`frm_modific2024` (`:1806`) pentru editare/validare inainte de scriere.
- `COMUN\ferestre\frm_import_note_facturi_clienti.sc2:667,815,898,911` — acelasi tipar
(`actactan`/`tact` editabil + `frm_modific2024`), pentru import manual de note pe facturi de
clienti.
Ambele sunt scenarii de **initializare/import** (sold de deschidere, import de note), nu de
facturare curenta — dar confirma ca `ACT_TEMP` pentru **categoria "facturi"** se scrie deja, in mod
curent, direct din cursoare VFP construite de la zero, fara `pack_facturare`.
### 4. `ID_VENCHELT` / `CRM_NOTE_VANZARI` — **NU e canal alternativ catre SCC**
Deja stabilit exhaustiv in `coresp_cont_venchelt.md` sectiunea 7: `ID_VENCHELT` e o dimensiune
(`NOM_VENIT_CHELTUIELI.ID_VENCHELT`), citita cu fallback pe `nid_venchelt`
(`ff_...:7244-7245`), dar **nu participa la calculul `SCC`** — `V_SCC` vine exclusiv din
`cursor_articol.D.SCC`. Nu exista camp de tip cont pe `VANZARI`/`VANZARI_DETALII` — reconfirmat aici
prin cautare `grep -inE "SCC|CONT_VENIT"` in blocurile `CREATE`/`ALTER TABLE VANZARI` din
`ff_...` (fara rezultate suplimentare fata de ce era deja stabilit).
### 5. `GetAnaliticByGrupUtilizatori` — **doar analitic, nu cont sintetic**
Confirmat deja in `coresp_cont_venchelt.md` sectiunea 7: functia da fallback pentru `ASCD`/`ASCC`
(analiticul), nu pentru `SCD`/`SCC` (contul sintetic). Nu exista o functie analoaga pentru cont —
cautare `GetSinteticBy`/`GetContBy` in tot `ff_...`: zero rezultate.
---
## Lista exhaustiva a intrarilor catre `SCD`/`SCC` in `ACT_TEMP`, pe/langa fluxul de facturare
Sursa: `ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql` + fisierele VFP citate.
1. **`pack_facturare.contabilizeaza_articol -> scrie_nota`** (`ff_...:7218-7556` / `12338-12570`,
`INSERT INTO ACT_TEMP` la `:12458-12544`) — calea principala de **emitere**. `SCD`/`SCC` vin din
`cursor_articol` (`D.SCD`, `D.SCC`, lantul politicii). Blocheaza cu FACT-024
(`:7275-7311`) daca articolul nu e in politica — fara fallback (deja stabilit in
`nota_contabila_fara_politica.md`).
2. **Ramurile speciale din `scrie_factura2`** (transfer subunitati `ntip IN (23,25,30,41)`, custodie
`ntip IN (42,47)`, rata `id_rata<>0`) — tot `contabilizeaza_articol`, acelasi punct 1.
3. **`scrie_factura_avize_retur`** (`ff_...:6273-6666`, apel la `:6867`) si **`scrie_aviz_retur`**
(`ff_...:7094-7180`, apel la `:7149`) — tot `contabilizeaza_articol`.
4. **`descarca_gestiune`** (`ff_...:7476-7498`, apelata din interiorul buclei `cursor_articol`) —
scrie o a doua nota, de **iesire din gestiune** (`SCD`/`SCC` = conturi de stoc, din `V_CONT`/
`poArticol.Cont`, nu din politica) — parte a fluxului de facturare, dar nu e nota de venit.
5. **Discount pe linie** (`ff_...:7501-7518`) — scrie o nota separata (vazuta pe date live ca
`id_nota=2`, `SCD=667`/`SCC=4111`, `verif_baza_vie_cont_venit.md` sectiunea 4) — tot in interiorul
`cursor_articol`, deci tot dependenta de politica pentru a ajunge acolo.
6. **`oscrie_vanzare_din_stoc`** (`COMUN\programe\ofacturare_stoc.prg:104-450`) — flux ROAGEST
"vanzare din stoc". Apeleaza `pack_facturare.adauga_articol_factura_stoc` per articol
(`:357-378`) apoi `oscrie_in_fisiere(0,.F.,.T.)` (`:392`). **Neverificat complet**: codul citit nu
arata explicit unde/cum se populeaza `actactan` cu `SCD`/`SCC` inainte de linia 392 in acest flux
particular (cursorul `ACTACTAN` e doar *citit* la `:253-289` pentru alte campuri, nu am gasit
punctul de scriere in fisierul citit) — posibil populat de o procedura anterioara neexaminata.
Marcat ca zona neinchisa, vezi "Ce nu s-a putut stabili".
7. **Registrul Jurnal — editare/stergere manuala** (`COMUN\clase\comun.vc2:2222-2724`, clasa
`afisjurcom`) — canalul confirmat la pista 3(a). Genereic, orice document din `ACT`.
8. **Editare factura emisa** (`COMUN\clase\ofacturare_comun.vc2:3769-3838`, proiectul #6) — canalul
confirmat la pista 3(b), specific "facturi emise".
9. **`frm_initializare_facturi_balanta.sc2`** si **`frm_import_note_facturi_clienti.sc2`** — canalul
confirmat la pista 3, scop initializare/import pe categoria "facturi".
10. **eFactura import** (`COMUN\clase\anaf_efactura.vc2:12241,13087-13102,13244-13325`) — acelasi
tipar generic (`actactan`/`tact` + `frm_modific2024` + `oscrie_in_fisiere`), dar pentru facturi
de **achizitie** importate din XML ANAF, nu facturi emise — mentionat pentru completitudine, nu
aplicabil direct la #13.
11. **`ointroduceri.vc2`/`ointroduceri.prg`** (NIR, BON, RETUR, intrare din gestiune valorica) si
**`oschimbare_pret.prg`**, **`oproceduri_rulaje.prg`**, **`reglari_denominare2005.prg`** —
acelasi canal generic `actactan`/`oscrie_in_fisiere`, dar pentru alte categorii de document
(gestiune, nu vanzare/factura). Mentionate pentru completitudinea listei de consumatori ai
canalului, nu aplicabile la #13.
**Niciuna dintre intrarile 1-6 (fluxul de emitere efectiv) nu are o ramura care sa ocoleasca
politica.** Intrarile 7-11 folosesc toate acelasi canal generic (punctul 3), dar niciuna nu e
cablata pe fluxul de **emitere** — toate opereaza pe note deja existente sau pe alte categorii de
document.
---
## DDL `ACT_TEMP` (interogat 10.08.2026, schema `MARIUSM_AUTO`, `ROA_CENTRAL`)
| Coloana | Tip | Null |
|---|---|---|
| SCD | VARCHAR2(4) | **Y** |
| ASCD | VARCHAR2(4) | Y |
| SCC | VARCHAR2(4) | **Y** |
| ASCC | VARCHAR2(4) | Y |
| COD, NRACT, SUMA, PERECHED, PERECHEC, SUMA_VAL, CURS, NEIMPOZAB, NNIR, ID_UTIL, ID_UTILS, ID_RESPONSABIL, ID_VENCHELT, ID_SECTIE, ID_SET, ID_FACT, ID_PARTD, ID_PARTC, ID_FDOC, ID_LUCRARE, ID_GESTIN, ID_GESTOUT, ID_VALUTA, PROC_TVA, STERS, ID_FACTD, ID_FACTC, VALIDAT, TVA_INCASARE | numeric | N (29 coloane NOT NULL, restul optionale) |
Restul coloanelor (52 in total) sunt fie `NUMBER` (majoritatea `NOT NULL`), fie `DATE`/`VARCHAR2`
opționale (`DATAIREG`, `EXPLICATIA`, `DATASCAD`, `EXPLICATIA4/5`, `ID_SUCURSALA`, `ID_ACT`, `ID_CTR`,
`ID_JTVA_COLOANA`, `SERIE_ACT`, `ID_UTILV`, `DATAORAV`, `TAXCODE`, `PAYMENTCODE`).
Constrangeri: **29 `CHECK` constraints** (`SYS_C0014966`...`SYS_C0014994`) — corespund exact
coloanelor `NOT NULL` de mai sus (Oracle genereaza `CHECK (coloana IS NOT NULL)` pentru `NOT NULL`
declarat fara nume). **Niciun constraint pe `SCD`/`SCC`** (nici `NOT NULL`, nici `CHECK` de format,
nici FK catre un plan de conturi). **Nicio cheie primara/unica** — normal pentru un tabel `_TEMP` de
staging. Concluzie: schema **nu blocheaza in niciun fel** o valoare `SCC` calculata de VFP, oricare
ar fi ea, inclusiv `NULL`.
---
## Ce nu s-a putut stabilit si de ce
- **Punctul exact unde `ACTACTAN` primeste `SCD`/`SCC` in fluxul `oscrie_vanzare_din_stoc`**
(`ofacturare_stoc.prg`, intrarea 6 de mai sus) — codul citit (`:104-450`) nu arata sursa; ar
necesita urmarirea completa a apelantului (`initializeaza_vanzare_din_stoc`) si a modulului care
populeaza `ACTACTAN` inainte de acest punct (posibil `pack_facturare.adauga_articol_factura_stoc`
intoarce un ref cursor legat automat de `goExecutor` pe numele `actactan`, dar nu am gasit apelul
explicit). Nu schimba verdictul (oricum ar fi tot `pack_facturare`, deci tot politica), dar ramane
o zona neinchisa complet.
- **Daca discountul pe linie (`SCD=667`/`SCC=4111`) are vreo cale alternativa in afara
`cursor_articol`** — nu verificat aici, presupus dependent de politica la fel ca restul buclei.
- **Comportamentul practic al `frm_modific2024` cu privire la validarea contului tastat manual**
(daca exista vreo verificare `verific_cont`/plan de conturi la salvare, sau accepta orice text de
4 caractere) — nu urmarit pana la capat in `omodificari.vc2`; relevant doar daca se propune
reutilizarea canalului 3(b)/3(a) pentru scriere programatica (fara interactiune UI), caz in care ar
trebui verificat daca `frm_modific2024` insusi impune vreo validare care ar bloca o scriere
automata.
- **Daca fluxul de emitere (`scrie_factura2`) ar putea, teoretic, sa scrie intai o factura "goala" de
nota (sau cu o nota tehnica minimala) si apoi sa foloseasca imediat, in aceeasi tranzactie logica,
mecanismul de la pista 3(b) pentru a corecta `SCC`-ul** — nu explorat aici (ar fi o propunere de
design, in afara scopului acestei cercetari read-only); mentionat doar ca directie posibila care
reiese direct din ce s-a gasit.
- Nu am cautat/citit `pack_contafin.SCRIE_IN_ACT`/`STERGE_DIN_ACT` in `PACK_CONTAFIN.pck` pentru a
confirma ca acestea, la randul lor, nu re-deriva `SCC` din altceva — presupunerea (bazata pe
`oracle_export.md` si pe `flux-modificare-stergere-nota-jurnal.md`, care descriu deja aceste
proceduri drept "distribuie ce a scris clientul", nu "recalculeaza") e ca fac un simplu
`INSERT INTO ACT SELECT * FROM ACT_TEMP`-tip transfer, nu o derivare noua — dar nu am deschis
personal codul lor in aceasta runda.