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:
255
docs/cercetare/rec_r6_nomenclatoare_grid.md
Normal file
255
docs/cercetare/rec_r6_nomenclatoare_grid.md
Normal file
@@ -0,0 +1,255 @@
|
||||
# Cercetare R6 — nomenclatoare in gridul Articole (frm_modific2024)
|
||||
|
||||
Zona: `COMUN\clase\omodificari.vc2` (formularul `frm_modific2024`), gridul
|
||||
`pgfArticole.PAGE3.grdArticoleFactura`. Dispecerul comun e in
|
||||
`COMUN\programe\ofacturare_editare.prg`, clasa `ArticoleNotaEditor`.
|
||||
|
||||
## A. Inventarul coloanelor gridului Articole
|
||||
|
||||
Bloc `ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura'` incepe la
|
||||
`omodificari.vc2:12330`; lista completa a coloanelor (`ControlSource` + `Name`) e la
|
||||
`omodificari.vc2:12349-12471`.
|
||||
|
||||
| Coloana (Name) | ControlSource | Linie ControlSource | Legata de nomenclator? |
|
||||
|---|---|---|---|
|
||||
| cDenumireArt (Column1) | `tvd.denumire` | `omodificari.vc2:12349` | DA — articol |
|
||||
| cCodmatArt (Column2) | `tvd.codmat` | `omodificari.vc2:12356` | nu |
|
||||
| cSerieArt (Column3) | `tvd.serie` | `omodificari.vc2:12363` | nu |
|
||||
| cLotArt (Column4) | `tvd.lot` | `omodificari.vc2:12370` | nu |
|
||||
| cCantitateArt (Column5) | `tvd.cantitate` | `omodificari.vc2:12377` | nu |
|
||||
| cPretArt (Column6) | `tvd.pret` | `omodificari.vc2:12386` | nu |
|
||||
| cPretAchizitieArt (Column7) | `tvd.pret_achizitie` | `omodificari.vc2:12395` | nu |
|
||||
| cPretCuTvaArt (Column8) | `tvd.pret_cu_tva` | `omodificari.vc2:12404` | nu (checkbox propriu) |
|
||||
| cProcTvavArt (Column9) | `tvd.proc_tvav` | `omodificari.vc2:12412` | nu |
|
||||
| cDiscountUnitarArt (Column10) | `tvd.discount_unitar` | `omodificari.vc2:12421` | nu |
|
||||
| **cGestiuneArt (Column11)** | `tvd.nume_gestiune` | `omodificari.vc2:12430` | **DA — gestiune** |
|
||||
| **cValutaArt (Column12)** | `tvd.nume_val` | `omodificari.vc2:12437` | **DA — valuta** |
|
||||
| cExplicatieArt (Column13) | `tvd.explicatie` | `omodificari.vc2:12444` | nu (text liber) |
|
||||
| **cTaxcodeArt (Column14)** | `tvd.taxcode` | `omodificari.vc2:12451` | **DA — cod TVA SAF-T** |
|
||||
| cValoareArt (Column15) | `tvd.valoare` | `omodificari.vc2:12458` | nu (calculat) |
|
||||
| **cExplicatieTvaArt (Column16)** | `Iif(Seek(Nvl(tvd.id_jtva_coloana,0),'crsJtvaTemp','id_jtva'),crsJtvaTemp.denumire,'')` | `omodificari.vc2:12467` | **DA — explicatie TVA / id_jtva_coloana** |
|
||||
|
||||
Cele 5 coloane legate de un nomenclator sunt exact cele acceptate de dispecer —
|
||||
vezi `ArticoleNotaEditor::AreNomenclator` (`ofacturare_editare.prg:978-981`):
|
||||
|
||||
```
|
||||
PROCEDURE AreNomenclator
|
||||
LPARAMETERS tcControl
|
||||
RETURN Inlist(This.NumeCamp(m.tcControl), 'denumire', 'nume_gestiune', 'nume_val', 'taxcode', 'id_jtva_coloana')
|
||||
ENDPROC
|
||||
```
|
||||
|
||||
Observatie importanta pentru cauza de la punctul D: **`cTaxcodeArt` si `cExplicatieTvaArt` au
|
||||
Column.ReadOnly = .F.** (`omodificari.vc2:12379` / linia `Column14.ReadOnly = .F.` la
|
||||
`omodificari.vc2` in blocul 12451-12457, respectiv `Column16.ReadOnly = .F.` in blocul
|
||||
12467-12471), dar **controlul `Text1` din interiorul lor are `ReadOnly = .T.`** — vezi
|
||||
`omodificari.vc2:12759` (cTaxcodeArt.Text1) si `omodificari.vc2:12594` (cExplicatieTvaArt.Text1).
|
||||
Diferenta reala dintre ele nu e ReadOnly-ul (identic), ci **daca `ControlSource` e camp direct
|
||||
sau expresie** — vezi punctul D.
|
||||
|
||||
## B. Ce evenimente exista azi pe fiecare coloana cu nomenclator
|
||||
|
||||
| Coloana | InteractiveChange | DblClick | Buton lateral "Modificare" (`But_modificaR`) |
|
||||
|---|---|---|---|
|
||||
| cDenumireArt | DA — `omodificari.vc2:16710-16714` | **nu exista** | DA (comun, vezi E) |
|
||||
| cGestiuneArt | DA — `omodificari.vc2:16739-16743` | **nu exista** | DA (comun) |
|
||||
| cValutaArt | DA — `omodificari.vc2:16826-16830` | **nu exista** | DA (comun) |
|
||||
| cTaxcodeArt | DA — `omodificari.vc2:16815-16819` | **nu exista** | DA (comun) |
|
||||
| cExplicatieTvaArt | DA — `omodificari.vc2:16728-16732` (exista, dar nu se declanseaza — vezi D) | **nu exista** | DA (comun) |
|
||||
|
||||
Corpul e identic pentru toate cele 5 (exemplu, taxcode):
|
||||
|
||||
```
|
||||
PROCEDURE pgfArticole.PAGE3.grdArticoleFactura.cTaxcodeArt.Text1.InteractiveChange
|
||||
Local loEditor
|
||||
loEditor = Createobject('ArticoleNotaEditor', Thisform)
|
||||
loEditor.ModificaNomenclator(Thisform.pccontrol)
|
||||
ENDPROC
|
||||
```
|
||||
|
||||
Confirmare ca `DblClick` nu exista deloc pe `grdArticoleFactura` sau pe coloanele lui: cautare
|
||||
`InteractiveChange|DblClick` in tot `omodificari.vc2` — singurele `DblClick` din fisier sunt pe
|
||||
alt grid, `grdRequest` (`omodificari.vc2:390` si `omodificari.vc2:408`, vezi F).
|
||||
|
||||
## C. Dispecerul comun — `ArticoleNotaEditor::ModificaNomenclator`
|
||||
|
||||
Definit in `COMUN\programe\ofacturare_editare.prg:1069-1137`, clasa `ArticoleNotaEditor`
|
||||
(`ofacturare_editare.prg:947-1165`).
|
||||
|
||||
Semnatura: `PROCEDURE ModificaNomenclator LPARAMETERS tcControl` — primeste un string de forma
|
||||
`alias.camp` (ex. `tvd.taxcode`, `tvd.id_jtva_coloana`).
|
||||
|
||||
Garda de intrare (`ofacturare_editare.prg:1073-1076`):
|
||||
|
||||
```
|
||||
lcCamp = This.NumeCamp(m.tcControl)
|
||||
IF !This.Editabil() OR Reccount('tvd') = 0 OR !This.AreNomenclator(m.lcCamp) OR Nvl(tvd.id_vanzare_set, 0) <> 0
|
||||
RETURN .F.
|
||||
ENDIF
|
||||
```
|
||||
|
||||
`Do Case` de deschidere a nomenclatorului (`ofacturare_editare.prg:1078-1089`):
|
||||
|
||||
```
|
||||
DO CASE
|
||||
CASE m.lcCamp == 'denumire'
|
||||
loCauta = caut_articol()
|
||||
CASE m.lcCamp == 'nume_gestiune'
|
||||
loCauta = caut_gestiune()
|
||||
CASE m.lcCamp == 'nume_val'
|
||||
loCauta = caut_valuta()
|
||||
CASE m.lcCamp == 'id_jtva_coloana'
|
||||
loCauta = This.CautaExplicatieTva()
|
||||
OTHERWISE
|
||||
loCauta = This.CautaCodTva()
|
||||
ENDCASE
|
||||
```
|
||||
|
||||
Discrimineaza dupa **numele campului** extras din `tcControl` (nu dupa numele coloanei din grid,
|
||||
nu dupa un parametru separat) — `NumeCamp` (`ofacturare_editare.prg:966-974`) taie tot ce e
|
||||
inainte de primul `.`. `taxcode` cade pe ramura `OTHERWISE` (`CautaCodTva`,
|
||||
`ofacturare_editare.prg:1152-1158`).
|
||||
|
||||
Dupa alegere, al doilea `Do Case` (`ofacturare_editare.prg:1096-1132`) scrie valorile alese
|
||||
inapoi in `tvd`, cu ramura dedicata pentru `id_jtva_coloana`
|
||||
(`ofacturare_editare.prg:1124-1129`, recalculeaza `proc_tvav` si cheama
|
||||
`This.oForm.UpdateExplicatieSAFTArt()` + `calculeaza_valori_articol()`).
|
||||
|
||||
## D. De ce "explicatie TVA" nu se declanseaza pe InteractiveChange
|
||||
|
||||
**Nu e o garda care blocheaza si nu e o ramura lipsa in dispecer** — `id_jtva_coloana` e in
|
||||
`AreNomenclator` (`ofacturare_editare.prg:980`) si are ramura proprie in `Do Case`
|
||||
(`ofacturare_editare.prg:1085-1086`). Handlerul `InteractiveChange` exista si e corect
|
||||
(`omodificari.vc2:16728-16732`).
|
||||
|
||||
**Cauza e ca evenimentul `InteractiveChange` pur si simplu nu se produce niciodata din tastare
|
||||
pe aceasta coloana**, pentru ca `ControlSource`-ul ei e o expresie, nu un camp direct:
|
||||
|
||||
```
|
||||
Column16.ControlSource = "Iif(Seek(Nvl(tvd.id_jtva_coloana,0),'crsJtvaTemp','id_jtva'),crsJtvaTemp.denumire,'')"
|
||||
```
|
||||
(`omodificari.vc2:12467`)
|
||||
|
||||
versus `cTaxcodeArt`:
|
||||
|
||||
```
|
||||
Column14.ControlSource = "tvd.taxcode"
|
||||
```
|
||||
(`omodificari.vc2:12451`)
|
||||
|
||||
In VFP, un `Textbox` intr-o coloana de grid cu `ReadOnly = .T.` (asa cum sunt ambele,
|
||||
`omodificari.vc2:12759` si `omodificari.vc2:12594`) nu accepta editare directa de text, dar cand
|
||||
`Column.ControlSource` e un **camp real dintr-un cursor navigabil** ("bound field"), gridul
|
||||
VFP declanseaza cautarea incrementala nativa la tastare (type-ahead / seek pe recordset): tasta
|
||||
apasata muta recordul curent la prima potrivire, ceea ce schimba valoarea afisata legata de acel
|
||||
camp — iar aceasta schimbare de `Value` e cea care declanseaza `InteractiveChange`. Cand
|
||||
`ControlSource` e o **expresie** (ca la `cExplicatieTvaArt`, care afiseaza denumirea din
|
||||
`crsJtvaTemp` via `Seek`, nu campul `tvd.id_jtva_coloana` in sine), gridul nu are un camp
|
||||
indexabil pe care sa faca seek — mecanismul de cautare incrementala nu se activeaza, deci
|
||||
`Value`-ul textboxului nu se schimba niciodata din tastare, deci `InteractiveChange` nu are cum
|
||||
sa se declanseze prin tastare pe aceasta coloana.
|
||||
|
||||
Chiar comentariul din cod confirma asta, la `GotFocus`-ul aceleiasi coloane
|
||||
(`omodificari.vc2:16723`):
|
||||
|
||||
```
|
||||
*!* coloana afiseaza denumirea din crsJtvaTemp, deci ControlSource e expresie - campul editat se da explicit
|
||||
```
|
||||
|
||||
adica autorul stia deja ca `ControlSource` e o expresie si de-aia a scris explicit campul real
|
||||
(`tvd.id_jtva_coloana`) in `Thisform.pccontrol` la `GotFocus`, in loc sa se bazeze pe
|
||||
`This.ControlSource` (cum fac celelalte coloane). Explicatia asta e chiar mecanismul care face ca
|
||||
butonul lateral sa functioneze — vezi E.
|
||||
|
||||
Dublu-click nu se declanseaza pe nicio coloana pentru ca **pur si simplu nu exista niciun handler
|
||||
`DblClick`** pe `grdArticoleFactura` (vezi B) — nu e o problema specifica de "explicatie TVA", e
|
||||
valabil identic si pentru `taxcode`, doar ca la `taxcode` utilizatorul are alternativa tastarii,
|
||||
care functioneaza (camp direct).
|
||||
|
||||
## E. Cum ajunge butonul lateral "Modificare" sa deschida explicatie TVA
|
||||
|
||||
Handler: `PROCEDURE But_modificaR.Click`, `omodificari.vc2:15319-15326`:
|
||||
|
||||
```
|
||||
PROCEDURE But_modificaR.Click
|
||||
Local lcRul, loEditor
|
||||
IF thisform.pgfArticole.ActivePage = 3
|
||||
loEditor = Createobject('ArticoleNotaEditor', Thisform)
|
||||
loEditor.ModificaNomenclator(thisform.pccontrol)
|
||||
RETURN
|
||||
ENDIF
|
||||
...
|
||||
ENDPROC
|
||||
```
|
||||
|
||||
Cheia e ca butonul **nu citeste `ControlSource`-ul coloanei curente** — foloseste direct
|
||||
`Thisform.pccontrol`, o proprietate a formularului scrisa de fiecare `GotFocus` al coloanei
|
||||
active, inainte ca utilizatorul sa apuce sa tasteze ceva. Pentru `cExplicatieTvaArt`, `GotFocus`
|
||||
scrie explicit campul real (`omodificari.vc2:16722-16726`):
|
||||
|
||||
```
|
||||
PROCEDURE pgfArticole.PAGE3.grdArticoleFactura.cExplicatieTvaArt.Text1.GotFocus
|
||||
*!* coloana afiseaza denumirea din crsJtvaTemp, deci ControlSource e expresie - campul editat se da explicit
|
||||
Thisform.pccontrol = 'tvd.id_jtva_coloana'
|
||||
Thisform.pncolumnorder = This.Parent.ColumnOrder
|
||||
ENDPROC
|
||||
```
|
||||
|
||||
Pentru celelalte 4 coloane, `GotFocus` foloseste `Alltrim(This.ControlSource)` direct (ex.
|
||||
`cTaxcodeArt.Text1.GotFocus`, `omodificari.vc2:16810-16813`), ceea ce functioneaza pentru ele
|
||||
pentru ca acolo `ControlSource` chiar e campul real.
|
||||
|
||||
Deci calea functioneaza pentru ca **`GotFocus` — care se declanseaza la orice intrare in celula,
|
||||
prin click simplu, tab sau navigare cu sagetile, indiferent de tipul de `ControlSource` — a
|
||||
populat deja `Thisform.pccontrol` corect inainte ca butonul sa fie apasat.** Butonul nu depinde
|
||||
deloc de `InteractiveChange`; de-aia merge la explicatie TVA desi tastarea nu merge.
|
||||
|
||||
## F. Cost estimat pentru DblClick pe fiecare coloana cu nomenclator
|
||||
|
||||
**Exista deja un sablon direct aplicabil**, chiar in cadrul modelului de "coloana Text1 in grid cu
|
||||
InteractiveChange care deschide ceva" — `grdRequest`, alt grid din acelasi formular:
|
||||
|
||||
```
|
||||
PROCEDURE grdRequest.cLabelItem.Text1.DblClick
|
||||
Thisform.lEditMode = .T.
|
||||
ENDPROC
|
||||
```
|
||||
(`omodificari.vc2:390-392`)
|
||||
|
||||
```
|
||||
PROCEDURE grdRequest.cValoareDefaultText.Text1.DblClick
|
||||
If !Empty(Nvl(crsRequest.fis_lista, ''))
|
||||
Thisform.Selectfromlookup()
|
||||
Endif
|
||||
ENDPROC
|
||||
```
|
||||
(`omodificari.vc2:408-412`)
|
||||
|
||||
Confirmare pentru VFP: intr-adevar, evenimentul se pune pe **controlul din interiorul coloanei**
|
||||
(`Column.Text1.DblClick`), exact cum arata cele doua exemple de mai sus si exact cum sunt puse
|
||||
deja `InteractiveChange` si `GotFocus` pe `grdArticoleFactura` (`Column.Text1.InteractiveChange`,
|
||||
`Column.Text1.GotFocus`) — nu exista niciun `DblClick` pus pe nivelul `Column` insusi in tot
|
||||
fisierul. Modelul `grdRequest` e potrivit ca forma (unde se pune evenimentul), dar nu ca
|
||||
continut — acolo `DblClick` face lucruri specifice acelui grid (comuta un mod de editare / arata
|
||||
un lookup din alta zona), nu apeleaza un dispecer de nomenclator.
|
||||
|
||||
Sablonul de continut potrivit e chiar `InteractiveChange`-urile deja existente pe
|
||||
`grdArticoleFactura` (`omodificari.vc2:16710-16714`, `16728-16732`, `16739-16743`,
|
||||
`16815-16819`, `16826-16830`) — toate identice, 3 linii:
|
||||
|
||||
```
|
||||
Local loEditor
|
||||
loEditor = Createobject('ArticoleNotaEditor', Thisform)
|
||||
loEditor.ModificaNomenclator(Thisform.pccontrol)
|
||||
```
|
||||
|
||||
Costul e mic si uniform: adaugarea a 5 metode noi `DblClick` (una per coloana cu nomenclator),
|
||||
fiecare cu acelasi corp de 3 linii de mai sus. Pentru ca toate cele 5 `GotFocus` seteaza deja
|
||||
`Thisform.pccontrol` corect — fie din `ControlSource` (denumire, gestiune, valuta, taxcode), fie
|
||||
explicit (explicatie TVA, `omodificari.vc2:16724`) — folosirea lui `Thisform.pccontrol` in
|
||||
`DblClick` functioneaza uniform pe toate cele 5, inclusiv pe explicatie TVA, fara sa depinda de
|
||||
mecanismul de seek care lipseste la coloana cu `ControlSource` expresie. Practic acelasi apel pe
|
||||
care il face deja `But_modificaR.Click` (`omodificari.vc2:15319-15326`, vezi E).
|
||||
|
||||
Nu e nevoie de nicio schimbare in dispecer (`ModificaNomenclator`) sau in `AreNomenclator` — ele
|
||||
deja accepta toate cele 5 campuri.
|
||||
Reference in New Issue
Block a user