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
This commit is contained in:
2026-08-20 16:35:03 +03:00
parent b5a7108f34
commit ca3c5d7eea
26 changed files with 5316 additions and 103 deletions

View File

@@ -0,0 +1,229 @@
# R6: zecimale la Pret si aspect gri al campurilor editabile, grid Articole (frm_modific2024)
Cercetare, fara modificari de cod. Zona: `COMUN\clase\omodificari.vc2`, clasa `frm_modific2024`
(liniile 6375-16838), grid-ul de articole al facturii editate: `pgfArticole.PAGE3.grdArticoleFactura`
(nu vechiul `Grid1`/`Column1..44` — acela e alt grid, RecordSource `"tACT"`, folosit pentru notele
contabile, nu pentru articolele facturii; grid-ul de articole are 16 coloane numite, ADD OBJECT la
`omodificari.vc2:12330`).
## Partea 1 — zecimalele la pret
### A. Coloanele monetare din grid si masca lor
RecordSource al grid-ului = cursorul `tvd` (creat in `COMUN\programe\ofacturare_editare.prg:278`,
populat in `IncarcaArticoleFactura`, `ofacturare_editare.prg:294-328`, din view-ul Oracle
`VVANZARI_ARTICOLE`).
| Coloana (Header) | Name | ControlSource | Format/InputMask | Linie |
|---|---|---|---|---|
| Pret | cPretArt | `tvd.pret` | `get_mask(12,gnPPRET)` | `omodificari.vc2:12391` |
| Pret achizitie | cPretAchizitieArt | `tvd.pret_achizitie` | `get_mask(12,gnPPRET)` | `omodificari.vc2:12400` |
| Pret cu TVA | cPretCuTvaArt | `tvd.pret_cu_tva` | **fara Format/InputMask** | `omodificari.vc2:12404-12409` |
| Discount unitar | cDiscountUnitarArt | `tvd.discount_unitar` | `get_mask(12,gnPPRET)` | `omodificari.vc2:12426` |
| Cantitate | cCantitateArt | `tvd.cantitate` | `get_mask(12,gnPCANT)` | `omodificari.vc2:12382` |
| Valoare | cValoareArt | `tvd.valoare` | `get_mask(14,gnPa)` | `omodificari.vc2:12463` |
| TVA % | cProcTvavArt | `tvd.proc_tvav` | `"9.99"` (fix, 2 zecimale) | `omodificari.vc2:12417` |
Structura cursorului `tvd` (`ofacturare_editare.prg:278-281`):
```
pret N(14,4) NULL, pret_cu_tva N(14,4) NULL, proc_tvav N(6,4) NULL, discount_unitar N(14,4) NULL,
..., pret_achizitie N(14,4) NULL, ..., cantitate N(12,3) NULL (nu e in acest citat, vezi mai jos)
```
Precizia campurilor din cursor e **hardcodata** (4 zecimale la pret/pret_cu_tva/discount_unitar/
pret_achizitie, 3 la cantitate — vezi linia completa `ofacturare_editare.prg:278`), independent de
`gnPPret`/`gnPCant`. Asta e doar plafonul de stocare; ce se AFISEAZA il decide InputMask-ul de pe
coloana (cand exista).
### B. De unde vin cele 3 zecimale afisate la "Pret"
**Nu dintr-un bug de masca lipsa.** Coloana "Pret" (`cPretArt`, `tvd.pret`) ARE InputMask legat de
o variabila globala: `get_mask(12,gnPPRET)`, `omodificari.vc2:12391`. Daca `gnPPRET` = 3 in mediul
curent, InputMask-ul produce exact 3 zecimale — comportamentul e "controlat de o variabila globala",
exact ce cere utilizatorul. **Problema e ca variabila legata e cea gresita**: `gnPPRET`, nu
`gnPPretV` — vezi punctul D.
### C. Ce este `gnPPret` si care e sablonul consacrat
`gnPPret` e o variabila PUBLIC incarcata din firma (parametru `OPTIUNI.PPRET`), documentata deja in
cercetarea anterioara `docs\cercetare\rec_fact008_pret_achizitie_zecimale.md:28`:
> `OPTIUNI.PPRET` (precizia pretului de achizitie) = **3** (in mediul de productie investigat acolo)
N-am gasit in acest proiect linia exacta unde `gnPPret` e citit din `OPTIUNI` si atribuit (cautare
in `COMUN\programe\oinit_optiuni.prg` — gaseste `gnPA`, `gnPC`, `gnPCurs`, `gnPPretV`, `gnZ`, dar
nu `gnPPret`; probabil incarcat generic, printr-un mecanism care nu foloseste literal sirul
`"gnPPret ="`) — **NESTABILIT exact unde**, dar valoarea si semantica (precizie **achizitie**) sunt
confirmate atat de raportul anterior cat si de tiparul de folosire de mai jos.
Exista o familie de variabile de precizie, cu roluri distincte, confirmate prin comentarii si prin
folosire consecventa in cod:
- `gnPPret` — precizie **pret de achizitie** (cost). Folosire: `ofacturare_stoc.prg:364`
`Alltrim(Str(poArticol.pret_achizitie,18,Max(gnPPret,4)))`; masti pe `pret_achizitie` in
`ointroduceri.vc2:16390,19638` (`get_mask(12,gnPPret)`, coloana NIR).
- `gnPPretV` — precizie **pret de vanzare**, comentata explicit
`COMUN\programe\oinit_optiuni.prg:515`: `Store 0 To gnPPretV && nr. de zecimale pret vanzare`.
Folosire masiva in `ofacturare_comun.prg` (peste 40 de locuri: `pretftva`, `pretctva`,
`pretv_orig`, `discountftva` etc. — toate rotunjite/formatate cu `gnPPretV`) si, esential, la
**scrierea efectiva a pretului de vanzare al liniei de factura**:
`ofacturare_stoc.prg:367` — `Alltrim(Str(poArticol.Pret,18,Iif(poDate.in_valuta=1,gnPVal,gnPPretV)))`
(in functia care insereaza randul in `VANZARI_DETALII`, aceeasi coloana `PRET` pe care o incarca
`tvd.pret`).
- `gnPCant` — precizie cantitate (`get_mask(12,gnPCANT)`, `omodificari.vc2:12382`).
- `gnPc` (`gnPC`) — precizie de calcul/valoare (`get_mask(14,gnPa)`/`gnPc` la coloana Valoare).
- `gnPa` (`gnPA`) — precizie de afisare generica (folosit la `cValoareArt`).
Sablonul consacrat de constructie a mastii: `get_mask(nrCaractere, nrZecimale)`
(`COMUN\programe\proceduri_comune.prg:1090-1110`) — construieste un sir `"999 999.999"` cu atatea
`9` dupa punct cate zecimale i se dau; **nu exista logica speciala in `get_mask`**, deci diferenta
de comportament vine strict din CE variabila i se paseaza la fiecare coloana.
### D. Modelul corect exista deja, in acelasi fisier de clase — `ofacturare.vc2`
`COMUN\clase\ofacturare.vc2:3489-3498`, grid de rulaje/stoc, doua coloane invecinate:
```
Column5.ControlSource = "pret", ;
Column5.InputMask = (get_mask(14,gnPPret)), ; && cost / achizitie
Column5.Name = "cPret", ;
...
Column6.ControlSource = "pretv", ;
Column6.InputMask = (get_mask(14,gnPPretV)), ; && vanzare
Column6.Name = "cPretv", ;
```
Acelasi tipar apare si in `COMUN\clase\ocomenzi.vc2:1174`
(`This._grdrow2.cPret.InputMask = get_mask(14,gnPPretV)` — pret de vanzare pe comanda) si in
`ointroduceri.vc2:10071,16390,19638` (`get_mask(...,gnPPret)` — toate pe campuri de **achizitie**,
in formularele de NIR).
**Regula confirmata in tot codul suitei: campul care reprezinta pretul de ACHIZITIE foloseste
`gnPPret`; campul care reprezinta pretul de VANZARE al liniei foloseste `gnPPretV`.** Chiar scrierea
in Oracle a coloanei `VANZARI_DETALII.PRET` (aceeasi coloana din care se umple `tvd.pret`) respecta
aceasta regula: `ofacturare_stoc.prg:367` foloseste `gnPPretV`, nu `gnPPret`.
### Concluzie Partea 1 — defectul
`omodificari.vc2:12391` — `Column6.InputMask = (get_mask(12,gnPPRET))` pentru **`cPretArt`**
(`tvd.pret`, coloana "Pret" = pretul de VANZARE al liniei) foloseste variabila gresita din familie:
**`gnPPRET`** (precizie achizitie) in loc de **`gnPPretV`** (precizie vanzare, cea corecta pentru
acest camp). Coloana vecina, `cPretAchizitieArt` (`omodificari.vc2:12400`, `tvd.pret_achizitie`),
foloseste corect `gnPPRET` — e evident ca la scrierea acestei sectiuni de grid s-a copiat masca de
la achizitie si pe coloana de vanzare de langa ea.
Daca in mediul reclamat `OPTIUNI.PPRET` (achizitie) = 3 si `OPTIUNI.PPRETV` (vanzare) e alta
valoare (tipic 2), exact asta explica simptomul: coloana "Pret" (vanzare) afiseaza 3 zecimale
pentru ca "imprumuta" precizia de achizitie, nu pe cea de vanzare.
Coloana "Pret cu TVA" (`cPretCuTvaArt`) nu are deloc InputMask (`omodificari.vc2:12404-12409`) — nu
e sursa celor "3 zecimale" reclamate la "Pret", dar e un defect inrudit: afiseaza precizia bruta a
campului din cursor (4 zecimale, `pret_cu_tva N(14,4)`), necontrolata de nicio variabila globala.
**Schita de interventie** (fara aplicare): `Column6.InputMask = (get_mask(12,gnPPRET))` ->
`Column6.InputMask = (get_mask(12,gnPPretV))` la `omodificari.vc2:12391`, dupa modelul din
`ofacturare.vc2:3497` / `ocomenzi.vc2:1174`.
## Partea 2 — fundalul gri al campurilor editabile
### E-F. Sursa reala a griului si divergenta Column.ReadOnly vs Text1.ReadOnly
Confirmat: aproape toate coloanele au `DynamicForeColor` (nu `BackColor`) la nivel de coloana —
un singur `IIF` pentru culoarea textului dupa `tvd.sters`/`id_vanzare_set`, identic pe toate cele
16 coloane (ex. `omodificari.vc2:12350`). **Niciun `DynamicBackColor`, niciun `Enabled=.F.`** pe
coloane. Culoarea de fundal reala vine din proprietatea `BackColor` fixa a controlului `Text1`
inclus in fiecare coloana (`ADD OBJECT '...Text1' AS textbox`), si **nu coincide cu
`Column.ReadOnly`**:
| Camp | Column.ReadOnly | Column linie | Text1.ReadOnly | Text1.BackColor | Text1 linii |
|---|---|---|---|---|---|
| Denumire (cDenumireArt) | `.F.` (editabil) | 12354 | **`.T.`** | **225,225,225 (gri)** | 12527-12536 |
| Cod material (cCodmatArt) | `.T.` | 12361 | `.T.` | 225,225,225 | 12506-12515 (consistent) |
| Serie (cSerieArt) | `.F.` (editabil) | 12368 | **`.T.`** | **225,225,225 (gri)** | 12734-12743 |
| Lot (cLotArt) | `.F.` (editabil) | 12375 | **`.T.`** | **225,225,225 (gri)** | 12631-12640 |
| Cantitate (cCantitateArt) | `.F.` | 12384 | `.F.` | 255,255,255 (alb) | 12485-12494 (consistent) |
| Pret (cPretArt) | `.F.` | 12393 | `.F.` | 255,255,255 (alb) | 12673-12682 (consistent) |
| Pret achizitie (cPretAchizitieArt) | `.F.` | 12402 | `.F.` | 255,255,255 (alb) | 12652-12661 (consistent) |
| TVA % (cProcTvavArt) | `.F.` (editabil) | 12419 | **`.T.`** | **225,225,225 (gri)** | 12713-12722 |
| Discount unitar (cDiscountUnitarArt) | `.T.` | 12428 | `.T.` | 225,225,225 | 12548-12557 (consistent) |
| Gestiune (cGestiuneArt) | `.F.` (editabil) | 12435 | **`.T.`** | **225,225,225 (gri)** | 12610-12619 |
| Valuta (cValutaArt) | `.F.` (editabil) | 12442 | **`.T.`** | **225,225,225 (gri)** | 12797-12806 |
| Explicatie (cExplicatieArt) | `.F.` (editabil) | 12449 | **`.T.`** | **225,225,225 (gri)** | 12569-12578 |
| Taxcode (cTaxcodeArt) | `.F.` (editabil) | 12456 | **`.T.`** | **225,225,225 (gri)** | 12755-12764 |
| Valoare (cValoareArt) | `.T.` | 12465 | `.T.` | 225,225,225 | 12776-12785 (consistent) |
| Explicatie TVA (cExplicatieTvaArt) | `.F.` (editabil) | 12472 | **`.T.`** | **225,225,225 (gri)** | 12589-12598 |
**9 din 16 coloane sunt declarate editabile la nivel de `Column.ReadOnly=.F.` dar controlul `Text1`
inclus e `ReadOnly=.T.` cu fundal gri (225,225,225).** In VFP, cand o coloana de grid contine un
control custom (nu editorul implicit), editabilitatea reala vine din controlul inclus, nu din
`Column.ReadOnly` — deci aceste 9 campuri **nu accepta tastare directa in celula**, indiferent ce
spune `Column.ReadOnly`. Asta explica de ce aratau gri: griul e corect pentru "nu se editeaza prin
tastare directa".
Pentru unele din ele exista insa un mecanism real de editare, prin dialog, nu prin tastare:
`cGestiuneArt.Text1.GotFocus` (`omodificari.vc2:12734`... de fapt liniile de cod sunt la
`16734-16744`) seteaza `Thisform.pccontrol` si `InteractiveChange` deschide un editor:
```
PROCEDURE pgfArticole.PAGE3.grdArticoleFactura.cGestiuneArt.Text1.InteractiveChange (16739)
loEditor = Createobject('ArticoleNotaEditor', Thisform)
loEditor.ModificaNomenclator(Thisform.pccontrol)
```
Acelasi tipar la `cExplicatieTvaArt` (`16722-16732`). Pentru `cSerieArt`, `cLotArt`, `cExplicatieArt`
exista doar un handler `.When` (`16745`, `16716`, `16804`) care blocheaza intrarea in celula cand
`Thisform.lArticoleReadOnly` sau `id_vanzare_set<>0`, dar **niciun cod care sa comute
`Text1.ReadOnly` la `.F.`** — n-am gasit nicio atribuire dinamica `.Text1.ReadOnly = ...` in tot
corpul clasei `frm_modific2024` pentru aceste coloane (cautare exhaustiva pe intervalul
6375-16838). **Concluzie verificabila pe cod**: cu configuratia actuala, `cSerieArt`, `cLotArt`,
`cExplicatieArt`, `cValutaArt`, `cTaxcodeArt`, `cDenumireArt`, `cProcTvavArt` **nu au niciun
mecanism de editare activ in acest grid** — nici tastare (Text1.ReadOnly=.T.), nici editor prin
dublu-clic/InteractiveChange (spre deosebire de cGestiuneArt/cExplicatieTvaArt, care au editor).
Daca utilizatorul le percepe ca "editabile", fie testeaza cu date/build vechi, fie editarea se
intampla prin alta cale neinventariata aici (buton `but_modificaR` — vezi mai jos, NESTABILIT unde
e definit click-ul lui).
`Thisform.but_modificaR.Enabled` se seteaza in `AfterRowColChange`
(`omodificari.vc2:16678-16682`) dupa coloana curenta si `!lArticoleReadOnly`, sugerand un buton
extern de "Modifica" — dar **n-am gasit definitia obiectului `but_modificaR` sau handler-ul lui de
`Click` in `omodificari.vc2`** (cautare `grep -n "but_modificaR"` in tot fisierul: doar cele 7
referinte de mai sus, toate `.Enabled = ...` sau `.Visible = ...`, niciun `ADD OBJECT` sau
`PROCEDURE but_modificaR...Click`). **NESTABILIT**: butonul e probabil mostenit dintr-o clasa
parinte in afara acestui fisier — nu s-a investigat mai departe (ar necesita cautare in
`_frm_base.vcx`/alte `.vc2` din `COMUN\clase`, in afara scopului "aceasta clasa").
### G. Conventia de culoare in restul aplicatiei
**Exista o conventie, si e vizibila chiar in acelasi fisier de clasa**, pe pagina "Rulaje"
(`pgfArticole.PAGE1.grdRulaje`, alt tab al aceluiasi formular):
- editabil prin tastare directa: `BackColor = 255,255,255` (alb) + `ReadOnly = .F.` — ex.
`cPret.Text1`, `omodificari.vc2:9990-9999`.
- editabil prin dialog (GotFocus seteaza `pccontrol`, InteractiveChange deschide editor):
`BackColor = 160,255,205` (**verde deschis**) + `ReadOnly = .F.` — ex. `cGest.Text1`
(`omodificari.vc2:9689-9698`) si `cDenumire.Text1` (`omodificari.vc2:9595-9604`).
- needitabil: `BackColor = 225,225,225` (gri) + `ReadOnly = .T.`.
Pe pagina "Articole" (`grdArticoleFactura`, PAGE3 — grid-ul reclamat), campul `cGestiuneArt` are
**exact acelasi mecanism de editare prin dialog** ca `cGest` de pe pagina Rulaje (acelasi tipar
GotFocus/InteractiveChange/`ArticoleNotaEditor`), dar culoarea lui e **gri + ReadOnly=.T.**
(`omodificari.vc2:12610-12619`), nu verde + ReadOnly=.F. ca omologul lui de pe Rulaje. **Asta e
dovada directa a inconsistentei**: acelasi tipar functional (editare prin editor extern) e codat
cu doua culori diferite in doua pagini ale aceluiasi formular — verde (corect, semnaleaza "se
editeaza altfel") pe Rulaje, gri (gresit, semnaleaza "nu se editeaza") pe Articole.
## Rezumatul defectelor gasite (fara aplicare)
1. **Zecimale**: `Column6.InputMask` la `cPretArt` (`omodificari.vc2:12391`) foloseste `gnPPRET`
(precizie achizitie) in loc de `gnPPretV` (precizie vanzare) — schita: schimbat argumentul.
2. **Aspect gri**: 9 coloane (`cDenumireArt`, `cSerieArt`, `cLotArt`, `cProcTvavArt`,
`cGestiuneArt`, `cValutaArt`, `cExplicatieArt`, `cTaxcodeArt`, `cExplicatieTvaArt`) au
`Column.ReadOnly=.F.` dar `Text1.ReadOnly=.T.` + `BackColor=225,225,225` — contrazic propria
lor declaratie de editabilitate. Dintre ele, doar `cGestiuneArt` si `cExplicatieTvaArt` au
mecanism real de editare (editor extern) si ar trebui colorate verde
(`160,255,205`, ca modelul de pe Rulaje) + `ReadOnly=.F.` pe Text1; restul (`cDenumireArt`,
`cSerieArt`, `cLotArt`, `cProcTvavArt`, `cValutaArt`, `cExplicatieArt`, `cTaxcodeArt`) fie n-au
deloc cale de editare activa in cod (raman corect needitabile — atunci `Column.ReadOnly` ar
trebui pus `.T.` ca sa nu mai contrazica aspectul), fie editarea lor se face pe o cale
neidentificata in aceasta cercetare (butonul `but_modificaR`, NESTABILIT unde e definit).