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

183 lines
13 KiB
Markdown

# Verificare discount pe linie de factura — frm_facturare_articole / VANZARI_DETALII
Investigatie read-only. Toate liniile citate au fost verificate pe fisierul text real din working
copy (`ofacturare.vc2`, 23087 linii, ultima scriere 07.08 22:18) si pe scripturile DDL din
`D:\ROA\DATABASE\SCRIPTURI_CLAR`. Nu s-a executat nimic pe baza de date.
## 1. Confirmare/infirmare afirmatii initiale
**Concluzie**: toate afirmatiile despre `frm_facturare_articole` sunt corecte, cu linii care se
potrivesc exact sau aproape exact. Confirmat via `vfp_symbols.ps1 -Where` ca formularul
`frm_facturare_articole` ocupa exact `ofacturare.vc2:10968-15739`.
**Dovezi**:
- `Column5.ControlSource = "discountctva"`, `Column5.Name = "cDiscountCTva"`, `Column5.ReadOnly = .T.`
— confirmat la `ofacturare.vc2:12311-12317` (identic cu afirmatia).
- `Column9.ControlSource = "vdiscountftva"`, `Column9.Name = "cVdiscountftva"`, **fara** `ReadOnly`
— confirmat la `ofacturare.vc2:12340-12345` (identic).
- Capete de coloana: `Caption = "Discount unitar cu TVA"` la `:12409`, `Caption = "Discount unitar in
valuta fara TVA"` la `:12546` — ambele confirmate exact.
- Excludere reciproca pe valuta la `ofacturare.vc2:15269-15278`:
```
15269 If poDate.in_valuta = 0
15270 Thisform.grd_factura.RemoveObject([cVpretFtva])
15271 Thisform.grd_factura.RemoveObject([cVdiscountftva])
15272 Thisform.grd_factura.RemoveObject([cVvaldiminuatftva])
15273 Else
15274 Thisform.grd_factura.RemoveObject([cPretFtva])
15275 Thisform.grd_factura.RemoveObject([cDiscountctva])
```
confirmat identic (linii exacte, nu doar apropiate).
- `VANZARI_DETALII.DISCOUNT_UNITAR NUMBER(22,6)` — confirmat, dar cu precizare: linia corecta in
`ff_2024_06_13_02_COMUN_FACTURARE.sql` e `:3` (nu si `:9`/`:16` cum lasa sa se inteleaga
formularea initiala — acelea sunt `VANZARI_DETALII_TEMP` si, respectiv, `CRM_POLITICI_PRET_ART`,
vezi punctul 4).
## 2. Consecinta practica pe ecran
**Concluzie**: pe factura in lei, coloana vizibila e **"Discount unitar cu TVA"** (`discountctva`)
si e **needitabila** in grid (`ReadOnly = .T.`). Pe factura in valuta, coloana vizibila e
**"Discount unitar in valuta fara TVA"** (`vdiscountftva`) si **este editabila direct in grid**
(nicio proprietate `ReadOnly` setata pe coloana sau pe `Text1`-ul ei → mosteneste default-ul VFP,
`.F.`).
**Dovezi**:
- Ramane pe ecran: cand `in_valuta = 0` se elimina cele 3 coloane "V..." (inclusiv
`cVdiscountftva`) → ramane `cDiscountCTva`. Cand `in_valuta <> 0` se elimina `cDiscountctva` (si
celelalte 3 coloane fara "V") → ramane `cVdiscountftva`. (`:15269-15278`, citat mai sus).
- Ca sa nu presupun ca lipsa lui `Column9.ReadOnly` inseamna implicit editabil, am verificat lantul
de clase: grid-ul `grd_factura` e `ADD OBJECT 'grd_factura' AS _grdrow` (`:12263`), fara
`ReadOnly` la nivel de grid intre `:12263-12364`; clasa `_grdrow` (`_grd_base.vc2:445`) nu
seteaza `ReadOnly` nicaieri in propriul body, iar parintele ei `_grdbase`/`_grid` de asemenea nu
(singurele 3 aparitii de `ReadOnly` in `_grd_base.vc2` sunt in clasa separata `_grdfooter`,
neinrudita). Deci Column9 chiar e editabila.
- Confirmare suplimentara: in formularul **`frm_facturare_articole2`** (prototip separat, clasa la
`ofacturare.vc2:15741-19355`, NU formularul in productie), aceleasi doua coloane apar cu
`ReadOnly` explicit: `Column5.ReadOnly = .F.` (`:16657`) si `Column9.ReadOnly = .F.` (`:16688`) —
adica in prototip discountul e editabil in ambele monede direct din grid; in formularul real
doar varianta in valuta e editabila din grid.
## 3. Poate operatorul introduce azi un discount pe linie, si pe ce cale
**Concluzie**: da, poate — dar nu prin `do_calculeaza_discount` de la
`frm_facturare_articole:13405-13424` (asta calculeaza discountul **global pe toata factura**,
`Thisform.ndiscfactron`/`ndiscfactval`, nicio legatura cu `discountctva`/`vdiscountftva` pe
linie — vezi corectia de la final). Calea reala e formularul **`frm_articol_factura`**
(`ofacturare.vc2:1108-2659`), deschis din `do_adauga_articol` la adaugarea unui articol
(`:12873`, `ofrmadarticol.Show(1)` doar daca `!tlImplicit`). Acolo exista metoda
`frm_articol_factura.do_calculeaza_discount` (`:1874-1976`) legata de 3 controale editabile:
`Clb_procent_discount.Text_simplu1` (procent), `Clb_discount_unitar.tx_suma_nat`/`tx_suma_val`
(suma in lei / valuta), `Clb_discountctva.tx_suma_nat`/`tx_suma_val` (varianta cu TVA) — toate cu
handler `Valid`/`InteractiveChange` care apeleaza `do_calculeaza_discount(valoare, tip)` cu
`tip=1` procent, `tip=2` lei, `tip=3` valuta (`:2602-2624`, `:2646-2649`).
**Lantul, cu linii**:
1. Operator tasteaza in unul din campurile de mai sus → `Valid`/`InteractiveChange` →
`Thisform.do_calculeaza_discount(valoare, tip)` (`ofacturare.vc2:2602-2649`).
2. `do_calculeaza_discount` (`:1874-1976`) scrie in obiectul `poArticol`:
`poArticol.discount_unitar`, `discount_unitar_val`, `discount_unitar_ctva`,
`discount_unitar_ctva_val` (ex. `:1898-1906`, `:1943-1951`).
3. La revenirea in `do_adauga_articol` (`:12813-13086`), `poArticol` e scris in `crsfactura` prin
`Gather`/`Replace`:
```
12956 Replace id_temp With Recno(), codmat With Nvl(poArticol.codmat, Space(50)), ;
...
12957 discountftva With poArticol.discount_unitar, discountctva With poArticol.discount_unitar_ctva, ;
vdiscountftva With Nvl(poArticol.discount_unitar_val, 0), vdiscountctva With Nvl(poArticol.discount_unitar_ctva_val, 0)
```
(linii `12956-12957`; varianta pentru selectie multipla de articole la `13003-13005`).
4. `discount_unitar` initial (inainte de tastare) e preluat din `crsarticole` (cursorul de stoc,
populat inainte de deschiderea dialogului) prin `do_initializeaza_articol` (`:13618` si urm.):
`toArticol.discount_unitar = Nvl(toArticol.discount_unitar, 0)` (`:13630`) — deci daca stocul /
politica de pret vine deja cu un discount populat, acela e valoarea implicita afisata in dialog,
pe care operatorul o poate suprascrie.
5. Cale suplimentara, directa: pe factura in valuta, cum `cVdiscountftva` e editabil in grid
(punctul 2), operatorul poate scrie si direct in celula `vdiscountftva` din `grd_factura` — dar
fara niciun `Valid`/`InteractiveChange` propriu definit pentru acea coloana in
`frm_facturare_articole` (cautat explicit `cVdiscountftva`/`cDiscountCTva` in intervalul
`10968-15739`: singurele hit-uri sunt definitiile de coloana si `RemoveObject`, niciun handler
de eveniment) — editarea directa in grid NU declanseaza recalcularea automata a
`vvaldiminuatftva`/totaluri, doar modifica valoarea bruta in `crsfactura`.
## 4. Structura reala a coloanelor de discount pe VANZARI_DETALII
**Concluzie**: nu exista un `CREATE TABLE VANZARI_DETALII` in `SCRIPTURI_CLAR` (arhiva incepe din
2009, iar tabela exista deja atunci — coloana `DISCOUNT_UNITAR` era deja in uz in pachete PL/SQL
din 2009, deci a fost creata inainte de arhiva). Singura coloana de discount pe
`VANZARI_DETALII`/`VANZARI_DETALII_TEMP` gasita in `SCRIPTURI_CLAR` e **`DISCOUNT_UNITAR`**, si
singura modificare de tip/precizie inregistrata e cea din 2024.
**Dovezi (cronologic, tot ce am gasit cu `DISCOUNT` in contextul acestei tabele)**:
- Nu exista niciun `CREATE TABLE VANZARI_DETALII` sau `ALTER TABLE VANZARI_DETALII ADD DISCOUNT...`
in toata arhiva `SCRIPTURI_CLAR` (2009-2026). Cel mai vechi hit pe `DISCOUNT_UNITAR` legat de
aceasta tabela e o declaratie de variabila `V_DISCOUNT_UNITAR VANZARI_DETALII.DISCOUNT_UNITAR%TYPE`
in pachetul `PACK_FACTURARE`, prezenta deja in scripturile din 2009 (ex.
`2009\9\ff_2009_09_03_01_FACTURARE_PACK_FACTURARE.sql`) — coloana exista deja atunci.
- Singura modificare de precizie gasita: `ff_2024_06_13_02_COMUN_FACTURARE.sql:3` —
`alter table VANZARI_DETALII modify discount_unitar NUMBER(22,6);` — si simetric pentru
`VANZARI_DETALII_TEMP` la linia `:9`, si pentru `CRM_POLITICI_PRET_ART` (tabela de **politici de
pret**) la linia `:16`. Deci forma finala confirmata: **`DISCOUNT_UNITAR NUMBER(22,6)`**, o
singura coloana de discount (valoare, nu procent), identica pe toate cele 3 tabele.
- Nu exista alte coloane `DISCOUNT%`/`VDISCOUNT%` la nivel Oracle pe `VANZARI_DETALII` — cele patru
campuri VFP `discountftva`/`discountctva`/`vdiscountftva`/`vdiscountctva` din `crsfactura` NU au
corespondent 1:1 in schema Oracle; la scriere (`Gather`/`Replace` in `do_adauga_articol`, punctul
3) doar `discount_unitar` (si varianta cu TVA calculata din el) ajunge, prin campurile
intermediare, la coloana unica Oracle.
- Convenția de interogare a bazei de dezvoltare, gasita in `COMUN\docs\scripturi-migrare-db.md:36-40`:
sursa de referinta pentru DDL e schema de dezvoltare **`MARIUSM_AUTO`** (bazata pe
`ROA_CENTRAL`), interogata prin `goExecutor`, niciodata o schema de client. Nu am rulat nimic pe
baza — doar raportez conventia, asa cum a cerut sarcina.
## 5. Coloana de procent de discount pe VANZARI_DETALII / campul procdisc
**Concluzie**: **nu** exista o coloana de procent de discount pe `VANZARI_DETALII` (doar
`DISCOUNT_UNITAR`, o valoare absoluta). Campul `procdisc` din `frm_facturare_articole2` e doar un
camp de lucru in grid, **fara nicio scriere in cursorul local si fara corespondent Oracle** —
practic un camp scaffolded si neconectat.
**Dovezi**:
- Cautare `DISCOUNT`+`PROCENT`/`PROC` in `ff_2024_06_13_02_COMUN_FACTURARE.sql` (scriptul care
fixeaza forma finala a coloanelor de discount): nicio potrivire — confirma ca nu exista un
"procent discount" ca si coloana pe `VANZARI_DETALII`.
- `procdisc` apare **o singura data** in tot `ofacturare.vc2`: `Column14.ControlSource = "procdisc"`
la `:16721`, in interiorul clasei `frm_facturare_articole2` (`15741-19355` — prototip, nu
formularul in productie).
- Nicio instructiune `Gather`/`Replace ... procdisc With ...` in tot fisierul (cautat pe tot
`ofacturare.vc2`) — camp fara sursa de populare in cod.
- Toate celelalte aparitii de "procdisc" din fisier sunt de fapt variabila de memorie
`gnMemProcDisc` ("memorare procent discount" — o optiune de aplicatie care controleaza daca
procentul de discount tastat se retine intre articole, `:2299`, `:2441`, `:12835` etc.), fara
legatura cu campul de cursor `procdisc`.
- Cautare `PROCDISC` in `SCRIPTURI_CLAR`: doar 2 hit-uri, ambele in scripturi din 2015 pentru
tabela de **optiuni firma** (`co_2015_12_09_01_OPTIUNI.sql`, `ff_2015_12_09_01_OPTIUNI.sql`) —
legate de aceeasi optiune `gnMemProcDisc`, nu de `VANZARI_DETALII`.
## Ce era gresit in afirmatiile de mai sus
- Formularea "linia 3, 9, 16" pentru coloana Oracle `DISCOUNT_UNITAR` grupa laolalta 3 tabele
diferite (`VANZARI_DETALII` la `:3`, `VANZARI_DETALII_TEMP` la `:9`, `CRM_POLITICI_PRET_ART` la
`:16`) ca si cum ar fi acelasi lucru repetat de 3 ori — corect ca valoare (toate devin
`NUMBER(22,6)`), dar sunt 3 tabele distincte, nu 3 confirmari ale aceleiasi coloane.
- Cea mai importanta corectie: linia indicata pentru "de unde se scrie discountctva/vdiscountftva
— din `do_calculeaza_discount` (`ofacturare.vc2:13405-13424`)" trimite la metoda gresita.
`frm_facturare_articole.do_calculeaza_discount` de la acea linie calculeaza discountul **global
pe factura** (`Thisform.ndiscfactron`/`ndiscfactval`), nu discountul pe linie. Metoda care chiar
calculeaza `discount_unitar`/`discount_unitar_ctva` (sursa reala pentru `discountctva` si
`vdiscountftva`) e **`frm_articol_factura.do_calculeaza_discount`**, o metoda cu acelasi nume dar
in alta clasa, la `ofacturare.vc2:1874-1976`. Cele doua metode au nume identic dar apartin la
doua clase diferite din acelasi fisier — o capcana reala de grep fara indexul de simboluri.
## Necunoscute ramase
- Nu am verificat daca `crsarticole` (cursorul de stoc din care pleaca `poArticol.discount_unitar`
la `do_initializeaza_articol:13630`) e populat vreodata cu un discount nenul direct dintr-o
interogare de politica de pret (`CRM_POLITICI_PRET_ART`) inainte de a ajunge in dialogul
`frm_articol_factura` — am gasit doar ca acea tabela are aceeasi coloana `discount_unitar`
(`NUMBER(22,6)`), nu am urmarit interogarea SQL efectiva care umple `crsarticole`/`crsartselectate`
(cod probabil in `Programe/`, in afara `ofacturare.vc2`, netrasat din lipsa de timp alocat).
- Nu am confirmat pe date reale (Oracle) daca exista astazi randuri cu `DISCOUNT_UNITAR` populat pe
`VANZARI_DETALII` provenind din editarea directa in grid pe factura in valuta (punctul 2/3,
ultimul paragraf) — doar am aratat ca acea cale exista in cod, fara handler de recalcul.
- Nu am cautat daca `frm_facturare_articole2` (prototipul) e instantiat undeva in productie sau e
cu adevarat mort/nefolosit — task-ul l-a framat deja ca "prototip" si am pastrat presupunerea.