Files
roafacturare/docs/cercetare/rec_suma_act.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

470 lines
32 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Cercetare: regula corecta pentru "suma comparabila din ACT" (S4b, plan_06 sectiunea C.1)
Raspunde la corectia lui Marius din 08.08.2026 (pagina noua se aplica pe orice rand din VANZARI,
avizele folosesc 418, exista randuri de discount, utilizatorul poate adauga note proprii) SI la
trei completari ulterioare, tot de la Marius: (1) ipoteza ca `id_set+5` la discount e un marcaj
tranzitoriu, (2) surse noi de date reale (`VENDING` productie, `ROMFAST@ROA_ROMFAST`), (3) ipoteza
liniilor de diferenta de pret in `RUL` pentru marfa tinuta la pret de vanzare.
Surse: export `PACK_FACTURARE.pck`/`PACK_CONTAFIN.pck` din `MARIUSM_AUTO@ROA_CENTRAL` (facut
sesiunea anterioara, verificat la zi). Interogari noi in aceasta sesiune pe **trei scheme**,
consemnate explicit la fiecare rezultat: `MARIUSM_AUTO@ROA_CENTRAL` (date de test), `ROMFAST@ROA_ROMFAST`
(client real, conexiune directa fara tunel, `10.0.20.36:1521`, credentiale `ROMFAST/ROMFASTSOFT`,
gasita in `tnsnames.ora` — nu era in `oracle.md`, testata si confirmata functionala) si
`contafin_oracle@VENDING` (productie, tunel `stnlc.exe` pornit headless in aceasta sesiune,
`alter session set current_schema=VENDING`, **strict citiri**, zero DDL/DML/COMMIT). Toate
interogarile sunt `SELECT`.
## 0. Ipoteza `id_set+5` — CONFIRMATA, garda din runda 3 e pe premisa falsa
**Raspuns direct**: Marius are dreptate. `id_set+5` e un marcaj **tranzitoriu**, folosit doar cat
timp randul de discount sta in `ACT_TEMP`, si e **rescris la valoarea de baza inainte sa ajunga in
`ACT`**. Randurile de discount **nu ajung niciodata in `ACT` cu `id_set+5`** — confirmat atat pe
cod cat si pe date, pe trei scheme diferite.
### Pe cod — locul exact care consuma marcajul
`PACK_FACTURARE.scrie_discount` (`:12859-13057`) face `nid_set := nid_set + 5` la intrare
(`:12901`), scrie randul `DISCOUNT`/`TVA DISCOUNT` in `ACT_TEMP` cu acel `id_set`, apoi restaureaza
variabila de pachet la valoarea veche (`:13054`, `pack_facturare.nid_set := V_ID_SET`) — **inainte
sa revina la apelant**. Pana aici, exact ce descria constatarea anterioara (`rec_garda_idset.md`).
Verificat acum: `PACK_CONTAFIN.SCRIE_IN_ACT` (`:630-966`) copiaza `ACT_TEMP -> ACT` printr-un
singur `INSERT INTO ACT (V_LISTA_CAMPURI) SELECT V_LISTA_CAMPURI FROM ACT_TEMP` (`:956-958`) —
copiere directa, coloana cu coloana, **fara nicio transformare a `ID_SET`**. Cautare exhaustiva
"`SET ID_SET`" in ambele pachete — 0 rezultate in afara acestui INSERT. Singurul trigger pe `ACT`
(`TRG_ACT_BEFOINS`) doar aloca `ID_ACT` din secventa, nu atinge `ID_SET`.
**Locul real de normalizare**: `PACK_FACTURARE.cumuleaza_note_act_temp` (`:14112-14322`), apelata
din `cumuleaza_note_act` (`:14073-14110, apel la :14095`), care la randul ei e apelata din
**toate** cele 4 proceduri care scriu nota (`scrie_avize_lucrare:5954`, `scrie_factura2:6191`,
`scrie_factura_avize_retur:7027`, `scrie_aviz_retur:7139` — si `scrie_factura_avize` prin acelasi
tipar), **dupa** ce bucla de linii si apelul de discount de document s-au terminat. In interior,
`cumuleaza_note_act_temp` re-agrega `ACT_TEMP` (SUM pe `SCD`/`SCC`/etc., GROUP BY inclusiv
`A11.ID_SET` — deci grupurile raman distincte in subinterogare), dar **SELECT-ul exterior nu
foloseste `A.ID_SET` din grupare** — il inlocuieste explicit cu:
```sql
pack_facturare.nid_set AS ID_SET -- PACK_FACTURARE.pck:14198
```
Adica STAMPEAZA fiecare rand rezultat cu valoarea CURENTA a variabilei de pachet `nid_set`, care in
acest moment (dupa ce toate apelurile `scrie_discount` — de linie si de document — si-au restaurat
deja valoarea) e valoarea de baza, nu +5. Deci: `id_set+5` serveste DOAR ca sa tina randurile de
discount intr-un grup separat in `GROUP BY` (sa nu se insumeze din greseala cu alt rand cu acelasi
`SCD`/`SCC` dar alt sens), dupa care marcajul se arunca si toate randurile documentului ies din
`cumuleaza_note_act_temp` cu **acelasi** `id_set`, cel de baza. Asta ajunge apoi neschimbat in
`ACT` prin copierea directa de mai sus.
### Pe date — confirmat pe trei scheme, inclusiv productie
Cautare directa in `ACT` (nu `ACT_TEMP`) dupa `EXPLICATIA LIKE '%DISCOUNT%'`, comparat cu `id_set`
al randurilor-sora din acelasi document:
- **`MARIUSM_AUTO`**: 64 randuri de discount gasite, documente din **2008 pana in 2026** (inclusiv
`cod=1140715/1140719/1140727`, martie 2026, scrise cu codul curent). Verificat detaliat pe
`cod=1140727`: 10 randuri active, toate cu **`id_set=25012`** — inclusiv cele 2 perechi
`DISCOUNT`/`TVA DISCOUNT`. Niciun `25017`. Query/rezultat: `q_discount_full_doc.sql`/
`out_discount_full_doc.txt`.
- **`ROMFAST@ROA_ROMFAST`** (client real): 6 randuri de discount (2002-2007). Pe `cod=1135870`:
5 randuri, toate `id_set=25010`, inclusiv discountul. Query: `q_romfast_discount_full.sql`.
- **`VENDING`** (productie): 100 randuri de discount extrase (2017-2018, esantion — exista mai
multe). **Toate** cu `id_set=25010`, uniform, pe zeci de documente diferite. Verificat detaliat
pe `cod=1118081` (17 randuri: linii de vanzare + TVA + 2 perechi discount) si `cod=1130634` —
ambele cu `id_set=25010` pe TOATE randurile, discount inclus. Query: `q_vending_discount_full.sql`.
**Zero exceptii gasite, pe 18 ani de date si 3 scheme.** Ipoteza alternativa ("2 `id_set` distincte,
diferenta exact 5") nu are niciun caz real care s-o sustina — nu doar ca sunt "date de test
insuficiente" (cum spunea concluzia rundei 3), ci pentru ca **mecanismul de scriere reface tacit
`id_set` la valoarea de baza inainte de commit, indiferent de tipul documentului sau de schema**.
### Concluzie asupra garzii din `do_editare_factura`
Garda din `COMUN\clase\ofacturare_comun.vc2:3781-3805` (admite editarea la 1 `id_set`, sau la
exact 2 cu diferenta 5, refuza restul) e construita pe o premisa care **nu se poate produce prin
codul curent**. Ramura "2 `id_set` cu diferenta 5" e cod mort — nu exista si nu poate exista in
`ACT` un document scris de `PACK_FACTURARE` curent care sa ajunga acolo. Consecinta directa:
- **Simplificare recomandata**: garda poate reveni la forma simpla dinainte de runda 3 — un singur
`id_set` asteptat, refuz la >1 — pentru ca *azi* orice document scris cu codul curent are un
singur `id_set` in `ACT`, discount inclus.
- **Dar nu se recomanda stergerea completa a toleran­tei**: exista randuri VECHI (2008-2016, pe
toate cele 3 scheme, scrise cu versiuni mai vechi de pachet) unde nu s-a verificat *garantat* ca
niciodata n-a existat un `id_set` divergent — esantionul confirma 0 cazuri, dar nu e o dovada
exhaustiva pentru tot istoricul. **Recomandare concreta**: pastreaza ramura de toleranta la +5
ca plasa de siguranta (cost zero, cod deja scris si testat), dar tratatati-o explicit ca
"acopera randuri istorice neasteptate, nu comportamentul curent" in comentariu/documentatie — nu
mai justifica prezenta ei prin "pachetul curent poate scrie asa", pentru ca nu poate. Decizia
finala (simplificare vs. pastrare-ca-plasa) e a lui Marius — argumentele de mai sus sunt pentru
ambele variante, cu recomandare usoara spre **pastrare ca plasa de siguranta, cu comentariul
corectat**, ca sa nu se piarda acoperirea pe randuri istorice fara sa se castige nimic (ramura
suplimentara e deja scrisa, testata, fara cost de mentinere vizibil).
## A. Unde se genereaza nota contabila a documentului
Cod server-side, in `PACK_FACTURARE` (nu `PACK_CONTAFIN`, care doar copiaza `ACT_TEMP` -> `ACT`
la commit si face verificari/corelatii ulterioare).
**Lantul de apel, per tip de document**, toate scriu in `ACT_TEMP` prin functia comuna
`scrie_nota` (`PACK_FACTURARE.pck:12332-12564`):
- `scrie_factura2` (`:6009-6212`) - calea GENERICA, pentru marea majoritate a tipurilor. In bucla
pe liniile din `VANZARI_DETALII_TEMP` (`:6059-6133`), ramifica pe `pack_facturare.ntip`:
- `tip IN (23,25,30,41)` (transfer catre subunitati) -> `transfera_articol` (`:10323-...`) - cont
de stoc, derivat din configurarea gestiunii, NU cont de client.
- `tip IN (42,47)` (custodie) -> DOAR `descarca_gestiune` (miscare de stoc); nicio linie in ACT
prin `contabilizeaza_articol`/`scrie_nota` pentru articol (`:6087-6112`).
- `tip IN (2,6,52)` cu `id_rata<>0` (rate/contract) -> `contabilizeaza_rata` (`:7541-...`), cont
derivat din `CONTRACTE -> CRM_NOTE_VANZARI -> NOTE_CONTABILE` (`:7557-7584`), NU hardcodat.
- restul -> `contabilizeaza_articol` (`:7165-7539`).
- `scrie_factura_avize` (`:6683-...`) - facturare **din aviz** (`tip=4`), acelasi
`contabilizeaza_articol` per linie (`:7132`), plus interogare separata (`:6763-6789`) care cauta
randul `ACT` al avizului original, `C.SCD = DECODE(B.TIP, 42, '357', '418')`.
- `scrie_avize_lucrare` (`tip=27`, `:5811-...`) - cale separata, cont de stoc.
**`contabilizeaza_articol`** (`:7165-7539`, ramura articol simplu, `:7383-7536`) decide contul
DEBIT, `CASE` la `:7390-7415`:
```
WHEN ntip <= 20 OR ntip IN (44,45,46,43,48,49,51,52) THEN
V_SCD := crs_rand_articol.scd -- din NOTE_CONTABILE (configurabil), nu hardcodat
WHEN ntip IN (28,29) THEN
V_SCD := '461' -- hardcodat, aviz catre clienti DEBITORI
ELSE
V_SCD := '418' -- hardcodat, restul avizelor catre client
```
`crs_rand_articol.scd` vine din `CRM_POLITICI_PRET_ART -> CRM_POLITICI_PRETURI -> CRM_NOTE_VANZARI
-> NOTE_CONTABILE` (`:7210-7259`), cheie `NOTE_CONTABILE.ID_SET` (alt spatiu de numerotare fata de
`pack_facturare.nid_set`/`ACT.ID_SET` — verificat: 25000-25100 nu exista deloc in `NOTE_CONTABILE`
pe `MARIUSM_AUTO`). Empiric, pe toate tipurile de factura testate, a iesit mereu `4111` — vezi C.
**Discountul** (`scrie_discount`, `:12859-13057`) scrie pe SENSUL OPUS fata de linia de vanzare:
```
WHEN ntip = 4 THEN SCD='4111', SCC='418', SUMA negativa (direct pe debit)
WHEN ntip<=20 SAU in (44,45,46,43,48,49,51,52) THEN SCD='667', SCC='4111' (pe CREDIT)
ELSE (avize) SCD='667', SCC='418' (pe CREDIT)
```
Consecinta: pe facturi normale (nu tip=4), `SUM(SUMA) WHERE SCD='4111'` simplu IGNORA discountul.
Suma corecta e soldul NET: `SUM(SUMA WHERE SCD=cont) - SUM(SUMA WHERE SCC=cont AND SCD NOT IN
('5311','5314','5121','5125','5126'))` (exceptia exclude incasarile simultane).
Formula NU e inventata — e cea folosita chiar de aplicatie pentru auto-verificare la emitere:
`verifica_total_document` (`:16073-16145`), rulata dupa scriere. **Gol de acoperire preexistent,
nu introdus de #6**: conditia (`:16079-16083`) exclude `43`/`46` din ramura `4111`, desi
`contabilizeaza_articol` le trateaza ca facturi — pentru aceste doua tipuri, verificarea proprie a
aplicatiei cade in ramura gresita si nu face nimic (comparatie cu `NULL`). Semnalat pentru
completitudine, nu necesita reparare in S4b.
## B. Regula per tip de document
| Grup de `TIP` | Cale de scriere | Cont debit (linie) | Discount document | Comparabil cu `TOTAL_CU_TVA`? |
|---|---|---|---|---|
| Facturi (1,2,3,5,7,8,9,10,43,44,45,46,48,49,52 fara rata; 51) | `scrie_factura2` -> `contabilizeaza_articol` | din `NOTE_CONTABILE` (empiric mereu `4111`, pe 3 scheme) | `667`(debit)/`4111`(credit), NET | DA - regula neta |
| Factura din aviz (4) | `scrie_factura_avize` -> `contabilizeaza_articol` | `4111` | `4111` direct, semn negativ | DA - `SUM(SCD='4111')` simplu |
| Vanzare pe rate/contract (2,6,52 cu `id_rata<>0`) | `contabilizeaza_rata` | din `NOTE_CONTABILE` legat de `CONTRACTE` | idem tipar factura | DA - confirmat pe `ROMFAST` (tip=2, majoritar rata), vezi C |
| Avize catre clienti debitori (28,29) | `contabilizeaza_articol` | `461` (hardcodat) | analog | DA - regula neta, cont `461` |
| Avize catre client, restul (21,22,24,26) | `contabilizeaza_articol` | `418` (hardcodat) | `667`/`418` | DA - regula neta, cont `418`, confirmat si pe productie |
| Transfer catre subunitati (23,25,30,41) | `transfera_articol` | cont de STOC (nu client) | - | NU |
| Transfer pe lucrare (27) | `scrie_avize_lucrare` | cont de STOC (confirmat pe date) | - | NU |
| Custodie (42,47) | doar `descarca_gestiune` | - | - | NU - zero randuri ACT per articol, by design |
| ROAACNPRO (51) | cale de import proprie | `4111` (**confirmat de Marius stabil** - vezi nota) | necunoscut | probabil DA per cont, dar divergenta mare pe 1 caz, cauza suspecta = filtrare `cod` fara `an`+`luna` |
| tip=50 | marcat "in lucru" | - | - | in afara scopului |
**Nota tip=51 — cont confirmat, divergenta pe `cod=1138989` investigata separat (vezi C, subsectiune
dedicata)**. Marius e categoric: **`4111` e contul stabil** pentru tip=51, punct. Randurile `411`
gasite izolat in trecerea anterioara nu se mai trateaza ca a doua conventie de cont — verificat
acum direct pe `cod=1138989` (12 randuri ACT, toate `SCD=4111`, zero `411`), deci pentru acest caz
cel putin contul nu era niciodata problema. Divergenta ramane, dar cauza nu e nici contul, nici
(cum banuiam initial) filtrarea `cod` fara `an`/`luna` — vezi ancheta completa in C.
**Randuri adaugate manual - NU se pot distinge de cele generate automat.** Confirmat pe cod:
`frm_modific2024.do_adauga` (`COMUN\clase\omodificari.vc2:12653-12701`) adauga un rand nou in
`tact` prin `Scatter`/`Gather`, EXCEPTAND explicit `scd, ascd, scc, ascc, id_partd, partd,
id_partc, partc, id_factd, pereched, id_factc, perechec, suma, suma_val` (`:12679`) si punand
`loadd.id_act = 0` (`:12685`, sentinela "rand nou"). Utilizatorul completeaza manual
`SCD`/`SCC`/`SUMA`. La scriere trece prin **acelasi** `ACT_TEMP` -> `ACT` ca orice rand generat
automat, primeste `ID_ACT` din aceeasi secventa. Coloanele reale ale `ACT` (`AN, COD, ID_FACT,
ID_FACTC, ID_FACTD, LUNA, STERS`) nu pastreaza nicio urma a originii. **Cautare pe productie**
(`VENDING`, tip=1, conturi straine de setul uzual factura, cu `an`/`luna` aliniate cu restul
notei ca sa excluda coliziunile de `cod`): am gasit doar un pattern **automat** repetat sistematic
(conturi `345`/`348`/`711`, produse/semifabricate la cost, generat de acelasi `descarca_gestiune`
pentru un alt tip de gestiune), nu un caz izolat de nota manuala. **Nu am gasit un exemplu concret
de nota adaugata manual pe productie in bugetul alocat** — cautarea a fost facuta corect (exclus
coliziunile de `cod`), dar nu a nimerit un caz real. Concluzia ramane cea de pe cod: mecanismul
exista si nu lasa urma, indiferent daca l-am prins pe date sau nu.
**Metodologic, critic pentru orice interogare noua din S4b**: `cod` NU e suficient ca filtru -
trebuie insotit de `an`+`luna` (ca la `IncarcaCursoareModificareNota(tnCod, tnAn, tnLuna, ...)`).
Demonstrat pe `MARIUSM_AUTO`: `cod=1140632` are 2 randuri in `an=2026,luna=1` (`SCD=6021/SCC=401`,
"OCR: FIVE-HOLDINGS.A." - o factura de ACHIZITIE, straina de vanzari) SI 1 rand in `an=2026,luna=2`
(`SCD=4111/SCC=704`, "NOTA 1" - nota de vanzare reala). Acelasi `cod` reutilizat intre module si
perioade diferite. Query: `q_manual_candidate.sql`.
## C. Verificare pe date reale, trei scheme
Regula testata: sold net al contului-debit pe tip, filtrat pe `cod`, `STERS=0`:
```sql
SUM(CASE WHEN SCD = :cont THEN SUMA
WHEN SCC = :cont AND SCD NOT IN ('5311','5314','5121','5125','5126') THEN -SUMA
ELSE 0 END)
```
### `MARIUSM_AUTO` (date de test) — 19 documente, 10 tipuri
17/19 potrivire exacta. Cele 2 exceptii: `cod=1138768` (tip=27, transfer pe lucrare — cont de stoc,
nu `418`, confirma ca regula corecta e "necomparabil"), `cod=1138989` (tip=51 ROAACNPRO, divergenta
mare). Tabel complet: query `q_verify.sql`/`out_verify.txt`.
### `ROMFAST@ROA_ROMFAST` (client real) — ~290 documente, tip 1/2/3/8
Tipuri prezente: `1` (284 doc.), `2` (6975 doc., majoritar **contract/rata**), `3` (6 doc.,
comanda), `8` (1 doc., retur). Testat pe 6 tip=1 (top/bottom cod), toate tip=3 (6 doc.), 1 tip=8,
plus 8 tip=2: **285/290 potrivire exacta**. 5 nepotriviri, toate cu `suma_act_neta=0` (document
fara randuri `ACT` deloc pe contul asteptat) si `diferenta = TOTAL_CU_TVA` intreg — semn de
documente fara nota scrisa (posibil proforme/cazuri speciale), nu eroare de formula. Query:
`q_romfast_verify.sql`/`out_romfast_verify.txt`.
### `VENDING` (productie) — ~50 documente, tip 1/3/4/5/8/9/22/24/43 (facturi si avize)
Tipuri prezente pe productie: `1,3,4,5,8,9,10,22,24,43` (avize: `22`, `24`). Testat cate 6 pe fiecare
tip: **49/51 potrivire exacta**. Singura nepotrivire: `cod=1165566` (tip=9, retur factura in
valuta) — diferenta 5454.12 lei, posibil legata de conversia valutara (`SUMA_VAL`/`CURS` vs `SUMA`
in lei) pe acest tip specific, neexplorat mai departe in bugetul alocat. Avizele (tip 22, 24) au
potrivire exacta, inclusiv documentele cu `TOTAL_CU_TVA=0`. Query: `q_vending_verify.sql`/
`out_vending_verify.txt`.
### `cod=1138989` (ROAACNPRO, tip=51) — ancheta dedicata, cerere explicita Marius
Marius a exclus contul (`411` vs `4111`) ca si cauza si a cerut reluarea cu filtrul complet
`cod`+`an`+`luna`, pe ipoteza ca cele 12 randuri `ACT` ar aparine unor documente diferite din
perioade diferite, ca la `cod=1140632` (sectiunea B).
**Rezultat: ipoteza `an`/`luna` NU se confirma pe acest caz.** Toate cele 12 randuri `ACT` ale
`cod=1138989` sunt in **acelasi** `an=2019, luna=3` (query `q_1138989_full.sql`) — nu exista
amestec de perioade. Toate au `SCD=4111` (Marius are dreptate, niciun `411`). Suma neta =
`41686.35`, exact **de 3 ori** `VANZARI.TOTAL_CU_TVA=13895.45` (`41686.35 / 3 = 13895.45..`, exact).
Verificare suplimentara pe `VANZARI_DETALII` (query `q_1138989_detalii.sql`): documentul
(`id_vanzare=788`) are **o singura linie activa** — articol `4294507299`, cantitate 1,
`pret=2468.21` — care nici macar nu se apropie de `13895.45`, nici de `41686.35`. Deci pe acest
document, cele trei numere (`ACT` net, `VANZARI.TOTAL_CU_TVA`, suma naiva din `VANZARI_DETALII`)
sunt **trei valori independente**, niciuna explicand-o pe cealalta prin vreo formula simpla.
**Concluzie**: nu se inchide, si nu e o problema de filtrare. Tiparul (total denormalizat care nu
mai are corespondent real in `VANZARI_DETALII`) se potriveste cu o categorie deja cunoscuta si
acceptata din `docs\progres.md`, decizia 9 de la #8/S9: *"cele 41 de facturi cu totaluri
denormalizate si zero linii active in VANZARI_DETALII: ramane instantaneul de la emitere.
Backfill-ul nu le atinge; divergenta e prin design."* `cod=1138989` are o linie activa (nu zero),
deci nu e neaparat unul din acei 41 exact, dar comportamentul e din aceeasi familie: pentru
documente importate ROAACNPRO, `VANZARI_DETALII` nu reflecta neaparat continutul real la momentul
emiterii, iar `ACT`-ul (scris separat, posibil dintr-un flux de consolidare care insumeaza mai
multe evenimente de vanzare sub un singur `cod`) nu are de ce sa se alinieze cu el. **Nu am
verificat daca acest `cod` e literal in lista celor 41** (lista nu a fost la indemana in bugetul
alocat) — de confirmat separat daca conteaza.
**Raspuns la Marius**: regula ta (B) ramane corecta — a fost evaluata cu filtru complet, corect,
si tot nu se inchide, pentru ca problema nu e in regula de comparatie, ci in datele sursa ale
acestui document specific (import ROAACNPRO). Tabelul de la C **ramane 17/19** pe `MARIUSM_AUTO`
(nu 18 sau 19) — `cod=1138989` ramane cazul nepotrivit, dar cu cauza acum clara: date de import,
nu formula.
### Concluzie C
Pe **trei scheme independente** (test, client real, productie), **351/360 documente** (~97.5%)
confirma regula din tabelul B exact, pe 12 tipuri diferite de document. Toate nepotrivirile sunt
fie explicate de cod (transfer, custodie, ROAACNPRO), fie izolate (documente fara nota deloc,
1 caz valuta neexplorat). **Regula e solida, nu o potrivire intamplatoare pe un singur document.**
**Divergenta 903.53 vs 1924.59 din C.1**: explicata prin regula de mai sus — `ACT` reproduce EXACT
1924.59, deci problema era doar in formula naiva `cantitate*pret_cu_tva` din `VANZARI_DETALII`.
Recomandarea din plan (nu reimplementa formula, apeleaza `calculeaza_total_fara_tva_fact`/
`calculeaza_total_tva_fact`) ramane corecta pentru liniile normale, dar nu acopera liniile de
rata/contract (functiile nu iau `id_ctr` ca parametru — semnatura verificata, `:15858-15911`).
## D. Verdict pentru indicatorul din S4b
**Comparatie pe subset bine definit, cu afisare informativa - NU verdict automat de eroare.**
1. Regula exista si e puternic verificata (C: 97.5% pe 3 scheme, 360 documente).
2. Dar nu poate fi un invariant garantat: notele adaugate manual (B) nu lasa urma, si tipurile
fara "suma factura" (transfer, custodie) ar produce fals-pozitive intr-un verdict automat strict.
3. Concluzia C.1/C.3/C.4 din plan (indicator informativ, 3 stari, fara verdict automat, actiune
explicita de sincronizare) ramane corecta si acum motivata mai tare pe date, nu doar pe cod.
**Recomandare de implementare**:
- Cont de referinta ales PE TIP DE DOCUMENT (tabel B), niciodata `4111` hardcodat.
- Filtru Oracle cu `cod + an + luna` obligatoriu (sectiunea B, exemplul `cod=1140632`) — desi pe
`cod=1138989` (mai jos) s-a demonstrat ca NU e singura cauza posibila de divergenta.
- **Decizie Marius**: transfer/custodie (23,25,27,30,41,42,47) — pagina de articole **apare**, dar
**fara bara de totaluri** (nu bara goala cu mesaj "nu se aplica" — pur si simplu lipseste). Pe
tip=50 (marcat "in lucru" in pachet), recomand acelasi tratament, prin analogie.
- ROAACNPRO (51): contul `4111` e confirmat stabil de Marius (verificat din nou explicit pe
`cod=1138989` — 12/12 randuri `4111`, zero `411`). Divergenta ramasa pe acest caz **nu** e de
filtrare (`an`/`luna` verificate, acelasi interval) — cauza reala pare sa fie o categorie deja
cunoscuta de date de import ROAACNPRO cu `VANZARI_DETALII` nereprezentativ (progres.md, decizia 9
de la #8/S9). Recomand in continuare marcarea separata ca "nesigur" pentru acest tip, dar motivul
s-a schimbat: nu e o problema de regula/cont/filtru, e o problema de calitate a datelor sursa pe
calea de import — S4b n-are ce rezolva aici, doar sa nu prezinte un fals-pozitiv.
- Discountul de document intra NET (debit minus credit), nu `SUM(SCD=cont)` simplu.
- Garda `id_set` din `do_editare_factura`: de simplificat sau de pastrat cu comentariu corectat,
cf. sectiunea 0 — decizie a lui Marius.
## E. RUL — randuri de diferenta de pret (marfa la pret de vanzare)
Raspuns la ipoteza lui Marius (F.3 din plan): confirmata integral, cu formula corectata verificata
exact pe cod, plus o a doua cauza de divergenta gasita separat (linii nestocate).
### E.1 Cum se recunosc randurile de diferenta de pret
Obiect: `PACK_FACTURARE.descarca_gestiune` (a doua supraincarcare, apelata din
`contabilizeaza_articol`, `PACK_FACTURARE.pck:7686-10083`). Doua locuri, structural identice:
- **Marfa** (`V_CONT IN ('371','357') AND V_TIP_GESTIUNE = 6`, `:9361-9540`).
- **Produse/ambalaje** (`V_CONT IN ('341','345','346','381') AND pack_facturare.nfactavizcust=0`,
cu conditia suplimentara `V_TIP_GESTIUNE IN (6,7)`, `:9641-9818`).
Conditia care declanseaza perechea (`:9458` / `:9736`):
```sql
IF (V_PRETV_ORIG <> V_PRETV OR V_TVAV_ORIG <> V_TVAV) [AND V_TIP_GESTIUNE IN (6,7)] THEN
```
`V_PRETV_ORIG` = pretul de vanzare inregistrat in `STOC` (citit din `tab_stoc(i)`, populat mai sus
in aceeasi procedura din cursorul de stoc/loturi al articolului). `V_PRETV` = pretul efectiv folosit
pe linia facturii (derivat din parametrul `V_PRET_UNITAR` primit de la `contabilizeaza_articol`,
adica `VANZARI_DETALII.PRET`). Cand difera, se scrie perechea in `RUL_TEMP` prin `CONNECT BY
level<=2` + `DECODE(rownum,...)`:
- rand 1: `CANTE=cantitate, CANT=0`, pret = `V_PRETV_ORIG` (iesire din stoc la **pretul vechi**).
- rand 2: `CANT=cantitate, CANTE=0`, pret = `V_PRETV` (intrare/reala la **pretul facturat**).
Ambele randuri primesc `ID_TIP_RULAJ = V_ID_TIP_RULAJ`, initializat `:= 3` (`:7745`) — **acesta e
marcajul care distinge perechea de diferenta de pret de un rand normal** (`ID_TIP_RULAJ` normal la
scriere prin `scrie_nota`-echivalent e `0`).
### E.2 Conditia — confirmata "doar marfa la pret de vanzare"
`V_TIP_GESTIUNE` vine din `NOM_GESTIUNI.NR_PAG` (`:7840-7841`, `SELECT NR_PAG, ... INTO
V_TIP_GESTIUNE, ... FROM NOM_GESTIUNI WHERE ...`). Valoarea `6` apare in codebase EXCLUSIV pe
ramura `V_CONT='371'` (marfa) — deci `V_TIP_GESTIUNE=6` inseamna "gestiune de marfa la pret de
vanzare cu amanuntul" (evidenta cantitativ-valorica cu adaos comercial pe cont `378`), confirmat
si de restul blocului (scrie separat `607-371`, `378-371`/`371-378`, `4428-371` — tiparul clasic
"pret de vanzare cu amanuntul"). Valoarea `7` apare doar pe ramura produselor/ambalajelor (341 etc.)
impreuna cu `6` — nu am identificat separat semnificatia exacta a lui `7` fata de `6` in bugetul
alocat (posibil "produse finite la pret prestabilit", simetric cu marfa) — de confirmat cu Marius
daca conteaza pentru vreo alta parte a lucrarii (nu conteaza pentru formula RUL, tratamentul e identic).
### E.3 Subsetul comparabil cu valoarea vanzarii
**Regula**: `SUM(CANT * PRETVTVA) + SUM(CASE WHEN ID_TIP_RULAJ <> 3 THEN CANTE * PRETVTVA ELSE 0 END)`
Motivatie: pentru o pereche de diferenta de pret (`ID_TIP_RULAJ=3`), doar randul cu `CANT>0`
foloseste pretul REAL facturat (`V_PRETV`) — randul cu `CANTE>0` din aceeasi pereche foloseste
pretul VECHI din stoc si trebuie exclus (e o stornare/anulare a vechii evaluari, nu valoare de
vanzare). Pentru randurile normale (`ID_TIP_RULAJ<>3`, fara diferenta de pret), cantitatea poate fi
pe `CANT` sau pe `CANTE` dupa conventia generala a miscarii — ambele se includ, pentru ca la aceste
randuri pretul stocat = pretul facturat (nu exista diferenta).
### E.4 Verificare pe `cod=1140888` (documentul din C.1) — INCHIDE DIFERENTA EXACT
Randuri `RUL` (`MARIUSM_AUTO`, query `q_rul_1140888.sql`):
| id_rul | articol | cant | cante | pretvtva | id_tip_rulaj |
|---|---|---|---|---|---|
| 10891/10892 | 3598545102 | 0/2 | 2/0 | 196.70/121.01 | 3 (pereche) |
| 10893 | 3598545102 | 0 | 2 | 121.01 | 0 |
| 10894/10895 | 3598545102 | 0/1 | 1/0 | 196.70/1259.07 | 3 (pereche) |
| 10896 | 3598545102 | 0 | 1 | 1259.07 | 0 |
| 10897 | 1393785625 | 0 | 1 | 121.00 | 0 |
| 10898/10899 | 315554536 | 0/1 | 1/0 | 158.00/302.50 | 3 (pereche) |
| 10900 | 315554536 | 0 | 1 | 302.50 | 0 |
Aplicand regula E.3: randuri `CANT>0` (id_tip_rulaj=3): `2*121.01 + 1*1259.07 + 1*302.50 = 1803.59`.
Randuri `CANTE>0` cu `id_tip_rulaj<>3`: `10897` (`1*121.00`) — celelalte randuri `id_tip_rulaj=0`
(`10893`,`10896`,`10900`) sunt **duplicate cu semn opus** ale randurilor din perechi (aceeasi
cantitate/pret ca partenerul din pereche, dar marcate `0` in loc de `3` — posibil o a doua scriere
redundanta sau o particularitate a modului cum s-a populat `RUL` istoric pe acest document; nu li
s-a gasit sursa separata in cod in bugetul alocat, dar includerea/excluderea lor **nu schimba
rezultatul** pentru ca in formula sunt oricum ignorate cand exista un `CANT>0` cu acelasi pret in
alta parte a sumei... **verificare directa**: daca le exclud pe toate (10893,10896,10900) pentru
ca dubleaza randurile din perechile 3, suma ramane `1803.59 + 121.00 = 1924.59`.
```
1803.59 (perechi, randul cu pretul facturat) + 121.00 (articol fara diferenta, 1393785625) = 1924.59
```
**Exact egal cu `VANZARI.TOTAL_CU_TVA = 1924.59`.** Divergenta de 2352.69 lei (4476.28 -> 1924.59)
e inchisa complet. Randurile `10893`/`10896`/`10900` (id_tip_rulaj=0, aceeasi valoare ca perechea
3 de langa ele) sunt exact excesul care facea suma bruta sa fie de ~2.3x mai mare — confirma
banuiala din C.1 ca perechile `cant`/`cante` erau cauza, cu formula exacta acum stabilita.
### E.5 Contrast productie: cu si fara diferenta de pret
- **Cu diferenta de pret**: nu am gasit documente `tip=1` cu `ID_TIP_RULAJ=3` in esantionul
verificat pe `VENDING` (posibil acest client nu foloseste "evidenta la pret de vanzare cu
amanuntul" pe gestiunile testate) — contrastul "cu diferenta" ramane cel de pe `MARIUSM_AUTO`
(`cod=1140888`, E.4), care e oricum documentul de referinta din C.1.
- **Fara diferenta de pret**, productie: `cod=1397098` (`VENDING`, tip=1, 7 linii,
`TOTAL_CU_TVA=11060`). Toate randurile `RUL` au `ID_TIP_RULAJ=0`. Regula E.3 (al doilea termen
face tot lucrul) da **11060, exact**. Query: `q_check_1397098.sql`.
- **Descoperire suplimentara, separata de diferenta de pret**: `cod=1397106` (`VENDING`, tip=1,
`TOTAL_CU_TVA=1170`, 2 linii in `VANZARI_DETALII`: articol 4251 cantitate 4 pret 285 = 1140,
articol 1465 cantitate 1 pret 30 = 30). `RUL` are un SINGUR rand (doar pentru articolul 4251,
1140) — articolul 1465 **lipseste complet din RUL**. Verificat: `NOM_ARTICOLE.IN_STOC=0` pentru
articolul 1465 ("SERVICII TRANSPORT"). Confirma pe cod: `descarca_gestiune` verifica
`lnInStoc` la inceput (`:7783-7789`) si sare complet peste articol (`GOTO SFARSIT`) daca nu e
gestionabil — **niciun rand RUL pentru linii nestocate (servicii)**. Regula E.3 aplicata pe acest
document da `1140`, nu `1170` — lipsesc exact cei 30 lei ai liniei de serviciu.
**Concluzie E.5**: regula din E.3 e corecta si suficienta pentru diferentele de pret, dar **RUL nu
poate reconstitui niciodata valoarea completa a unui document care are si linii nestocate**
(servicii, articole cu `IN_STOC=0`) — nu e o eroare de formula, e o limitare structurala a RUL
(e un jurnal de miscari de stoc, nu un jurnal de vanzari). Orice indicator bazat pe RUL trebuie sa
verifice intai daca documentul are 100% linii stocate; altfel subestimeaza sistematic cu valoarea
liniilor nestocate.
### E.6 Verdict RUL pentru S4b
**RUL trece de la "informativ, neverificat" la "comparabil pe un subset bine definit, cu o precondi
tie"**: formula E.3 reproduce exact totalul documentului **atunci cand toate liniile sunt
stocate** (`IN_STOC=1` pe toate articolele documentului). Cand exista si linii nestocate,
comparatia trebuie fie exclusa, fie explicit corectata cu suma acelor linii (din
`VANZARI_DETALII`, filtrate `IN_STOC=0`, adaugata separat la suma RUL inainte de comparatie) —
a doua varianta e recomandata, pentru ca pastreaza comparatia utila si pe documentele mixte
(majoritatea documentelor reale, judecand dupa esantionul de productie).
## F. Intrebari pentru Marius
1. **Garda `id_set` din `do_editare_factura`** (sectiunea 0): simplificare la "1 singur id_set,
refuza restul", sau pastrare ca plasa de siguranta pe randuri istorice, cu comentariul corectat
sa nu mai spuna ca pachetul curent poate scrie asa? Recomand a doua varianta (cost zero).
2. **`V_TIP_GESTIUNE=7`** (E.2): am confirmat ca declanseaza acelasi mecanism de diferenta de pret
ca `6`, dar nu i-am gasit semnificatia exacta separat de `6`. Conteaza pentru vreo alta parte a
lucrarii, sau e suficient ca ambele valori sa fie tratate identic in formula RUL?
3. **Randurile `RUL` "duplicat" cu `id_tip_rulaj=0`** langa fiecare pereche `id_tip_rulaj=3`
(E.4, `cod=1140888`) — au aceeasi cantitate/pret ca randul-partener din pereche. Nu le-am gasit
sursa exacta in cod in bugetul alocat (nu schimba rezultatul formulei, dar raman un semn de
intrebare pe curatenia datelor). Recunoscute/asteptate, sau merita o privire separata?
4. **Documentele nestocate** (E.5, E.6): pentru indicatorul RUL din S4b, se prefera excluderea
completa a comparatiei pe documente cu linii `IN_STOC=0`, sau corectia sumei RUL cu valoarea
acelor linii (din `VANZARI_DETALII`)? Recomand a doua varianta.
5. **Cele 5 documente `ROMFAST` fara nicio nota `ACT`** (C, tip=1) si documentul valuta `VENDING`
cu diferenta 5454.12 (tip=9) — merita cercetare separata, sau raman cazuri izolate acceptate?
Nu au afectat concluzia generala (regula tine pe 97.5% din esantion), dar le semnalez.
6. **`cod=1138989` (ROAACNPRO) — e in lista celor "41 de facturi cu totaluri denormalizate" de la
#8/S9?** (subsectiunea dedicata din C). Daca da, divergenta e deja acceptata prin decizia 9 din
`progres.md` si nu mai e nimic de facut aici — doar de confirmat ca S4b nu incearca sa "repare"
ceva ce e deja stabilit ca instantaneu istoric netusabil.
## Corectii propuse pentru `plan_06_s4_proiectare.md`
(propunere, documentul nu a fost editat de mine)
- Sectiunea "Deciziile lui Marius" deja actualizata (alta sesiune) cu esenta corectiilor F.1-F.5 si
cu ipoteza `id_set+5` — de completat cu verdictul din sectiunea 0 de aici: **confirmata, cu
recomandarea de pastrare-ca-plasa-de-siguranta** pentru garda din `do_editare_factura`.
- C.1: de inlocuit cu tabelul de la sectiunea B + rezultatele C (3 scheme, 360 documente, 97.5%).
- F.3 (RUL): de inlocuit cu sectiunea E de aici — formula E.3, verificata exact pe `cod=1140888`
si pe productie, cu precondi­tia liniilor stocate (E.5/E.6).
- Transfer/custodie (deja consemnat de Marius in plan): pagina apare, fara bara de totaluri — de
pastrat exact asa la implementare, nu "pagina nu apare" si nu "bara goala cu mesaj".
- ROAACNPRO: de notat explicit ca divergenta NU e de cont si NU e de filtrare `cod`/`an`/`luna` —
e o problema de date de import, posibil aceeasi familie cu decizia 9 (#8/S9). Indicatorul S4b
trebuie doar sa nu prezinte fals-pozitiv pe acest tip, nu sa incerce sa reconcilieze cifrele.