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

204 lines
11 KiB
Markdown

# S5 — parametrul de discount si documentele in valuta. Rezultat
Inchide cele doua goluri declarate de `docs\cercetare\rec_s5_scriere_reala.md`, sectiunea
„Ce NU acopera testul". Suita: `COMUN\utile\Teste\editare_factura\test_s5_discount_valuta.prg`.
Log: `COMUN\utile\Teste\editare_factura\test_s5_discount_valuta_log.txt` (rulare 10.08.2026,
00:05:16-00:05:21). Diff: `docs\diff_s5_discount_valuta.patch`.
## Rezultat
**46 PASS / 0 FAIL**, numarate din log. Zero linii `EROARE`, ultima linie e `done`, deci rularea a
ajuns la capat. Starea finala e verificata **independent prin `sqlplus`**, nu din logul testului.
## VERDICTUL pe `NULL`: PASTREAZA. Nu zeroeaza.
Dovedit pe date, in doua contexte diferite, prin patru apeluri succesive in aceeasi tranzactie, cu
citirea starii necomise intre ele (log, blocul A):
| Apel | `VANZARI.DISCOUNT` | `DISCOUNT_TVA` | `TOTAL_FARA_TVA` | `TOTAL_TVA` | `TOTAL_CU_TVA` |
|---|---|---|---|---|---|
| stare initiala | 0 | 0 | 747.96 | 157.06 | 905.02 |
| `recalculeaza_totaluri_vanzari(1049, NULL)` | 0 | 0 | 747.96 | 157.06 | 905.02 |
| `recalculeaza_totaluri_vanzari(1049, 12.5)` | **12.50** | 2.63 | 735.46 | 154.43 | 889.89 |
| **`recalculeaza_totaluri_vanzari(1049, NULL)`** | **12.50** | 2.63 | 735.46 | 154.43 | 889.89 |
| `recalculeaza_totaluri_vanzari(1049, 0)` | 0 | 0 | 747.96 | 157.06 | 905.02 |
Randul al patrulea e verdictul: `NULL` peste un discount de 12.50 il lasa 12.50, si lasa **toate**
totalurile neschimbate pana la a patra zecimala (asertia `A3` compara exact, cu toleranta 0.0001,
nu aproximativ). Randul al cincilea arata contrastul: `0` **explicit** chiar zeroeaza — deci cele
doua valori nu se confunda in implementare.
Acelasi verdict, repetat pe calea de valuta (blocul B, `id_vanzare = 1037`): discount 10 -> `NULL`
-> discount ramane 10, `ftva/tva/valval/tvaval` neschimbate.
### Codul si datele concorda
`ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql:16043-16046`:
```sql
SELECT NVL(V_DISCOUNT, discount), in_valuta, NVL(discount_evidentiat, 0)
INTO lnDiscountFactura, lnInValuta, lnDiscountEvidentiat
FROM vanzari
WHERE id_vanzare = V_ID_VANZARE;
```
`NVL(V_DISCOUNT, discount)` — parametrul nul cade pe valoarea din tabela, iar `UPDATE`-ul final
(`:16215`) scrie inapoi `discount = lnDiscountFactura`. Citirea corpului si comportamentul pe date
spun acelasi lucru. Nu am gasit nicio divergenta si niciun defect in procedura.
## Cum se comporta o valoare nenula
**Document in RON** (`in_valuta = 0`): discountul se scade ca atare din baza fara TVA, iar TVA-ul
lui se scade din TVA. Cu `PPRETV = 2` si cota maxima `1.21` pe liniile active:
```
total_fara_tva = 747.96 - 12.50 = 735.46
discount_tva = ROUND(12.50 * 0.21, 2) = 2.63
total_tva = 157.06 - 2.63 = 154.43
total_cu_tva = 735.46 + 154.43 = 889.89
```
`VALOARE_ACHIZITIE` ramane `263.31` — nu depinde de discount, verificat explicit (`A2`).
**Document in valuta** (`in_valuta = 1`): discountul e exprimat **in valuta**. In RON se scade
convertit prin cursul documentului, in valuta se scade brut — ramura
`decode(in_valuta, 1, ROUND(curs * discount / multiplicator, PPRETV), discount)`
(`:16073-16092`). Pe `id_vanzare = 1037` (`id_valuta = 2`, `curs = 5.2688`, `multiplicator = 1`),
cu discount `10`:
```
discount in RON = ROUND(5.2688 * 10 / 1, 2) = 52.69
total_fara_tva = 1053.76 - 52.69 = 1001.07
total_tva = 221.29 - ROUND(52.69 * 0.21, 2) = 221.29 - 11.06 = 210.23
valval = 200 - 10 = 190.00
discount_tva = ROUND(10 * 0.21, 2) = 2.10 (TVA-ul discountului, in VALUTA)
tvaval = 42 - 2.10 = 39.90
totval = 190 + 39.90 = 229.90
```
Toate cele sapte valori au fost calculate in test din starea de plecare si comparate cu ce a scris
procedura. `ID_VALUTA`, `CURS` si `MULTIPLICATOR` raman `2 / 5.2688 / 1` dupa recalcul.
De consemnat, pentru cine citeste coloanele: **`DISCOUNT_TVA` retine `DISC_TVA_VAL`, adica TVA-ul
discountului in valuta (2.10), nu in RON (11.06)** — pe documentele in RON cele doua coincid, pe
cele in valuta nu. Nu e defect, `scrie_in_vanzari` face la fel; e doar neevident din nume.
## Documentele in valuta EXISTA. Premisa contrara era gresita.
Nota anterioara („nu exista in schema un document descoperibil simultan cu articole si in valuta
reala") **nu se confirma**. In `MARIUSM_AUTO`:
- **28** de randuri `VANZARI` cu `IN_VALUTA = 1`;
- **25** dintre ele au cel putin o linie activa in `VANZARI_DETALII`;
- **8** au si `ID_VALUTA` / `CURS` / `MULTIPLICATOR` completate **si** rand in `VANZARI_CURSURI`:
`id_vanzare` 329, 627, 678, 859, 864, 947, 952, **1037**.
Celelalte 17 sunt degenerate (`ID_VALUTA` si `CURS` nule pe cap), deci nu sunt cazuri de test bune.
Ales: **`id_vanzare = 1037`**, `cod = 1140730`, din **07.05.2026**, o linie activa (`det = 1565`,
cantitate 1, pret 200 in valuta, `pret_cu_tva = 0`, `proc_tvav = 1.21`, `pret_achizitie = 100`),
totaluri persistate `1053.76 / 221.29 / 1275.05` in RON si `200 / 42 / 242` in valuta.
**Recalculul reproduce exact starea persistata a acestui document**, si in RON si in valuta
(asertiile `B1`). Asta e proba directa ca agregarea din procedura — inclusiv conversia prin
`VANZARI_CURSURI` — e corecta pe un document in valuta emis pe cale normala, nu doar pe unul
simulat in VFP. Golul lasat de `test_adauga_linie_valuta.prg` (care suprascria `tvanz` manual) e
inchis pe partea de Oracle.
### Ce NU se poate acoperi pe documentele in valuta
Niciunul dintre cele 8 nu e **din luna curenta** (cel mai recent e din 05.2026, restul din
2009-2022), iar garda din `do_editare_factura` cere `data_act` in luna de lucru. Deci **lantul
complet de editare nu poate fi rulat pe un document in valuta** — pe date exista doar recalculul
Oracle, care e insa exact partea despre care nu se stia nimic. Documentul fiind arhiva, blocul B
se inchide cu **ROLLBACK**: `1037` e verificat prin `sqlplus` dupa test si e **neatins**.
## Lantul real de salvare cu discount nenul (blocul C)
Singurul bloc care comite. Documentul `1049` a primit discount `12.5` prin chiar procedura testata
(commit), apoi a trecut prin lantul complet de editare **fara nicio modificare de linii**:
```
recalculeaza_totaluri_vanzari(1049, 12.5) -- COMMIT, pregatire
IncarcaVanzareDinNota -> tvanz.discount = 12.5000 <- proba C2
MyDeschideTranzactie()
OSCRIE_IN_FISIERE(2, .T., .T.) => 1
OSCRIE_IN_FISIERE(0, .T., .T.) => 1
pack_contafin.finalizeaza_modificare_nota => 1
[in tranzactie] cod 1140897 -> 1140898, discount INCA 12.50 <- proba C3
ScrieArticoleFacturaEditate(1049) => 1
MyInchideTranzactie(1) -- COMMIT
[dupa commit] discount 12.50, ftva 735.46, tva 154.43, ctva 889.89 <- proba C5
recalculeaza_totaluri_vanzari(1049, 0) -- COMMIT, restaurare
```
Trei lucruri pe care doar acest bloc le stabileste:
1. **`tvanz.discount` chiar aduce discountul din `VANZARI`.** `IncarcaVanzareNota`
(`ofacturare_editare.prg:177`) selecteaza `v.discount` direct din `VANZARI`, iar helperul
citeste de acolo (`:485-486`). Daca cursorul l-ar fi adus 0, salvarea ar fi **sters** discountul
documentului — exact riscul din briefing. Nu se intampla.
2. **`finalizeaza_modificare_nota` nu atinge `DISCOUNT`.** Citit in tranzactie, dupa realinierea
`COD`-ului: `1140897 -> 1140898`, discount inca `12.50`. Concorda cu corpul lui
`actualizeaza_vanzari` (`:16012-16022`), care scrie doar `VANZARI_DETALII.STERS`, `VANZARI.COD`
si `VANZARI.STERS`.
3. **Discountul supravietuieste unei salvari complete**, cu totalurile recalculate coerent
(`735.46 + 154.43 = 889.89`).
`NULL` nu ajunge azi in procedura pe calea VFP decat daca `VANZARI.DISCOUNT` e **NULL** in baza —
helperul trimite `NULL` doar la `Isnull(discount)` (`:546`), altfel trimite valoarea. Pe `1049`
discountul e `0`, nu NULL, deci calea reala trimite mereu o valoare. Ramura `NULL` a helperului nu
e atinsa de acest test; contractul procedurii pe `NULL` este insa dovedit direct (blocurile A si B).
## Verificarea independenta prin `sqlplus` (dupa test, cu procesul VFP terminat)
`MARIUSM_AUTO/…@ROA_CENTRAL`:
```
1049: cod=1140898 sters=0 in_valuta=0 discount=0 discount_tva=0 val_ach=263.31
ftva=747.96 tva=157.06 ctva=905.02 valval=747.96 tvaval=157.06 totval=905.02
linii 1049: det=1581 sters=0 cant=2 pret=302.51 pret_ach=10
det=1582 sters=1 cant=1 pret=121.30 pret_ach=0
det=1583 sters=0 cant=1 pret=150.00 pret_ach=10
det=1588 sters=0 cant=3 pret=50.00 pret_ach=77.77
1037: cod=1140730 sters=0 in_valuta=1 discount=0 discount_tva=0 val_ach=100
ftva=1053.76 tva=221.29 ctva=1275.05 valval=200 tvaval=42 totval=242
id_valuta=2 curs=5.2688 multiplicator=1 -- NEATINS
1050: cod=1140895 discount=0 total_cu_tva=1924.59 -- NEATINS
vact_tot 08.2026: cod=1140897 randuri=10 sterse=10 | cod=1140898 randuri=10 sterse=0
v$transaction pe MARIUSM_AUTO: 0 randuri
```
`1049` e **exact** in starea de dinaintea acestui test pe toate coloanele de valoare — singura
schimbare e `COD`. Structura liniilor e neschimbata (aceleasi 3 active, `1582` ramane stearsa din
testul precedent).
## Date de test consumate
- **Un singur `cod` realocat: `1140897` -> `1140898`** pe `id_vanzare = 1049`. Cine reia testul
citeste `cod`-ul curent din `VANZARI`, nu-l presupune.
- **Nimic altceva.** Zero linii adaugate sau sterse, zero valori de totaluri lasate schimbate,
`DISCOUNT` restaurat la `0`. Blocurile A si B nu consuma nimic (ROLLBACK).
- `id_vanzare = 1050` si `id_vanzare = 1037` sunt **neatinse**, verificat prin `sqlplus`.
## Ce NU acopera nici acest test
- **Liniile din seturi** (`id_vanzare_set` nenul) — niciunul dintre documentele folosite nu are
asa ceva, deci ramura `union all` din agregare (`:16178-16209`), care ia totalurile din capul de
set, ramane neatinsa. Neschimbat fata de raportul precedent.
- **Lantul complet de editare pe un document in valuta** — imposibil azi: niciun document in valuta
nu e din luna curenta (vezi mai sus). Doar recalculul Oracle e acoperit.
- **Ramura `NULL` a helperului** (`ofacturare_editare.prg:546`) — cere `VANZARI.DISCOUNT` NULL in
baza, ceea ce nu s-a fabricat.
- **`discount_evidentiat = 1`** — toate documentele folosite au `0`; ramura care distribuie
discountul pe linii nu e atinsa.
- Cele cinci validari din `inainte_de_do_termin`, `frm_modific2024`, al doilea punct de intrare
(`comun.vc2:2491`) si calea de ROLLBACK la esec partial raman neacoperite, ca inainte.
## Igiena la iesire
Zero tranzactii deschise (`v$transaction`, 0 randuri), zero procese `vfp9.exe` (`tasklist`), zero
commituri git sau SVN. Niciun fisier de productie atins: singurul fisier nou este suita de test.
`PACK_FACTURARE`, `omodificari.vc2`, `ofacturare_comun.vc2`, `comun.vc2`, `ofacturare_editare.prg`
si `COMUN\clase\ofacturare.vc2` sunt neatinse.