# Discount pe linie (DISCOUNT_UNITAR) in afara formularului de facturare — rapoarte .frx, eFactura, SAF-T Cercetare read-only pentru S4c (plan_13). Nu s-a modificat niciun fisier, nu s-a rulat git_sync. ## Verdict (5-10 randuri) Niciun raport tiparit de factura (`factura.fr2`, `facturatip*.fr2`, `factura_val*.fr2`, `invoice*.fr2`, `proforma*.fr2`) nu afiseaza discountul pe linie ca coloana separata — nici ca valoare, nici ca procent. Rapoartele tiparesc `pretftva` (pret unitar) si `valftva` (valoare linie) care sunt **deja nete de discount** (calculate ca `pretftva-discountftva` / `Sum(valdiminuatftva)` in cursorul intermediar `crsfacttemp`, construit de `prelucreaza_factura`/`creeaza_crsfacttemp` din `ofacturare_comun.prg`). eFactura (`xmlefactura.prg`) foloseste **exact acelasi cursor** — comentariul din cod chiar spune asta explicit — deci `LineExtensionAmount`/`PriceAmount` trimise la ANAF sunt aceleasi valori nete, cu optiunea (dezactivata implicit, din flag-uri globale) de a adauga si un `cac:AllowanceCharge` informativ pe linie. SAF-T (D406): **nu exista niciun generator D406/SAF-T in ROAFACTURARE** — exista doar tabele de nomenclator cu prefix `saft_` (coduri TVA/plata) folosite pe partea de achizitii, fara legatura cu `DISCOUNT_UNITAR`. **Raspuns la intrebarea care conteaza**: daca discountul pe linie devine editabil direct in grid, **nu se strica nimic in codul rapoartelor/eFacturii** — ele citesc oricum campurile finale (`valdiminuatftva`/`discountftva`/`discount_unitar`) din cursor, indiferent cum au fost populate (dialog separat vs. editare in grid). **Riscul real e in alta parte**: exista deja azi o cale prin care discountul e editabil direct in grid (`vdiscountftva`, pe factura in valuta) care **nu declanseaza recalcularea** lui `valdiminuatftva`/`valdiminuatctva` — vezi `docs\cercetare\discount_verificare2.md` punctul 3, ultimul paragraf. Daca S4c extinde editarea in grid la toate coloanele de discount fara sa cablaje si recalculul, rapoartele si eFactura vor tipari/trimite **valori vechi** (stale), pentru ca ambele citesc `valdiminuatftva`, nu `discount_unitar` direct. ## 1. Rapoartele .frx/.fr2 tiparite **Cautare**: `Grep 'DISCOUNT'` si apoi `Grep 'disc'` (case-insensitive) in toate `.fr2` din `COMUN\Rapoarte` cu glob `*factur*.fr2`, `*proforma*.fr2`, `*invoice*.fr2` — **zero potriviri** in toate cele (factura.fr2, facturatip.fr2, facturatip_a5.fr2, facturatip_cuchit.fr2, factura_a5.fr2, factura_chit.fr2, factura_val.fr2, factura_val_a5.fr2, invoice.fr2, invoice_a5.fr2, proforma.fr2, proforma_orig.fr2, proforma_val.fr2, proforma_val_orig.fr2). Singurele 2 fisiere `.fr2` din toata `COMUN\Rapoarte` care contin "DISCOUNT" sunt `rap_nir_materiale.fr2` si `rap_nir_marfuri.fr2` — rapoarte de NIR (receptie), nu facturi emise. **Ce se tipareste per linie** (confirmat in `factura.fr2`): ``` 1002: 1014: 1026: 1062: -- procent TVA, nu discount ``` Deci: cantitate, pret unitar, valoare linie, procent TVA. Nici discount valoric, nici procent discount. **De unde vin `pretftva`/`valftva` — si de ce sunt deja nete**: cursorul de tiparire (`crsfacttemp`) e construit de `Procedure prelucreaza_factura` (`COMUN\programe\ofacturare_comun.prg:1055-1059`), apelata din `COMUN\programe\ofacturare.prg:1887`: ``` prelucreaza_factura([crsfactura], [crsfacturaset], [crsfacturafinala], poDate.discount_evidentiat, poDate.in_valuta, lnPretListAviz, poDate.nListareDetaliata) ``` In interior, `Do Case` pe `tnDiscountEvidentiat`/`lnPretListAviz` (`ofacturare_comun.prg:1156-1248`). Cazul comun, `tnDiscountEvidentiat = 0` (checkbox-ul "Se pune in evidenta discount-ul..." NEBIFAT — comportamentul implicit): ``` 1182: Sum(cantitate) As cantitate,pretftva-discountftva As pretftva,; ... 1186: Sum(valdiminuatftva) As valftva,Sum(valdiminuattva) As valtva,; ``` adica pretul tiparit = pret brut minus discountul pe unitate, iar valoarea tiparita = suma `valdiminuatftva` (deja calculata la adaugarea articolului ca `pretftva - discount_unitar`, cf. `ofacturare.vc2:13126`, deja documentat in `discount_pe_articol.md` sectiunea 3). Simetric pentru varianta cu TVA la `:1226-1230`. **Cazul `tnDiscountEvidentiat = 1`** (checkbox bifat — discountul "se pune in evidenta"): ``` 1165: pretftva,Nvl(codbare,... -- pretftva RAMANE brut, nu se scade discountftva 1166-1167: Sum(valftva) As valftvai,... Sum(valftva) As valftva,Sum(valtva) As valtva, 1168: discountftva,Sum(valdiscountftva) As valdiscountftva,Sum(valdiscounttva) As valdiscounttva, ``` Aici `pretftva`/`valftva` tiparite raman **brute** (neta de discount), iar `discountftva`/ `valdiscountftva`/`valdiscounttva` sunt calculate in cursor **dar nu sunt tiparite de niciun .frx** (confirmat, zero hit pe "disc" in .fr2). Practic, cand discountul e "pus in evidenta", pretul si valoarea linie tiparite pe factura NU reflecta discountul per linie — discountul apare doar ca linie separata de document (randul-sentinela `denumire = Replicate('Z',20)`, populat din `Thisform.nbazafdiscount`/`nbazafdiscountval` la `ofacturare.vc2:14534,14591,18532,18602` si `ofacturare_comun.prg:1891`) — asta e insa discountul **de document** (`VANZARI.DISCOUNT`), nu `DISCOUNT_UNITAR` pe linie. Nu am gasit nicio dovada ca acest mod (`discount_evidentiat=1`) ar fi folosit uzual — e o optiune existenta, documentata deja in `discount_pe_articol.md` punctul 3 ca schimband "doar mecanismul aritmetic", dar aici se vede consecinta suplimentara: **si ce se tipareste**. **Fara impartiri la pret zero pe randul de discount**: unde raportul calculeaza procent (`proc_disc`), sursa e protejata explicit: ``` 1184-1185 (ofacturare_comun.prg): Iif(cu_tva=0,Iif(pretftva<>0,Round(discountftva/pretftva*100,2),0),; Iif(pretctva<>0,Round(discountctva/pretctva*100,2),0)) ``` deci nu exista risc de impartire la zero — dar, ca observat mai sus, `proc_disc` nu e tiparit nicaieri in .frx-urile de factura verificate (e calculat doar pentru consum intern/eFactura). ## 2. eFactura (ANAF/UBL) — `xmlefactura.prg` **Concluzie**: eFactura foloseste **acelasi cursor de linii ca cel de la tiparire**, explicit documentat in cod: ``` oexport.prg:1590: * tcCursorLiniiFactura = numele cursorului cu liniile facturii, asa cum arata la listare ``` Lantul: `ofacturare.prg:2126` -> `goExport.export2xml_efactura(poDate, m.lcCursoreFactura, ...)` cu `lcCursoreFactura` = `lcCursorFacturaTemp` (= `'crsFacturaFinala'`, `ofacturare.prg:1892`, sau `'crsfacturafinalaval'` pentru valuta) -> `xmlefactura.prg:231`: ``` Select a.*, ... From (m.tcCursorLiniiFactura) a Left Join cJTVAVanzariTemp b ... Into Cursor C_IES_FORM Readwrite ``` Deci `C_IES_FORM` (sursa liniilor XML) e construit direct din cursorul de tiparire — aceleasi `pretftva`/`pretftvai`/`valftva`/`valftvai`/`proc_disc` descrise la punctul 1, cu aceeasi dependenta de `poDate.discount_evidentiat`. **Ce se trimite pe linie**: - `cbc:LineExtensionAmount` (BT-131) = `C_IES_FORM.valftva` — `xmlefactura.prg:935-937`. - `cbc:PriceAmount` = `C_IES_FORM.pretftva` — `xmlefactura.prg:1043-1046`. - Optional (doar daca flag global `gnEFACTURA_XML_DISC_PLISTA_LINIE = 1` SI `pretftvai > pretftva`): un `cac:AllowanceCharge` la nivel de linie cu `Amount = valftvai-valftva`, `BaseAmount = valftvai`, `MultiplierFactorNumeric = proc_disc` — `xmlefactura.prg:952-971`. - Optional (flag separat `gnEFACTURA_XML_DISC_PLISTA_ART = 1`): un `cac:AllowanceCharge` la nivel de `cac:Price` cu discountul unitar (`ABS(pretftvai-pretftva)`) — `xmlefactura.prg:1054-1067`. Ambele flag-uri sunt verificate cu `TYPE(...) = 'N' AND ... = 1` — daca variabila globala nu exista sau e 0 (implicit), **nu se trimite niciun `AllowanceCharge` pe linie**; discountul e vizibil pentru ANAF doar implicit, prin faptul ca `PriceAmount * InvoicedQuantity = LineExtensionAmount` (adica pretul e deja net). Nu am gasit unde sunt setate global aceste doua variabile (`gnEFACTURA_XML_DISC_PLISTA_LINIE`/`_ART`) — posibil optiuni de firma necautate in acest fisier; nu afecteaza concluzia principala. **Discount de document, separat**: exista o eticheta euristica in `C_IES_FORM` (`Iif('DISCOUNT' $ Upper(a.denumire) And a.pretftva < 0, 1, 0) As discount`, `xmlefactura.prg:230`) care detecteaza randuri-pseudo-articol de discount/taxa (denumire contine "DISCOUNT", pret negativ) si le exclude din liniile normale (`Scan For discount = 0`, `:901`), agregandu-le separat intr-un `cac:AllowanceCharge` la nivel de document (`:756-793`, motiv "Discount", cod 95). Acesta e discountul de document, nu `DISCOUNT_UNITAR` pe linie — mecanism diferit de randul-sentinela `Replicate('Z',20)` folosit la tiparire (punctul 1). **Nicio validare care ar respinge discount > pret**: n-am gasit nicio verificare explicita in `xmlefactura.prg` care sa blocheze o linie cu `discount_unitar` mai mare ca pretul (ar rezulta `pretftva` negativ pe linie individuala; codul are doar o corectie generala pentru `pretftva < 0` la nivel de linie completa, `xmlefactura.prg:236-239`, care inverseaza semnul cantitate/pret — nu specifica pentru discount). ## 3. SAF-T (D406) **Concluzie: nu exista implementare SAF-T/D406 in ROAFACTURARE.** Cautat explicit: - `Grep 'SAF-T|SAFT|D406|declaratie406|GenereazaSAFT|GenereazaD406'` in tot `COMUN\programe` si `COMUN` — nicio potrivire pe un generator de fisier D406/SAF-T XML. - `Glob '**/*saft*'` pe tot proiectul si pe `COMUN` — zero fisiere cu "saft" in nume. - Singurele aparitii reale (nu fals-pozitive de tip "safe") sunt: - `oinit_optiuni.prg:523-524`: `gl406 = (TYPE('gnD406') = 'N' and m.gnD406 = 1)` — un flag "firma are activata SAFT 406", comentat "Firma are activata SAFT 406". - `oproceduri_comune.prg:889-896,6083,6151`, `ointroduceri.prg:1597`: `saft_taxtable` si `saft_mecanisme_plati` — tabele de nomenclator (coduri de TVA/mecanism de plata compatibile SAF-T) folosite pe **partea de achizitii** (limitare deducere TVA la introducerea facturilor de achizitie), nu pe vanzari/facturare. - `oproceduri_comune.prg:6066-6067,6137-6138,6195`: comentarii care mentioneaza "Taxa SAFT tip" ca denumire pentru codurile de TVA, tot pe achizitii. - Niciuna din aceste aparitii nu are legatura cu `DISCOUNT`/`DISCOUNT_UNITAR` — cautarea `DISCOUNT` in fisierele care contin "saft" (`oproceduri_comune.prg`, `ointroduceri.prg`, `pmenu.prg`, `oinit_optiuni.prg`) nu a gasit nicio intersectie intre cele doua seturi de rezultate. **Interpretare**: `gl406` pare sa activeze doar validari/coduri suplimentare pentru conformitate SAF-T pe partea de achizitii (poate pentru ca alt produs din suita, ROACONT, genereaza efectiv D406 din datele contabile) — ROAFACTURARE nu produce singur un fisier D406. ## 4. Alte consumatori care ar presupune discount uniform pe document Nu am gasit vreun raport/export care sa presupuna un discount unic pe tot documentul in sensul de "aceeasi valoare/procent pe toate liniile" — mecanismul de discount de document (`VANZARI.DISCOUNT`, randul `Replicate('Z',20)`) e tratat ca **valoare agregata separata**, adaugata ca linie proprie (in tiparire) sau ca `AllowanceCharge` de document (in eFactura), nu redistribuita implicit pe liniile existente — cu o exceptie: `xmlefactura.prg` are logica de **distribuire** explicita a discountului/taxelor de document pe articole cand bifa `chkDistribuieDiscount`/ `llDistribuieDiscountTaxe` e activa (`xmlefactura.prg:12189-12320`, `:12534-12790`) — asta insa opereaza pe discountul de document, nu presupune ca discountul de linie (`DISCOUNT_UNITAR`) e uniform; dimpotriva, distribuie proportional cu valoarea fiecarei linii, deci suporta discount diferit per linie din start. ## Ce ar strica S4c, concret **Nu se strica codul rapoartelor sau al eFacturii** — ambele citesc valori finale din cursor (`valdiminuatftva`, `discountftva`, `pretftva` deja net), indiferent de sursa UI a discountului. **Se poate strica invariantul pe care se bazeaza**, daca editarea in grid nu recalculeaza: - **Dovada ca gaura exista deja azi**: pe factura in valuta, coloana `vdiscountftva` e editabila direct in grid (`ofacturare.vc2:12340-12345`, fara `ReadOnly`) dar **fara niciun handler `Valid`/`InteractiveChange`** care sa recalculeze `vvaldiminuatftva`/totalurile — confirmat cautat explicit in `docs\cercetare\discount_verificare2.md` punctul 3, ultimul paragraf ("editarea directa in grid NU declanseaza recalcularea automata a `vvaldiminuatftva`/totaluri, doar modifica valoarea bruta in `crsfactura`"). - **De ce conteaza pentru rapoarte/eFactura**: `valdiminuatftva`/`valdiminuatctva` (nu `discount_unitar` brut) sunt campurile citite de `prelucreaza_factura`/`creeaza_crsfacttemp` pentru `valftva` tiparit si trimis la ANAF (punctele 1 si 2 de mai sus). Daca operatorul modifica discountul direct in grid si acel camp nu se recalculeaza, factura tiparita si XML-ul ANAF vor arata **valoarea veche** (dinainte de editare) — o discrepanta reala intre ce vede operatorul in grid si ce se tipareste/trimite. - **Concluzie pentru plan**: daca S4c extinde editarea de discount la toate coloanele din grid (inclusiv `discountctva`, azi read-only pe lei), trebuie cablat un recalcul echivalent cu `frm_articol_factura.do_calculeaza_discount` (`ofacturare.vc2:1874-1976`) pe evenimentul de editare din grid — altfel riscul de mai sus (deja prezent azi doar pe valuta) se extinde la toate facturile in lei. ## Ramas de verificat - Valorile implicite ale flag-urilor globale `gnEFACTURA_XML_DISC_PLISTA_LINIE` si `gnEFACTURA_XML_DISC_PLISTA_ART` (unde sunt setate ca optiune de firma) — nu am cautat sursa lor, doar am confirmat ca cu `TYPE(...) <> 'N'` (nedefinite) comportamentul e "fara AllowanceCharge pe linie". - Nu am verificat pe date reale (Oracle/XML generat) un caz cu `discount_evidentiat=1` si `DISCOUNT_UNITAR` populat simultan, ca sa confirm empiric (nu doar din citirea codului) ca factura tiparita arata pretul brut. - Nu am urmarit `crsfacturafinalaval` (varianta valuta a cursorului final) linie cu linie — am presupus ca urmeaza acelasi patron ca `crsfacturafinala`/`crsfacttemp` (cursorul in lei), pe baza simetriei campurilor `vpretftva`/`vvalftva`/`vdiscountftva` gasite deja documentate in `discount_verificare2.md` si `discount_pe_articol.md`; n-am reverificat separat sursa SQL pentru varianta valuta. - Nu am identificat un al doilea produs (ROACONT?) care sa genereze efectiv D406 din datele scrise de ROAFACTURARE — presupunerea din sectiunea 3 e speculativa, nu confirmata cu cod.