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

32 KiB
Raw Blame History

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:

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:

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):

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.