# 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.