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
452 lines
23 KiB
Markdown
452 lines
23 KiB
Markdown
# Runda 5 - editare inline pe pagina Articole (proiectare, fara aplicare)
|
|
|
|
Document de proiectare pentru cerinta: pe formularul unificat `frm_modific2024`, pagina 3
|
|
"Articole factura" (`pgfArticole.PAGE3.grdArticoleFactura`, cursor `tvd`), sa devina editabile
|
|
inline `serie`, `lot`, `explicatie` si `proc_tvav`, iar coloanele cu nomenclator (`denumire`,
|
|
`nume_gestiune`, `nume_val`, `taxcode`, `id_jtva_coloana`) sa deschida dialogul de cautare si pe
|
|
`InteractiveChange`, nu doar din `But_modificaR.Click`.
|
|
|
|
Linii citate din `COMUN\clase\omodificari.vc2` (17059 linii) si
|
|
`COMUN\programe\ofacturare_editare.prg` (1140 linii), stare de pe disc la data cercetarii -
|
|
fisierul e in lucru, **reconfirma numerele de linie cu `vfp_symbols.ps1` inainte de orice
|
|
`txt2vcx.ps1`**.
|
|
|
|
Fiecare bloc de cod de mai jos e marcat **VERIFICAT** (citit direct din sursa) sau **PRESUPUS**
|
|
(judecata de proiectare, nu extrasa din cod existent).
|
|
|
|
---
|
|
|
|
## 0. Constatare care schimba premisa punctului A din brief
|
|
|
|
**VERIFICAT.** Intrebarea "`cCantitateArt`/`cPretArt` marcheaza `lmodificat` si conteaza asta la
|
|
salvare" are raspuns clar: **`lmodificat` nu e citit nicaieri ca filtru de salvare.**
|
|
|
|
`ScrieArticoleFacturaEditate` (`ofacturare_editare.prg:473-571`) are doar doua `SCAN`-uri pe
|
|
`tvd`:
|
|
|
|
- `ofacturare_editare.prg:502` - `SCAN FOR id_vanzare_det > 0 AND Nvl(sters,0) <> 1` (UPDATE
|
|
liniilor existente)
|
|
- `ofacturare_editare.prg:534` - `SCAN FOR id_vanzare_det = 0 AND Nvl(sters,0) <> 1` (INSERT
|
|
liniilor noi)
|
|
|
|
Niciunul nu conditioneaza pe `lmodificat`. Comentariul de la `ofacturare_editare.prg:498` o spune
|
|
explicit: *"invie si actualizeaza liniile pastrate - toate cele active din alias, nu doar
|
|
lmodificat, pasul de mai sus le-a marcat pe toate"*. Singurele scrieri ale campului
|
|
(`AplicaAdaugareTvd:857`, `ComutaSters:1034`, `DuplicaLinie:1053`,
|
|
`ModificaNomenclator:1108`, `calculeaza_valori_articol` in `omodificari.vc2:13521`) nu au nicio
|
|
citire-pereche - `lmodificat` e scris dar niciodata citit. E camp vestigial (poate util pentru o
|
|
extensie viitoare, gen indicator vizual "linie modificata"), **nu un defect de blocat livrarea**.
|
|
|
|
Consecinta pentru A: coloanele noi (`serie`, `lot`, `explicatie`, `proc_tvav`) **nu au nevoie sa
|
|
seteze `lmodificat` ca sa se salveze** - se salveaza oricum, ca toate liniile active. Recomand
|
|
totusi sa-l seteze, din consecventa cu restul coloanelor editabile si ca sa nu ramana singurele
|
|
exceptii daca cineva incepe sa-l citeasca in viitor - cost zero, un `REPLACE` in plus.
|
|
|
|
---
|
|
|
|
## 1. Defect real gasit pe drum: UPDATE-ul nu scrie `serie`/`lot`/`explicatie`
|
|
|
|
**VERIFICAT - trebuie reparat in aceeasi livrare**, exact cum a semnalat brief-ul.
|
|
|
|
UPDATE-ul liniilor existente (`ofacturare_editare.prg:505-517`):
|
|
|
|
```foxpro
|
|
lcSql = [update vanzari_detalii set sters = 0, cantitate = ] + Alltrim(Str(Nvl(cantitate,0),18,3)) + ;
|
|
[, pret = ] + Alltrim(Str(Nvl(pret,0),18,4)) + [, pret_cu_tva = ] + Alltrim(Str(Nvl(pret_cu_tva,0))) + ;
|
|
[, pret_achizitie = ] + Alltrim(Str(Nvl(pret_achizitie,0),18,4)) + ;
|
|
[, proc_tvav = ] + Alltrim(Str(Nvl(proc_tvav,0),18,4)) + ;
|
|
[, discount_unitar = ] + Alltrim(Str(Nvl(discount_unitar,0),18,4)) + ;
|
|
[, id_articol = ] + Alltrim(Str(Nvl(id_articol,0))) + ;
|
|
[, id_gestiune = ] + Iif(Isnull(id_gestiune),[NULL],Alltrim(Str(id_gestiune))) + ;
|
|
[, id_valuta = ] + Iif(Isnull(id_valuta),[NULL],Alltrim(Str(id_valuta))) + ;
|
|
[, id_jtva_coloana = ] + Iif(Isnull(id_jtva_coloana),[NULL],Alltrim(Str(id_jtva_coloana))) + ;
|
|
[, taxcode = ] + Iif(Isnull(taxcode),[NULL],Alltrim(Str(taxcode))) + ;
|
|
[, cont = ] + Iif(Empty(Nvl(cont,'')),[NULL],['] + OracleSpecialCharacters(Alltrim(Nvl(cont,''))) + [']) + ;
|
|
[, id_utils = ] + Alltrim(Str(gnIdUtil)) + [, dataoras = sysdate ] + ;
|
|
[where id_vanzare_det = ] + Alltrim(Str(id_vanzare_det)) + [ and id_vanzare = ] + Alltrim(Str(m.tnIdVanzare))
|
|
```
|
|
|
|
`proc_tvav` **e deja in lista** (linia 508) - editarea cotei TVA persista deja corect pe linii
|
|
existente, nimic de reparat acolo. Lipsesc doar `serie`, `lot`, `explicatie` - prezente in
|
|
INSERT-ul liniilor noi (`ofacturare_editare.prg:535-544`, aceeasi forma
|
|
`Iif(Empty(Nvl(...,'')),[NULL],['] + OracleSpecialCharacters(...) + [']`) dar absente din UPDATE.
|
|
Fara reparatie, editarea inline propusa la punctul A de mai jos s-ar pierde tacut la salvare pe
|
|
orice linie deja salvata (`id_vanzare_det > 0`) - exact scenariul cel mai comun (factura cu
|
|
articole sincronizate din rulaj).
|
|
|
|
### Propunere - `ofacturare_editare.prg`, dupa linia 515 (`, cont = ...`), inainte de linia 516
|
|
(`, id_utils = ...`)
|
|
|
|
```foxpro
|
|
[, cont = ] + Iif(Empty(Nvl(cont,'')),[NULL],['] + OracleSpecialCharacters(Alltrim(Nvl(cont,''))) + [']) + ;
|
|
[, serie = ] + Iif(Empty(Nvl(serie,'')),[NULL],['] + OracleSpecialCharacters(Alltrim(Nvl(serie,''))) + [']) + ;
|
|
[, lot = ] + Iif(Empty(Nvl(lot,'')),[NULL],['] + OracleSpecialCharacters(Alltrim(Nvl(lot,''))) + [']) + ;
|
|
[, explicatie = ] + Iif(Empty(Nvl(explicatie,'')),[NULL],['] + OracleSpecialCharacters(Alltrim(Nvl(explicatie,''))) + [']) + ;
|
|
[, id_utils = ] + Alltrim(Str(gnIdUtil)) + [, dataoras = sysdate ] + ;
|
|
```
|
|
|
|
Trei linii noi, tipar identic cu cel deja folosit pentru `cont` pe acelasi UPDATE si pentru
|
|
`serie`/`explicatie`/`lot` pe INSERT (`:538-540`). Comentariul de la `:503-504` ("toate campurile
|
|
pe care grila si nomenclatoarele le pot schimba") ramane valabil fara modificare.
|
|
|
|
---
|
|
|
|
## 2. Coloane care devin editabile inline (`serie`, `lot`, `explicatie`)
|
|
|
|
**VERIFICAT** - definitiile actuale, `omodificari.vc2`:
|
|
|
|
| coloana | linie definitie | `ControlSource` | `ReadOnly` azi |
|
|
|---|---|---|---|
|
|
| `cSerieArt` (Column3) | `:12359-12365` | `tvd.serie` | `.T.` |
|
|
| `cLotArt` (Column4) | `:12366-12372` | `tvd.lot` | `.T.` |
|
|
| `cExplicatieArt` (Column13) | `:12441-12447` | `tvd.explicatie` | `.T.` |
|
|
|
|
Niciuna nu are azi `Text1.When`/`Text1.Valid` propriu (singurele evenimente pe pagina 3 sunt cele
|
|
listate la `omodificari.vc2:16678-16770`, verificat prin citire directa a intervalului).
|
|
|
|
### Garda de editare - condifia de baza vs. cea extinsa a lui `cPretAchizitieArt`
|
|
|
|
**VERIFICAT.** Doua garde diferite exista azi pe pagina 3:
|
|
|
|
```foxpro
|
|
* cCantitateArt.Text1.When si cPretArt.Text1.When - garda de baza
|
|
IF Thisform.lArticoleReadOnly OR Nvl(tvd.id_vanzare_set,0) <> 0
|
|
RETURN .F.
|
|
ENDIF
|
|
|
|
* cPretAchizitieArt.Text1.When - garda extinsa, cu o conditie in plus
|
|
IF Thisform.lArticoleReadOnly OR Nvl(tvd.id_vanzare_set,0) <> 0 OR Nvl(tvd.id_vanzare_det,0) <> 0
|
|
RETURN .F.
|
|
ENDIF
|
|
```
|
|
|
|
**PRESUPUS** (nu exista comentariu care sa explice; judecata de proiectare pe baza codului
|
|
inconjurator): conditia suplimentara `Nvl(tvd.id_vanzare_det,0) <> 0` de pe pret de achizitie
|
|
blocheaza editarea manuala pe liniile **deja legate de o vanzare persistata** (`id_vanzare_det`
|
|
nenul inseamna linie care exista deja in `VANZARI_DETALII`, deci a venit dintr-o miscare de stoc
|
|
reala). Sustinut de garda de la salvare (`omodificari.vc2:14457-14460`): un avertisment de "pret
|
|
de achizitie 0" apare doar pentru linii **noi** (`id_vanzare_det = 0`) - semn ca liniile vechi au
|
|
deja o valoare de incredere, mostenita din stoc, si nu trebuie rescrisa manual dupa fapt (ar
|
|
strica marja/COGS calculat la vremea vanzarii). E o garda de **integritate financiara pe o
|
|
valoare derivata**, nu una generica de editare.
|
|
|
|
`serie`/`lot`/`explicatie` sunt campuri **descriptive/text**, nu valori derivate din stoc -
|
|
corectarea unei greseli de tastare pe o linie deja salvata (serie gresita, lot gresit, o
|
|
explicatie de corectat) e exact scenariul uzual de folosit al acestei livrari, inclusiv pe linii
|
|
vechi. Recomand garda de baza (fara conditia `id_vanzare_det`) pentru toate trei. Daca exista un
|
|
motiv de trasabilitate (serie/lot leaga factura de un lot fizic expediat, iar schimbarea lui dupa
|
|
livrare ar fi o problema de conformitate) - e o decizie de business, nu una pe care o pot confirma
|
|
din cod; semnalez-o explicit ca punct de validat cu tine inainte de aplicare.
|
|
|
|
### Propunere - `omodificari.vc2`, dupa `cPretArt.Text1.Valid` (`:16759`, inainte de
|
|
`cPretArt.Text1.When`)
|
|
|
|
```foxpro
|
|
PROCEDURE pgfArticole.PAGE3.grdArticoleFactura.cSerieArt.Text1.When
|
|
IF Thisform.lArticoleReadOnly OR Nvl(tvd.id_vanzare_set,0) <> 0
|
|
RETURN .F.
|
|
ENDIF
|
|
Thisform.oldvalue = This.Value
|
|
ENDPROC
|
|
|
|
PROCEDURE pgfArticole.PAGE3.grdArticoleFactura.cSerieArt.Text1.Valid
|
|
IF NVL(Thisform.oldvalue,'') <> NVL(This.Value,'')
|
|
REPLACE lmodificat WITH .T. IN tvd
|
|
Thisform.oldvalue = This.Value
|
|
ENDIF
|
|
ENDPROC
|
|
```
|
|
|
|
Identic (nume schimbat) pentru `cLotArt` (`tvd.lot`) si `cExplicatieArt` (`tvd.explicatie`).
|
|
Coloana 3 din `Column3.ReadOnly = .T.`, 4 din `Column4.ReadOnly = .T.`, 13 din
|
|
`Column13.ReadOnly = .T.` trec pe `.F.` (`omodificari.vc2:12365`, `:12372`, `:12447`).
|
|
|
|
---
|
|
|
|
## 3. Cazul delicat: `proc_tvav` (Column9, `cProcTvavArt`)
|
|
|
|
### 3.1 Forma stocata - VERIFICAT, nu presupus
|
|
|
|
`tvd.proc_tvav` e in forma multiplicativa (1.21, nu 21), confirmat in trei locuri independente:
|
|
|
|
- `CreeazaPoArticolNouTvd`... `calculeaza_valori_articol` (`omodificari.vc2:13511-13521`):
|
|
`lnProcTvav = NVL(proc_tvav, 1)` si `lnValoare = ... * lnPretNet * lnProcTvav` - daca ar fi
|
|
forma "21", valoarea liniei ar fi de 21x mai mare, evident gresit.
|
|
ei
|
|
- `ArticoleNotaEditor.ModificaNomenclator`, ramura `id_jtva_coloana`
|
|
(`ofacturare_editare.prg:1099-1101`): `proc_tvav WITH (Nvl(loCauta.cota_tva, 0) + 100) / 100` -
|
|
`cota_tva` vine din nomenclator ca "21", transformarea explicita in "1.21" e in cod.
|
|
- `CautaExplicatieTva` (`ofacturare_editare.prg:1117-1120`):
|
|
`lnCotaFiltru = Round((Nvl(tvd.proc_tvav, 0) - 1) * 100, 2)` - transformarea inversa, "1.21" ->
|
|
"21".
|
|
|
|
### 3.2 Precedent direct in acelasi grid family: editare libera in forma "1.xx"
|
|
|
|
**VERIFICAT.** Coloana `cProc_tva` de pe grila de rulaje (`pgfArticole.PAGE1.grdRulaje`,
|
|
`omodificari.vc2:8956-8963`, si dubletul ei pe `PAGE2.grdRulajeObinv`) e **deja editabila
|
|
direct**, in forma bruta:
|
|
|
|
```foxpro
|
|
Column24.ControlSource = "proc_tva", ;
|
|
Column24.Format = "R", ;
|
|
Column24.InputMask = "9.99", ;
|
|
Column24.Name = "cProc_tva", ;
|
|
Column24.ReadOnly = .F., ;
|
|
```
|
|
|
|
cu evenimentul (`omodificari.vc2:16337-16343`):
|
|
|
|
```foxpro
|
|
PROCEDURE pgfArticole.PAGE1.grdRulaje.cProc_tva.Text1.Valid
|
|
IF NVL(thisform.oldvalue, 0) <> NVL(this.Value, 0)
|
|
Thisform.calculeaza_valori_rul(this.ControlSource)
|
|
thisform.oldvalue = this.Value
|
|
ENDIF
|
|
ENDPROC
|
|
```
|
|
|
|
Utilizatorul tasteaza deja "1.21", nu "21", pe grila de rulaje din **acelasi formular**.
|
|
`cProcTvavArt` de pe grila de articole are deja azi `Column9.InputMask = "9.99"`
|
|
(`omodificari.vc2:12417`, mostenit inca de cand coloana era doar de afisare) - acelasi format,
|
|
gata pregatit.
|
|
|
|
### 3.3 Recomandare: pastreaza forma "1.21", nu converti la "21"
|
|
|
|
**Argument**: forma "1.21" e cea stocata in `proc_tvav`, cea folosita direct de
|
|
`calculeaza_valori_articol`, si cea deja tastata de utilizatori pe grila de rulaje din acelasi
|
|
formular - e conventia existenta, nu una noua. Varianta "utilizatorul tasteaza 21" ar cere:
|
|
|
|
- o proprietate ajutatoare separata pe care sa se afiseze/editeze (`Text1` legat printr-o
|
|
expresie de transformare, `ControlSource` nu mai poate fi direct `tvd.proc_tvav`), pentru ca
|
|
grid column text boxes nu pot face transformarea la afisare fara sa piarda editarea directa pe
|
|
`ControlSource`;
|
|
- conversia dus-intors (`/100+1` la citire, `(x-1)*100` la scriere) e exact riscul semnalat -
|
|
o greseala de semn sau de ordine ar strica toate liniile la urmatoarea recalculare, silentios
|
|
(nu exista validare care sa prinda "1900" in loc de "19" introdus gresit);
|
|
- ar fi **singura** coloana din tot formularul cu conventia asta, cand exact aceeasi valoare, pe
|
|
aceeasi pagina, la un tab distanta (rulaje), se editeaza deja in forma "1.21".
|
|
|
|
Nu recomand conversia. Ramane `InputMask = "9.99"`, neschimbat.
|
|
|
|
### 3.4 Riscul real: corelarea cu `id_jtva_coloana`/`taxcode` se poate dezincroniza
|
|
|
|
**VERIFICAT ca risc, nu ca deja tratat.** Spre deosebire de `cProc_tva` de pe rulaje (unde
|
|
`trul` nu are corelare SAF-T de taxcode legata de cota), pe `tvd` cota TVA e legata explicit de
|
|
`id_jtva_coloana` si de `taxcode`:
|
|
|
|
- `ModificaNomenclator`, ramura `id_jtva_coloana` (`ofacturare_editare.prg:1099-1104`): alegerea
|
|
unei explicatii TVA scrie **impreuna** `id_jtva_coloana` si `proc_tvav`, apoi cheama
|
|
`UpdateExplicatieSAFTArt()` care recoreleaza `taxcode` din `id_jtva_coloana`
|
|
(`omodificari.vc2:15049-15073`, verificat: `lnIdJtva = tvd.id_jtva_coloana`,
|
|
`GetTaxCodeIdPart(...)`, `Replace taxcode With m.lnTaxCode In tvd`).
|
|
- Daca utilizatorul editeaza `proc_tvav` direct (tasteaza "1.19" peste "1.21"), fara sa treaca si
|
|
prin nomenclatorul de explicatie TVA, **`id_jtva_coloana` si `taxcode` raman la cota veche** -
|
|
`cExplicatieTvaArt` (coloana 16) ar continua sa arate explicatia de 21% langa o cota de 19%, iar
|
|
`taxcode`-ul folosit la raportarea SAF-T ar fi cel corelat cu explicatia gresita. E o
|
|
inconsistenta silentioasa, nu doar cosmetica - `taxcode` alimenteaza raportarea SAF-T 406.
|
|
|
|
Pe grila de rulaje, editarea directa a lui `proc_tva`/`proc_tvav` **nu recoreleaza nimic** legat
|
|
de TVA (`trul` nu poarta `taxcode`/`id_jtva_coloana` in acelasi fel) - acolo riscul asta nu
|
|
exista, deci precedentul de la 3.2 nu acopera si problema asta.
|
|
|
|
### 3.5 Doua variante, cu recomandare
|
|
|
|
**Varianta A (recomandata) - blocheaza corelarea veche in loc s-o lase gresita**
|
|
|
|
```foxpro
|
|
PROCEDURE pgfArticole.PAGE3.grdArticoleFactura.cProcTvavArt.Text1.When
|
|
IF Thisform.lArticoleReadOnly OR Nvl(tvd.id_vanzare_set,0) <> 0
|
|
RETURN .F.
|
|
ENDIF
|
|
Thisform.oldvalue = This.Value
|
|
ENDPROC
|
|
|
|
PROCEDURE pgfArticole.PAGE3.grdArticoleFactura.cProcTvavArt.Text1.Valid
|
|
IF NVL(Thisform.oldvalue, 0) <> NVL(This.Value, 0)
|
|
SELECT tvd
|
|
REPLACE id_jtva_coloana WITH NULL, taxcode WITH NULL
|
|
Thisform.calculeaza_valori_articol()
|
|
Thisform.oldvalue = This.Value
|
|
This.Parent.Parent.Refresh()
|
|
ENDIF
|
|
ENDPROC
|
|
```
|
|
|
|
Dupa editare manuala a cotei, `cExplicatieTvaArt` si `cTaxcodeArt` raman **goale** pe randul
|
|
respectiv - semnal vizibil, imediat, ca utilizatorul trebuie sa aleaga din nou explicatia TVA
|
|
(punctul 4 de mai jos ii da exact calea: click sau tastare pe coloana Explicatie TVA deschide
|
|
dialogul, filtrat deja pe noua cota introdusa). `taxcode WITH NULL` inseamna insa ca linia nu mai
|
|
are cod SAF-T pana la re-alegere - de verificat cu tine daca exista vreo validare la salvare care
|
|
sa avertizeze pe `taxcode` nul (nu am gasit una explicita pentru `tvd`, doar cea de pret de
|
|
achizitie 0 de la `:14457`); daca nu exista, merita adaugata odata cu asta, ca sa nu scape o
|
|
factura fara cod SAF-T la salvare.
|
|
|
|
**Varianta B (respinsa) - lasa corelarea veche neatinsa, ca pe rulaje**
|
|
|
|
Doar `Thisform.calculeaza_valori_articol()` in `Valid`, fara sa atinga
|
|
`id_jtva_coloana`/`taxcode`. Simetrica cu precedentul de la 3.2, dar pe `tvd` inseamna taxcode
|
|
SAF-T incorect ramas silentios dupa o editare manuala de cota - risc pe raportare fiscala, nu doar
|
|
UX. Nu o recomand.
|
|
|
|
**Nu am incercat o a treia varianta ("re-coreleaza automat")** - ar insemna sa caut in
|
|
`crsJtvaTemp` o explicatie care sa aiba exact noua cota si sa o aplic fara dialog; las-o
|
|
deoparte pentru ca poate exista mai mult de o explicatie pe aceeasi cota (JC vs JV, exigibil vs
|
|
neexigibil - vezi parametrii `tlTipEx` din `caut_explicatie_tva`,
|
|
`ocautare.prg:3174-3181`), iar alegerea automata a uneia ar fi arbitrara exact acolo unde conteaza
|
|
sa fie corecta.
|
|
|
|
---
|
|
|
|
## 4. Nomenclatoarele pe `InteractiveChange`
|
|
|
|
**VERIFICAT** - sablonul de referinta indicat de tine (`Grid1.Column15/16/17` pe grila de note,
|
|
`omodificari.vc2:5890-5940`) e construit pe **`do_modifica`** generic (parametri `pcx_item`,
|
|
`pccontrol`, `pnid_item`, cautare in cursorul `xitems`) - un mecanism diferit fata de
|
|
`ArticoleNotaEditor.ModificaNomenclator`, care primeste **doar `pccontrol`** si decide singur ce
|
|
cautare deschide printr-un `DO CASE` pe numele campului
|
|
(`ofacturare_editare.prg:1073-1090`). **Sablonul se preia doar partial**: pattern-ul
|
|
`GotFocus` seteaza `pccontrol`+`pncolumnorder`, `InteractiveChange` cheama dialogul - dar apelul e
|
|
catre `ArticoleNotaEditor.ModificaNomenclator(pccontrol)`, fara `pcx_item`/`pnid_item` (nu exista
|
|
in semnatura ei).
|
|
|
|
Cele 5 coloane cu nomenclator (`AreNomenclator`, `ofacturare_editare.prg:1004-1007`:
|
|
`'denumire', 'nume_gestiune', 'nume_val', 'taxcode', 'id_jtva_coloana'`) au deja `Text1.GotFocus`
|
|
care seteaza `pccontrol`+`pncolumnorder` (`omodificari.vc2:16700-16704` `cDenumireArt`,
|
|
`:16723-16727` `cExplicatieTvaArt` cu `pccontrol` explicit `'tvd.id_jtva_coloana'` pentru ca
|
|
`ControlSource` e o expresie, `:16729-16733` `cGestiuneArt`, `:16750-16754` `cTaxcodeArt`,
|
|
`:16755-16759` `cValutaArt`) - functioneaza deja azi desi coloanele sunt `ReadOnly = .T.` (un
|
|
textbox readonly primeste `GotFocus` la navigare cu sagetile, doar nu accepta tastare). Asta e
|
|
mecanismul care tine `But_modificaR` sincronizat cu coloana curenta (punctul 5).
|
|
|
|
### Propunere - adauga `Text1.InteractiveChange` pe fiecare, `ReadOnly` -> `.F.`
|
|
|
|
```foxpro
|
|
PROCEDURE pgfArticole.PAGE3.grdArticoleFactura.cDenumireArt.Text1.InteractiveChange
|
|
LOCAL loEditor
|
|
loEditor = Createobject('ArticoleNotaEditor', Thisform)
|
|
loEditor.ModificaNomenclator(Thisform.pccontrol)
|
|
ENDPROC
|
|
```
|
|
|
|
Identic (nume schimbat) pentru `cGestiuneArt`, `cValutaArt`, `cTaxcodeArt`, `cExplicatieTvaArt` -
|
|
`Thisform.pccontrol` e deja setat corect de `GotFocus`-ul existent al fiecareia. `Column1.ReadOnly`
|
|
(`:12354`), `Column11.ReadOnly` (`:12428`), `Column12.ReadOnly` (`:12434`), `Column14.ReadOnly`
|
|
(`:12453`), `Column16.ReadOnly` (`:12474`) trec pe `.F.`.
|
|
|
|
### Risc: caracterul tastat inainte de deschiderea dialogului
|
|
|
|
**VERIFICAT ca exista deja acelasi risc, neremediat, in sablonul citat.** In `do_modifica`
|
|
(`omodificari.vc2:13960` si dublurile ei), `REPLACE`-ul cu valoarea aleasa se face **doar** in
|
|
ramura `IF gnButon = 1` (`omodificari.vc2:14019-14025` pentru `tact`) - la anulare (`gnButon <> 1`
|
|
sau formular inchis fara alegere), campul **nu e restaurat**. Cum coloana e `ReadOnly = .F.`,
|
|
`InteractiveChange` se declanseaza pe **prima tasta** apasata (Value s-a schimbat deja cu acel
|
|
caracter inainte ca evenimentul sa ruleze) - daca utilizatorul apasa o litera si apoi renunta la
|
|
dialog, acel caracter ramane in camp.
|
|
|
|
Pe `ArticoleNotaEditor.ModificaNomenclator` e identic: `REPLACE`-ul final
|
|
(`ofacturare_editare.prg:1093-1107`) e dupa `IF gnButon <> 1: RETURN .F. ENDIF`
|
|
(`:1082-1084`) - la anulare, campul nu se atinge, deci caracterul parazit ramane in `tvd.denumire`
|
|
(sau alt camp editat). Fara refresh explicit pe ramura de anulare (`RefreshGrid()` e apelat doar
|
|
dupa `REPLACE`, in afara ramurii de `RETURN` timpuriu), gridul ramane cu textul modificat vizual
|
|
pana la urmatoarea reimprospatare.
|
|
|
|
**Nota:** `lmodificat` nu se atinge pe ramura de anulare, dar cum am aratat la punctul 0, asta nu
|
|
opreste totusi salvarea - daca linia era oricum activa (`sters<>1`), caracterul parazit ar fi
|
|
scris in Oracle la urmatoarea salvare a documentului, indiferent de `lmodificat`.
|
|
|
|
**Propunere de atenuare (in plus fata de sablon, nu cerinta din brief):** in
|
|
`ArticoleNotaEditor.ModificaNomenclator`, muta `This.RefreshGrid()` inainte de
|
|
`RETURN .F.` din garda de anulare, ca sa readuca vizual valoarea corecta din cursor peste orice
|
|
caracter tastat:
|
|
|
|
```foxpro
|
|
IF gnButon <> 1
|
|
This.RefreshGrid()
|
|
RETURN .F.
|
|
ENDIF
|
|
```
|
|
|
|
`RefreshGrid()` doar re-deseneaza gridul din cursor (`This.oForm.pgfArticole.PAGE3.grdArticoleFactura.Refresh()`,
|
|
`ofacturare_editare.prg:1136-1138`) - nu scrie nimic, deci sigur de adaugat si pe ramura de
|
|
anulare. Nu rezolva 100% (daca utilizatorul apasa doua taste rapid inainte ca dialogul sa apuce sa
|
|
se deschida, a doua tasta tot ar intra), dar acopera cazul uzual (o tasta, apoi Esc pe dialog).
|
|
|
|
`But_modificaR` ramane functional neschimbat: click-ul lui cheama tot
|
|
`ArticoleNotaEditor.ModificaNomenclator(thisform.pccontrol)` (`omodificari.vc2:15319-15322`,
|
|
verificat), acelasi `pccontrol` pe care acum si `InteractiveChange`-ul il foloseste - **nu se
|
|
dubleaza deschiderea dialogului**, sunt doua declansatoare catre aceeasi metoda, niciodata
|
|
concurente (butonul se apasa explicit, `InteractiveChange` doar la tastare in celula).
|
|
|
|
---
|
|
|
|
## 5. `BeforeRowColChange`/`AfterRowColChange` - raman neschimbate
|
|
|
|
**VERIFICAT.**
|
|
|
|
```foxpro
|
|
PROCEDURE pgfArticole.PAGE3.grdArticoleFactura.AfterRowColChange
|
|
Lparameters nColIndex
|
|
DODEFAULT(m.nColIndex)
|
|
Thisform.but_modificaR.Enabled = (Thisform.pncolumnorder = m.nColIndex) AND !Thisform.lArticoleReadOnly
|
|
ENDPROC
|
|
|
|
PROCEDURE pgfArticole.PAGE3.grdArticoleFactura.BeforeRowColChange
|
|
LPARAMETERS nColIndex
|
|
IF Thisform.pncolumnorder # m.nColIndex
|
|
STORE [] TO Thisform.pccontrol
|
|
ENDIF
|
|
ENDPROC
|
|
```
|
|
|
|
Nu au nevoie de nicio schimbare:
|
|
|
|
- Coloanele cu nomenclator continua sa seteze `pncolumnorder` in `GotFocus` (neschimbat la
|
|
punctul 4) - `But_modificaR` ramane activat/dezactivat exact ca azi.
|
|
- Coloanele noi editabile fara nomenclator (`cSerieArt`, `cLotArt`, `cExplicatieArt`,
|
|
`cProcTvavArt`) **nu primesc `GotFocus` care sa seteze `pccontrol`/`pncolumnorder`** - la fel ca
|
|
`cCantitateArt`/`cPretArt`/`cPretAchizitieArt` azi (verificat: niciuna dintre astea trei nu are
|
|
`Text1.GotFocus` in intervalul `:16678-16770`). Cand utilizatorul navigheaza pe una din ele,
|
|
`pncolumnorder` ramane la valoarea din ultima coloana cu nomenclator vizitata, deci
|
|
`Thisform.pncolumnorder = m.nColIndex` e fals si `But_modificaR` ramane dezactivat - corect,
|
|
pentru ca aceste patru coloane n-au nomenclator si nu trebuie sa activeze butonul.
|
|
|
|
Nu propun sa le adaug `GotFocus` - ar activa gresit `But_modificaR` pe coloane fara cautare.
|
|
|
|
---
|
|
|
|
## 6. Ordinea coloanelor - doar de retinut, nu de aplicat acum
|
|
|
|
`cExplicatieTvaArt` (Column16) e ultima coloana din grid, dupa `cValoareArt` (Column15) -
|
|
`ColumnOrder`-ul azi urmeaza indicii (1-16). Mutarea ei langa `cTaxcodeArt` (Column14) ar cere
|
|
renumerotarea `ColumnOrder` pe toate cele 16 coloane (nu doar schimbarea pozitiei uneia), cost
|
|
deja notat in `docs\propunere_runda4_note_sincronizare_tva.md:242-244`. Ramane a doua iteratie,
|
|
separata de livrarea asta.
|
|
|
|
---
|
|
|
|
## Rezumat - ce e usor, ce e delicat
|
|
|
|
**Usor, cu incredere mare:**
|
|
- `serie`/`lot`/`explicatie` editabile inline (punctul 2) - tipar identic cu `cPretArt`, fara
|
|
recalcul necesar.
|
|
- UPDATE-ul din `ScrieArticoleFacturaEditate` (punctul 1) - trei linii, tipar deja folosit alaturi
|
|
(`cont` pe acelasi UPDATE, `serie`/`lot`/`explicatie` pe INSERT-ul de doua ori mai jos).
|
|
- Nomenclatoarele pe `InteractiveChange` (punctul 4) - `GotFocus` deja exista pe toate cele 5
|
|
coloane, doar `ReadOnly` si `InteractiveChange` lipsesc.
|
|
- `BeforeRowColChange`/`AfterRowColChange` (punctul 5) - zero schimbari, verificat ca raman
|
|
corecte.
|
|
|
|
**Delicat, cere o decizie a ta inainte de aplicare:**
|
|
- `proc_tvav` (punctul 3) - forma "1.21" e clar cea corecta de pastrat (precedent direct pe
|
|
aceeasi pagina, la rulaje), dar corelarea cu `id_jtva_coloana`/`taxcode` la editare manuala e un
|
|
risc real de raportare SAF-T netratat de niciun precedent existent. Recomand Varianta A
|
|
(goleste corelarea, forteaza re-alegere) - confirma daca vrei asta sau preferi sa nu atingi
|
|
`id_jtva_coloana`/`taxcode` deloc (Varianta B, mai simpla dar cu riscul asumat).
|
|
- Garda de editare pe `serie`/`lot`/`explicatie` - am recomandat garda de baza (fara restrictia
|
|
`id_vanzare_det<>0` de la pret de achizitie), dar e o decizie de business (trasabilitate lot pe
|
|
linii deja livrate), nu una pe care am putut-o confirma din cod.
|
|
- Riscul caracterului parazit la deschiderea nomenclatorului pe `InteractiveChange` (punctul 4) -
|
|
exista deja, neremediat, in sablonul `do_modifica` de pe grila de note; am propus o atenuare de
|
|
o linie (`RefreshGrid()` pe ramura de anulare) care nu era in cerinta ta, spune daca o vrei in
|
|
livrare sau ramane pentru alta runda.
|