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

177 lines
7.9 KiB
Markdown

# 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`):
```sql
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`
```foxpro
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:
```foxpro
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.