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
15 KiB
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:364Alltrim(Str(poArticol.pret_achizitie,18,Max(gnPPret,4))); masti pepret_achizitieinointroduceri.vc2:16390,19638(get_mask(12,gnPPret), coloana NIR).gnPPretV— precizie pret de vanzare, comentata explicitCOMUN\programe\oinit_optiuni.prg:515:Store 0 To gnPPretV && nr. de zecimale pret vanzare. Folosire masiva inofacturare_comun.prg(peste 40 de locuri:pretftva,pretctva,pretv_orig,discountftvaetc. — toate rotunjite/formatate cugnPPretV) 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 inVANZARI_DETALII, aceeasi coloanaPRETpe care o incarcatvd.pret).gnPCant— precizie cantitate (get_mask(12,gnPCANT),omodificari.vc2:12382).gnPc(gnPC) — precizie de calcul/valoare (get_mask(14,gnPa)/gnPcla coloana Valoare).gnPa(gnPA) — precizie de afisare generica (folosit lacValoareArt).
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) sicDenumire.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)
- Zecimale:
Column6.InputMasklacPretArt(omodificari.vc2:12391) folosestegnPPRET(precizie achizitie) in loc degnPPretV(precizie vanzare) — schita: schimbat argumentul. - Aspect gri: 9 coloane (
cDenumireArt,cSerieArt,cLotArt,cProcTvavArt,cGestiuneArt,cValutaArt,cExplicatieArt,cTaxcodeArt,cExplicatieTvaArt) auColumn.ReadOnly=.F.darText1.ReadOnly=.T.+BackColor=225,225,225— contrazic propria lor declaratie de editabilitate. Dintre ele, doarcGestiuneArtsicExplicatieTvaArtau 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 — atunciColumn.ReadOnlyar trebui pus.T.ca sa nu mai contrazica aspectul), fie editarea lor se face pe o cale neidentificata in aceasta cercetare (butonulbut_modificaR, NESTABILIT unde e definit).