# 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.