Files
roafacturare/docs/cercetare/rec_fact008_pret_achizitie_zecimale.md
Marius Mutu ca3c5d7eea docs: runda 6 - cercetari, propuneri si conventia mediului Oracle
Cercetarile si propunerile rundelor 4-6 pe editarea facturii emise. Starea
rundei 6 si ce s-a stabilit intra in progres.md.

Nou: docs/conventii_mediu_oracle.md - pe dev/test se lucreaza numai cu
ROA_CENTRAL si schemele CONTAFIN_ORACLE si MARIUSM_AUTO; schema ACN nu se
foloseste. Scripturile de pachet sunt necalificate, deci schema tinta o
decide sirul de conectare, nu fisierul.

roafacturare.pj2 regenerat de git_sync.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013gYCNE26G1G7UoGu2ju7aS
2026-08-20 16:35:03 +03:00

7.9 KiB

FACT-008 la vending: pretul de achizitie se trimite cu 3 zecimale, stocul il tine cu 4

Investigatie pe productia VENDING (tunel SSH, strict citiri). Articol reclamat: ZAHAR STICK BRUN 4G 200BUC/SET, id_articol = 5155.

Simptom

La salvarea facturii: Articolul ZAHAR STICK BRUN 4G 200BUC/SET nu mai e in stoc! (FACT-008), desi articolul are 500 buc pe stoc si e in lista de preturi.

Cauza

pack_facturare.descarca_gestiune cauta randul din STOC prin egalitate exacta pe pretul de achizitie (productie, PACK_FACTURARE body linia 7186, ramura ELSE):

AND A.PRET = V_PRET_ACHIZITIE

Daca BULK COLLECT nu aduce niciun rand, se ridica FACT-008 (linia 7247).

Datele din productie:

sursa valoare
STOC.PRET (id_articol 5155, gest. 1001, cont 371, luna 8 / 2026) 8.5586
RUL receptia din 06.08.2026 (id_rul 568464) cant 500, valoare 4279.28 -> 4279.28/500 = 8.55856 -> 8.5586
OPTIUNI.PPRET (precizia pretului de achizitie) 3

Clientul VFP tine pretul corect (cursorul e definit pret_achizitie N(20, max(gnPPret,4)), deci 4 zecimale), dar il serializeaza in SQL cu gnPPret zecimale:

  • COMUN\clase\ofacturare.vc2:14073 — frm_facturare_articole.do_scrie_articole
  • COMUN\clase\ofacturare.vc2:18108 — frm_facturare_articole2.do_scrie_articole
  • COMUN\programe\ofacturare_stoc.prg:360 — adauga_articol_factura_stoc
Alltrim(Str(poArt.pret_achizitie,18,gnPPret))

Str(8.5586, 18, 3) = 8.559. In VANZARI_DETALII_TEMP.PRET_ACHIZITIE (NUMBER(22,6)) ajunge 8.559, iar predicatul A.PRET = V_PRET_ACHIZITIE compara 8.5586 cu 8.559 -> 0 randuri -> FACT-008.

Verificat pe productie:

pret = 8.559  -> 0 randuri
pret = 8.5586 -> 1 rand

Ramura tip = 3 (articole fara stoc) nu salveaza situatia: OPTIUNI.RF_FACTURARE_FARA_STOC = 0.

Intinderea problemei

Nu e un caz izolat. In STOC exista 15 randuri cu pret pe mai mult de 3 zecimale, toate in luna 8 / 2026, si toate vor da FACT-008 la facturare:

1070 CAFEA COVIM OROCREMA 1KG            42.3203   360 buc
1367 PULBERE ALBA -ADAOS BAUTURI CALDE   25.3857   120 buc
1433 ZAHAR STICK 5G 200BUC/SET            7.2072  1000 buc
1537 CONTOR VOLUMETRIC NECTA             19.8347    30 buc
1677 GARNITURA BUCSA MIXER NECTA NEW       .4958    60 buc
1965 MOTOREDUCTOR GRUP CAFEA NECTA      152.0667     3 buc
2020 LAVAZZA BBE EXPERT GUSTO FORTE      55.8815  1188 buc (cants)
2057 LAVAZZA BBE EXPERT GUSTO PIENO      61.5397   396 buc
2261 FURTUN SILICONIC 6X9                 6.6116    50 buc
2934 BUCSA TEFLON MIXER NECTA             4.7107    60 buc
3680 ZAHAR MARGARITAR 1 KG                3.3243   100 buc
4282 GARNITURA NECTA OR2037 WITT 9100     1.6528    60 buc
5133 ZAHAR STICK MXA 5G 100BUC/SET        3.6036  1000 buc
5155 ZAHAR STICK BRUN 4G 200BUC/SET       8.5586   500 buc

In RUL, preturile cu peste 3 zecimale apar doar din 09.07.2026 incoace (20 randuri, ultimul 14.08.2026). Inainte de aceasta data nu exista niciunul — deci comportamentul a aparut recent, pe calea de receptie (pret unitar = valoare / cantitate, rotunjit la scale-ul coloanei STOC.PRET, care e 4).

Solutii

Rapid, fara cod (productie): OPTIUNI.PPRET de la 3 la 4. Str() incepe sa emita 4 zecimale si predicatul se potriveste. Aliniaza precizia de transport cu scale-ul real al STOC.PRET.

Durabil, in cod: in cele 3 puncte de mai sus, serializarea sa foloseasca aceeasi precizie ca definitia cursorului:

Alltrim(Str(poArt.pret_achizitie,18,Max(gnPPret,4)))

Nu se recomanda relaxarea predicatului in descarca_gestiune (round(A.PRET, ...)): pe gestiuni cu mai multe loturi ale aceluiasi articol ar putea potrivi randul gresit.

Risc similar, neatins inca

pretv_orig se trimite cu gnPPretV (= 2 la vending), iar STOC.PRETV are scale 4, cu acelasi predicat de egalitate exacta (A.PRETV = V_PRETV_ALES). La vending toate randurile din stoc au pretv = 0, deci nu se manifesta; pe o gestiune tinuta la pret de vanzare cu pret pe 3-4 zecimale ar da acelasi FACT-008.

De unde vin zecimalele: importul eFactura din ROACONT (confirmat)

Ipoteza s-a confirmat pe date. Receptia care a creat stocul articolului 5155 vine din eFactura:

ANAF_EFACTURA_DETALII / ANAF_EFACTURA
  furnizor NAVIS PROD CONCEPT SRL, NVS 1427, 06.08.2026
  id_articol 5155, cantitate 500, PRET = 8.5586, VALOAREFARATVA = 4279.28

Sunt doua surse de zecimale, ambele ocolind gnPPret:

1. Pretul din XML-ul furnizorului are el insusi 4 zecimale. Cazul 5155 (8.5586) si 1433 (7.2072, NVS 1406). Se preia ca atare in ANAF_EFACTURA_DETALII.PRET si de acolo in NIR.

2. Importul recalculeaza pretul unitar dupa distribuirea discounturilor, cu numarul de zecimale scris in cod (4, respectiv 6), nu cu gnPPret — frm_import_efactura.importmodifica, D:\ROA\ROACONT\COMUN\clase\anaf_efactura.vc2:

linie cod efect
12727 Set pret = ROUND(ROUND(pret / lnTotalFaraTVAx, 6) * lnTotalCuTVAx, 6) 6 zecimale
12744 lnPret = pret - ROUND(lnDiscount / cantitate, 4) 4 zecimale — discount pe linie
12786 Set Pret = Round(Pret * lnProcent, 4) 4 zecimale — discount/transport global

Verificare pe date, cazuri unde XML-ul avea 2 zecimale si stocul a ajuns cu 4 (deci recalculul de la 12744 e cel care a produs zecimalele):

articol XML: cant / pret / valoare valoare/cant STOC.PRET
1677 GARNITURA BUCSA MIXER 60 / 0.50 / 29.75 0.4958333 0.4958
1965 MOTOREDUCTOR GRUP CAFEA 3 / 152.07 / 456.20 152.066666 152.0667
1537 CONTOR VOLUMETRIC 30 / 19.83 / 595.04 19.834666 19.8347
2934 BUCSA TEFLON MIXER 30 / 4.71 / 141.32 4.7106666 4.7107

Mai departe, frm_import_efactura.importmodifica (anaf_efactura.vc2:12810) duce d.Pret in cursorul NIR-ului fara nicio rotunjire, desi toate valorile vecine din acelasi SELECT trec prin Round(..., gnPC).

De ce rotunjirea la import nu e solutia buna

Daca la import s-ar rotunji pretul la gnPPret = 3, pentru 5155 ar rezulta 8.559 x 500 = 4279.50, fata de valoarea reala a facturii, 4279.28 — o diferenta de 0.22 lei intre valoarea receptionata si cea care se descarca ulterior din stoc. Exact de aceea STOC.PRET are scale 4 si cursoarele din facturare sunt declarate N(20, max(gnPPret,4)).

Concluzia ramane: reparatia corecta e la transportul din facturare (Str(..., 18, gnPPret) -> Max(gnPPret,4)), sau, ca masura imediata, OPTIUNI.PPRET = 4. Importul eFactura e sursa zecimalelor, dar zecimalele in sine sunt legitime.

Al patrulea punct de emisie, in afara COMUN (ROAGEST)

D:\ROA\ROAGEST\Programe\ofactureaza.prg, liniile 267, 268, 280, construieste acelasi apel pack_facturare.adauga_articol_factura(...) cu aceeasi trunchiere (gnPPret, gnPPretVal, gnPPretV). E cod propriu ROAGEST, nu in COMUN, deci reparatia din COMUN nu-l acopera. Acelasi tipar, aceeasi solutie.

In plus, copiile COMUN din ROAGEST / ROACONT / ROAACNPRO sunt in urma celei din ROAFACTURARE (ofacturare.vc2 are acolo liniile la 13857 / 17889) — primesc reparatia la urmatorul svn update plus recompilare.

Ce mai atinge PPRET, in afara transportului

Nu e doar precizie de transport. Aceeasi optiune conduce:

  • rotunjirea pretului unitar la NIR-ul introdus manual: COMUN\clase\ointroduceri.vc2, liniile 1459, 1495, 15533, 19159 — Round(valoare / cantitate, gnPPret). Deci calea manuala de receptie respecta deja gnPPret; doar importul eFactura o ocoleste. Cu PPRET = 4, si NIR-urile introduse manual vor stoca preturi cu 4 zecimale, nu 3.
  • mastile de editare/afisare ale pretului de achizitie: ofacturare.vc2:3490, ofacturare_comun.vc2:1643, ointroduceri.vc2:10071, 16390, 19638 (get_mask(..., gnPPret)).

De aici si concluzia despre scriptul global: dupa ce intra versiunile cu Max(gnPPret,4), ridicarea lui PPRET la 4 nu mai repara nimic, dar schimba rotunjirea receptiilor manuale si afisarea la toti clientii.