# 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: diff aplicat (sters). ## 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.