Files
roafacturare/docs/cercetare/rec_s1_s3_intrare_editare.md
Marius Mutu d9f5ca4226 docs: planurile, proiectarile si rapoartele de lucru intra in versionare
Folderul docs\ era pana acum in afara oricarui control de versiuni - nici git,
nici SVN - desi contine planurile pe puncte, proiectarile si rapoartele de
cercetare pe care se sprijina modificarile din cod. O stergere acolo era
definitiva.

Fisierele intermediare (handoff-uri intre sesiuni, diff-uri deja aplicate) au
fost sterse inainte, nu versionate: ce era durabil in ele a intrat in antetele
fisierelor de test la care se refereau.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
2026-08-11 22:17:17 +03:00

447 lines
26 KiB
Markdown

# Cercetare S1-S3 (plan_06_editare_factura.md) - stare cod la 08.08.2026
Refera ancorele planului dupa commit-urile #7/#8. Toate liniile de mai jos sunt din textul
`.vc2` regenerat de `git_sync.ps1` in aceasta sesiune (deci la zi cu binarul).
## A. Ancore re-verificate
### A1. frm_facturi.do_sterge - COMUN\clase\ofacturare_comun.vc2:4501-4717
Clasa `frm_facturi` incepe la `ofacturare_comun.vc2:1168` (mosteneste `_frmbase`). Metoda
`do_sterge` e imediat dupa `do_modifica_explicatie` (4482-4499) si inainte de `do_verifica`
(4719-4766). Structura pe pasi:
1. `4502-4508`: citeste `gnLuna`/`gnAn` in variabile, iese daca `crsfacturi` e gol.
2. `4516-4518`: garda **luna inchisa** (`glLunaInchisa`) - `Return` fara mesaj.
3. `4520-4527`: pozitioneaza pe randul curent din `crsfacturi`, citeste `id_vanzare`, `cod`,
an/luna din `data_act`, `sters`, `eproforma`.
4. `4529-4536`: daca deja sters -> mesaj si `Return`; confirmare cu `amessagebox(...,4+32,...)`.
5. `4541-4544`: garda **luna curenta** - `(pnAn*12)+pnLuna <> (gnAn*12)+gnLuna` -> mesaj si
`Return`.
6. `4546-4559`: ramura separata **STERGERE PROFORMA** (`eproforma=1`) - apeleaza direct
`pack_facturare.sterge_proforma(pnIdVanzare,gnIdUtil)` si iese cu `RETURN`, **inainte** de
garda de referinte de mai jos. Facturile/avizele nu intra pe aceasta ramura.
7. `4562-4567`: garda **referinte incasari/plati** -
`ReferinteDocumenteNota(pnAn, pnLuna, lnCod)` (definita in
`COMUN\programe\odocumente.prg:8`) -> daca `.T.`, mesaj si `Return`.
8. `4569-4614`: incarca cursoare pe `cod` din `vact_tot`/`vrul_tot`/`vrul_obinv_tot` (schema
`gcs`), filtrate `sters=0 and an=gnAn and luna=gnLuna and cod=lnCod`, in `actactan`/
`rul_temp`/`rul_temp_obinv`.
9. `4617-4620`: daca sunt randuri in `actactan`, deschide formularul modal `verificare`
(confirmare vizuala inainte de stergere efectiva).
10. `4622-4685`: daca `buton=1` din `verificare`, trece manual pe tranzactie
(`SQLSetprop(gnhandle,"Transactions",2)`), apeleaza `OSCRIE_IN_FISIERE(2,.F.,llRul)`, apoi
`pack_contafin.finalizeaza_stergere_nota(pnLuna,pnAn,Null,lnIdSet,lnCod,lnIdFact,lnIdFactD,
gnIdUtil)`, COMMIT/ROLLBACK dupa rezultat, revine pe tranzactie automata.
11. `4686-4701`: ramura alternativa (fara randuri in `actactan`, adica document fara nota) -
apel direct `pack_facturare.sterge_factura(pnIdVanzare,gnLuna,gnAn,gnIdUtil)`.
12. `4707-4716`: inchide cursoarele temporare.
**Nu exista nicio verificare eFactura in do_sterge** - vezi A3, e o corectie fata de plan.
### A2. Cele 3 garzi lipsa din do_modifica - confirmate, linii curente
Toate trei sunt in `do_sterge` (A1) si lipsesc din `do_modifica` (`ofacturare_comun.vc2:4381-4480`,
care nu verifica deloc luna sau referinte, doar `sters`+eFactura, vezi A3):
- **Luna inchisa**, `ofacturare_comun.vc2:4516-4518`:
```
If glLunaInchisa
Return
Endif
```
- **Luna curenta**, `ofacturare_comun.vc2:4541-4544`:
```
If (pnAn * 12) + pnLuna <> (gnAn * 12) + gnLuna
amessagebox('Nu puteti sterge decat inregistrari din luna curenta!',0,'Atentie!')
Return
Endif
```
Text hardcodat pe "stergere" - la reutilizare pentru editare trebuie schimbat mesajul.
- **Referinte incasari/plati**, `ofacturare_comun.vc2:4562-4567`:
```
*** verificare restrictie stergere documente cu referinte (incasari/plati)
llReferinteDocumente = ReferinteDocumenteNota(pnAn, pnLuna, lnCod) && && odocumente.prg
If llReferinteDocumente
amessagebox("Documentul are referinte (incasari/plati). Nu poate fi sters.", 0+48,"Stergere")
Return
Endif
```
Idem, mesajul e specific stergerii.
### A3. Garda eFactura - CORECTIE fata de plan: e in do_modifica, NU in do_sterge
Cautare exhaustiva `anaf_efactura` in `ofacturare_comun.vc2`: **o singura aparitie**, la linia
4426, in interiorul lui `do_modifica` (4381-4480). `do_sterge` nu contine deloc `anaf_efactura`.
Cod exact, `ofacturare_comun.vc2:4426-4430`:
```
lcSql = [select count(*) as lneFactura from anaf_efactura where id_fact = ] + ALLTRIM(STR(poRec.id_fact))
pneFactura = 0
llSucces = goExecutor.oSelecteaza2Value(m.lcSql, @pneFactura)
If poRec.sters = 0 AND NVL(m.pnEFactura,0) = 0
```
(`pneFactura`/`pnEFactura` e aceeasi variabila, VFP e case-insensitive.)
Garda e refolosibila ca atare (interogare + conditie), dar trebuie extrasa dintr-un `If` care
astazi conditioneaza doar deschiderea dialogului `frm_modifica_factura` - pentru actiunea noua
S1 trebuie sa devina un `Return` explicit cu mesaj, dupa modelul celorlalte garzi din
`do_sterge`, nu o simpla conditie de `If`.
### A4. Mecanismul de drepturi pe frm_facturi
Nu exista o proprietate `lactiv3`/`lactiv4` setata explicit in `ofacturare_comun.vc2` - ele sunt
proprietati generice mostenite din `_frmbase` (`_frm_base.vc2:7`), populate dinamic din
`gcAcces` de metoda comuna `actualizeaza_drepturi`, `_frm_base.vc2:195-228`:
- Format `gcAcces = "opt1;opt2;...;optN;"` (string cu numere separate prin `;`).
- Pentru fiecare token `N` prezent, seteaza `thisform.lactivN = .T.` (linia 203-205:
`lcProp='thisform.lactiv'+Alltrim(lcAcces)` + `&lcProp=.T.`).
- Daca exista si o proprietate `thisform.cbutonN` (lista de nume de butoane separate prin `;`),
seteaza `.Visible = .T.` pe fiecare buton din lista (206-221).
Uzul din `inainte_de_do_modifica`/`inainte_de_do_sterge` (`_frm_base.vc2:476-481, 493-498`):
`If This.lactiv3 Then This.do_modifica()` / `If This.lactiv4 Then This.do_sterge()`. Deci
`lactivN` gateaza EXECUTIA actiunii, `cbutonN` gateaza VIZIBILITATEA butoanelor asociate.
**Tokenii folositi azi de frm_facturi** (proprietati proprii clasei, `ofacturare_comun.vc2:1352-1353`):
- `cbuton2 = but_listare1;but_listare2;But_listare3` (token "2" = listare)
- `cbuton3 = but_modifica1;but_modifica2` (token "3" = modificare - **ambele** butoane de
modificare, cel de antet si cel de explicatie articol, vezi A5)
- Tokenul "4" (stergere) nu are `cbuton4` definit pe `frm_facturi` - vizibilitatea lui
`but_sterge1` e gestionata separat, direct in `Init` (`4770-4773`): daca `glLunaInchisa`,
scoate manual `"4;"` din `gcAcces` si ascunde butonul. `lactiv4` insa tot se seteaza normal
din `gcAcces` (prin mecanismul generic), si `but_sterge1.Click` foloseste implicit
`caction = inainte_de_do_sterge` (default din clasa de baza `but_modifica`/`but_sterge`,
`cmd_butoane.vc2:358`), care verifica `This.lactiv4`.
- Tokenul "1" nu e folosit de `frm_facturi` (fara `cbuton1`) - liber pentru o semnificatie noua
daca s-ar dori, dar mai curat e un token nou (ex. "5").
**Sursa lui `gcAcces`**: variabila globala PUBLIC (comentariul `*:Global gcAcces`,
`ofacturare_comun.vc2:4770`), NU e setata in codul lui `frm_facturi` sau in procedura care il
deschide (`COMUN\programe\oproceduri_facturare.prg:416, 505` - `Createobject("frm_facturi")`
fara nicio atribuire de `gcAcces` inainte). E populata inainte, la click pe iconita de pe
ecranul-fundal (`ofundal.vc2:69,186,311,391` - `gcAcces = This.coptiuni_active`), unde
`coptiuni_active` per iconita vine din `dezactiveaza_imagini` (`COMUN\programe\acces_meniu.prg:39-80`),
care citeste central din view-ul Oracle `contafin_oracle.vdef_util_obiecte` (interogat in
`citeste_drepturi`, `acces_meniu.prg:17-37`, filtrat pe `id_util`/`id_program`/`id_firma`) si
mapeaza pe cheia iconitei (`cheie`) ultima cifra la un token numeric. Editarea drepturilor per
grup se face prin `PACK_DREPTURI.grupdreptmodproc` (`COMUN\clase\drept_grupuri.vc2:39`, apelat
din `frm_grupuri`).
**Nu am gasit** un catalog central editabil in VFP care sa enumere sensul fiecarui token numeric
per program (ex. un tabel `optiuni_program` cu eticheta "3 = modificare"). Sensul e o conventie
fixata in cod (proprietatile `cbutonN` din fiecare clasa de formular) - vezi intrebarea D2.
### A5. frm_facturi.do_modifica - CORECTIE fata de descrierea din task/plan
**Contrar formularii din plan_06 ("butonul existent din frm_facturi deschide
frm_modifica_articol_factura, care editeaza doar explicatie si taxcode")**, in codul de azi
exista DOUA actiuni distincte de "modificare" pe `frm_facturi`, ambele gateate de acelasi token
"3" (`cbuton3`), dar cu efecte diferite:
1. **`do_modifica`** (`ofacturare_comun.vc2:4381-4480`), legata de `but_modifica1` (butonul din
bara de sus, `Left=609`, fara `caction` explicit -> foloseste default-ul din clasa de baza
`but_modifica` = `caction = inainte_de_do_modifica` -> `This.lactiv3` -> `do_modifica()`).
Deschide **`frm_modifica_factura`** (antet document) si, la `gnButon=1`, ruleaza
`pack_facturare.modifica_date_factura(...)` pe UNA sau MAI MULTE facturi (dupa selectie
multipla `ales=1`) cu campurile: `id_ruta`, `id_delegat`, `id_agent`, `id_masina`,
`dataora_exp`, `id_facturare`, `listare_detaliata`, `text_aditional`, `tip_saft`,
`efactura`(flag intentie trimitere), `data_act`, `data_scad`, `numar_act`, `serie_act`.
**Niciun camp de suma/cantitate/pret.** Contine garda eFactura (A3).
2. **`do_modifica_explicatie`** (`ofacturare_comun.vc2:4482-4499`), legata de `But_modifica2`
(langa grid-ul de detalii, `caction = do_modifica_explicatie` explicit,
`ofacturare_comun.vc2:1433-1441`, tooltip "Modificare explicatie articol"). Deschide
**`frm_modifica_articol_factura`** (`ofacturare_comun.vc2:4959`, caption "Modifica explicatie
articol"), care editeaza DOAR `explicatie` (memo) si `taxcode` (combo SAFT) pe linia curenta
din `crsDetalii`. Garda: doar `poRec.sters = 0` - **fara verificare eFactura**.
Deci descrierea corecta pentru plan: actiunea care deschide `frm_modifica_articol_factura` e
`do_modifica_explicatie` (nu `do_modifica`), iar niciuna din cele doua actiuni existente nu
atinge sume/cantitati - confirma nevoia unei actiuni noi (S1), dar sablonul de clonat pentru
garzi ramane `do_sterge`, nu vreuna din cele doua `do_modifica*`.
### A6. afisjurcom.do_modifica - COMUN\clase\comun.vc2:2222-2563
Clasa `afisjurcom` (extinde `_frmbase`). Pasi:
1. `2230-2232`: `If !Thisform.lactiv3 Then Return` (acelasi mecanism de drept ca A4).
2. `2238-2240`: garda luna inchisa (`glLunaInchisa`).
3. `2242-2258`: determina daca se arata si randurile sterse (`lleSters`, dupa filtrul curent),
citeste `cod`/`an`/`luna`/`id_set`/`sters`/`id_fact`/`id_factd` din `actjur`.
4. `2265-2268`: garda luna curenta - **acelasi tipar** ca in `do_sterge`:
`(pnAn*12)+pnLuna <> (gnAn*12)+gnLuna` -> mesaj -> `Return`.
5. `2278-2281`: garda suplimentara - `id_set` intre 30000-30009 (note din ROAPRODUCTIE) ->
blocate necontional.
6. `2313-2332`: inchide cursoarele reziduale `actactan`/`tact`/`rul_temp`/`trul`/
`rul_temp_obinv`/`trul_obinv` daca sunt deschise.
7. `2352-2368`: incarca `vact_tot` in `actactan` -> `tact` (READWRITE), filtrat
`sters=0 and an=gnAn and luna=gnLuna and cod=lnCod` (daca nu se arata stersele) sau fara
filtrul de sters, ORDER BY `id_act`.
8. `2370-2427`: daca succes, incarca similar `vrul_tot` -> `rul_temp`/`trul` si
`vrul_obinv_tot` -> `rul_temp_obinv`/`trul_obinv`, cu recalcul de `valoare`/`valtva`/
`valoarev`/`valtvav` pe randurile goale (2383-2387, 2412-2416) inainte de a construi
`trul`/`trul_obinv`.
9. `2429-2442`: alege clasa de formular dupa an (`gnAn >= gnAnFormNou` implicit 2007) ->
**`frm_modific2024`** (`Createobject([frm_modific2024], lnIdSet)`) sau varianta veche
`frm_modific`; `Select tact` inainte de `Omodif.Show()`.
10. `2444-2538`: daca `buton=1`, deschide tranzactie manuala (`do_deschide_tranzactie`),
`oscrie_in_fisiere(2,.T.,llRul)`, reconstruieste `actactan`/`RUL_TEMP`/`RUL_TEMP_OBINV` din
`tact`/`trul`/`trul_obinv` cu `id_util`/`sters=0`, apoi `oscrie_in_fisiere(0,.T.,llRul)`,
apoi **`pack_contafin.finalizeaza_modificare_nota(pnLuna,pnAn,pdDataOra,lnIdSet,lnCod,
lnIdFact,lnIdfactd,gnIdUtil)`** (2484-2487), `do_inchide_tranzactie` si `do_cauta` la final.
11. Cod comentat (2496-2513, dezactivat) arata o incercare anterioara de a apela direct
`pack_facturare.actualizeaza_vanzari` din client dupa `finalizeaza_modificare_nota` - azi
e mort, apelul real se face DOAR server-side, in interiorul lui
`finalizeaza_modificare_nota` (confirma faptul deja stabilit in `progres.md`).
12. `llVanzari` e declarata (`Store .F.`, 2235) dar logica ei de activare e tot comentata
(2292-2307) - variabila ramane mereu `.F.`, deci sincronizarea cu `VANZARI` e complet
transparenta pentru `afisjurcom`, indiferent de tipul documentului.
### A7. frm_modific2024 - COMUN\clase\omodificari.vc2:6375-...
Clasa (`DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"`) incepe la linia 6375.
Metodele proprii merg de la `Activate` (12238) pana la ultimul handler de grid
(`pgfArticole.PAGE2.grdRulajeObinv.Init`, 15422-15424) - interval `12238-15424`, usor deplasat
fata de planul vechi (`12200-15319`).
**Contract de intrare** (`Init`, `13551-13660`):
```
Lparameters tnIdSet, tlNotaNoua, toBackupXML, toSet, tlVizualizare
```
- `tnIdSet`: id-ul setului de nota (obligatoriu, stocat in `This.nid_set`).
- `tlNotaNoua`: `.T.` daca vine din nota fara predefinire.
- `toBackupXML`, `toSet`: obiecte optionale (backup XML, respectiv setul de editare
restrictionata "doar Salveaza/Renunta" - `This.lEditare`).
- `tlVizualizare`: parametru opus, numeric sau logic - `1`/`.T.`=vizualizare, `2`=modificare
(default), `3`=verificare note (`13576-13591`).
- **Nu primeste cursoare ca parametru.** Formularul se leaga la aliasul curent `tact` (setat de
apelant cu `Select tact` inainte de `Createobject`) - grid-ul principal `Grid1` are
`RecordSource` legat implicit pe `tact` (conventie mostenita, nu vazuta explicit in Init, dar
confirmata de apelul din A6 pas 9). Grid-urile din pageframe au `RecordSource` FIX in
definitia clasei: `pgfArticole.PAGE1.grdRulaje.RecordSource = "trul"`
(`omodificari.vc2:8669`) si (dupa acelasi tipar, de verificat direct) `grdRulajeObinv` pe
`trul_obinv`. **Deci apelantul trebuie sa aiba deschise, cu exact aceste nume de alias,
cursoarele `tact`/`trul`/`trul_obinv` READWRITE inainte de instantiere** - exact ce face A6
pas 7-8.
- **Iesire**: `do_termin` nu e suprascrisa in `frm_modific2024` - foloseste default-ul din
`_frmbase` (`_frm_base.vc2:363-376`, seteaza `gnButon=1`/`Buton=1` si inchide/ascunde), dar
trece prin `inainte_de_do_termin` proprie, foarte lunga (`13357-13549`, ~192 linii) - acolo e
validarea grea (verificari de total, TVA exigibil etc.) inainte sa lase `buton=1`. **Orice
validare noua legata de sume factura trebuie sa intre in acest lant**, nu doar in `do_salvare`.
- **La iesire cu `buton=1`, cursoarele `tact`/`trul`/`trul_obinv` raman deschise** (formularul nu
le inchide) - apelantul (A6 pas 10) le reciteste in `actactan`/`RUL_TEMP`/`RUL_TEMP_OBINV`
dupa `Show()`.
**Pageframe existent** (`pgfArticole`, `omodificari.vc2:8627-8642`, doar 2 pagini azi):
```
PAGE1.Caption = "Rulaje materii prime, materiale, marfuri, obiecte inventar (303)" (grid grdRulaje pe trul)
PAGE2.Caption = "Rulaje obiecte inventar in folosinta (8039)" (grid grdRulajeObinv pe trul_obinv)
```
Nu exista azi PAGE3 - de adaugat pentru S4.
### A8. Butonul/actiunea in bara formularului si modelul de adaugare
Modelul concret (`But_modifica2`, `ofacturare_comun.vc2:1433-1441`):
```
ADD OBJECT 'But_modifica2' AS but_modifica WITH ;
Anchor = 12, ;
caction = do_modifica_explicatie, ;
Caption = "", ;
Left = 710, ;
Name = "But_modifica2", ;
TabIndex = 27, ;
ToolTipText = "Modificare explicatie articol", ;
Top = 341
```
Dispatch generic: `Click` din clasa de baza a butoanelor (`_cmd_base.vc2:41-...` si a doua
implementare la `120-...`) citeste `This.cAction` si il executa pe `Thisform` (cu
`This.clistaparametri` optional ca argument). Deci un buton nou nu are nevoie de propriul
`Click` - doar de `caction = <nume_metoda_pe_thisform>`.
Pentru o actiune noua gateata de drept (ca `but_modifica1`, nu ca `But_modifica2`):
1. Adauga metoda `do_editare_sume` (sau numele ales) pe `frm_facturi`.
2. Adauga `ADD OBJECT 'But_editare_sume1' AS but_modifica WITH ... caption/picture/tooltip/
pozitie ...` (poate mosteni orice clasa vizuala din `cmd_butoane.vcx`, nu neaparat
`but_modifica`).
3. Daca actiunea trebuie gateata separat de token-ul "3" (modificare antet/explicatie) - decizie
de arhitectura, vezi D1 - adauga `inainte_de_do_editare_sume` proprie care verifica
`This.lactivN` (N = tokenul nou ales, ex. "5"), si seteaza `caction =
inainte_de_do_editare_sume` pe buton (dupa modelul `but_modifica1`, care NU seteaza caption
explicit pe buton ci mosteneste `inainte_de_do_modifica` din `cmd_butoane.vc2:188`).
4. Adauga proprietatea `cbuton5 = But_editare_sume1` pe `frm_facturi` (langa `cbuton2`/`cbuton3`
existente, `ofacturare_comun.vc2:1352-1353`) ca butonul sa fie ascuns automat cand tokenul
"5" lipseste din `gcAcces` (mecanismul din A4).
5. Vezi `COMUN\docs\conventie_ux_formulare.md` pentru pozitionare/anchor in bara existenta.
## B. Deosebiri de fond fata de plan
1. **Garda eFactura NU e in `do_sterge`, e in `do_modifica`** (A3). Planul o citeaza gresit ca
parte a sablonului `do_sterge` ("Garda eFactura, de refolosit: `ofacturare_comun.vc2:4428-4432`"
sub titlul despre `do_sterge`). Practic nu schimba directia (garda tot exista si e
refolosibila), dar sursa corecta de citat si tiparul de extras (azi e un simplu `If`, nu un
`Return` cu mesaj ca restul garzilor) trebuie corectate in implementare.
2. **`frm_facturi.do_modifica` NU deschide `frm_modifica_articol_factura`** (A5). Planul (si
textul din task) atribuie asta lui `do_modifica`; in realitate `do_modifica` deschide
`frm_modifica_factura` (antet, alte campuri), iar `frm_modifica_articol_factura` (explicatie+
taxcode) e deschis de `do_modifica_explicatie`, legata de `But_modifica2`. Nu schimba
concluzia planului (niciuna din cele doua nu atinge sume), dar numele metodei/formularului de
citat in orice implementare viitoare trebuie sa fie cel corect.
3. **Drepturile pe `frm_facturi` nu sunt "lactiv3/lactiv4 + tokeni in gcAcces" ca fapt
autonom al formularului** - sunt mecanismul GENERIC din `_frm_base.actualizeaza_drepturi`
(A4), aplicat oricarui formular care extinde `_frmbase`. `frm_facturi` doar declara ce
inseamna fiecare token pentru el (`cbuton2`, `cbuton3`) si manipuleaza direct `gcAcces`/
vizibilitatea pentru cazul special "luna inchisa" (`Init`, 4770-4773). Nu exista o lista
centrala DB-editabila a semnificatiei tokenilor (vezi D2) - planul nu gresea factual, dar
ii lipsea acest nivel de detaliu, relevant pentru cum se inregistreaza un token nou.
4. Restul ancorelor (A1, A2, A6, A7) confirma planul, doar cu liniile deplasate de commit-urile
#7/#8 - nicio diferenta de fond.
## C. Propunerea de implementare S1-S3
### Arhitectura: unde se pune ce
Decizia lui Marius (progres.md, punctul 5) cere ca garzile sa se aplice pe AMBELE puncte de
intrare (`frm_facturi` din ROAFACTURARE si `afisjurcom` din ROACONT/ROAGEST). Azi, garzile
"luna inchisa" si "luna curenta" **exista deja si independent** in ambele clase
(`do_sterge`/A1 respectiv `do_modifica`/A6) - fiecare punct de intrare are propria lor copie,
pattern deja folosit in cod (nu e o incalcare noua sa le duplic). Garda "referinte
incasari/plati" si garda "eFactura" insa **exista azi doar in `frm_facturi`** (ROAFACTURARE) -
`afisjurcom.do_modifica` nu le are deloc.
Recomandare:
- **`ReferinteDocumenteNota`** (`COMUN\programe\odocumente.prg:8`) e deja in `COMUN`, deci
reutilizabila ca atare din `afisjurcom.do_modifica` fara nicio mutare de cod - se apeleaza cu
aceiasi parametri (`an`, `luna`, `cod`), doar ca `afisjurcom` trebuie sa stie cand documentul
curent e o factura (vezi mai jos).
- **Garda eFactura** foloseste `poRec.id_fact` - `afisjurcom` are deja `lnIdFact`/`lnIdfactd`
(A6 pas 3) din `actjur`, deci parametrul exista, doar interogarea (azi inline in
`do_modifica` a lui `frm_facturi`) trebuie extrasa intr-o functie mica in `COMUN\programe\`
(ex. `EsteInEFactura(tnIdFact)`) ca sa fie apelabila din ambele clase fara duplicare literala
a SQL-ului.
- Cazul "documentul curent e o factura de vanzare" trebuie detectat in ambele puncte de intrare
(nu doar in `frm_facturi`, care STIE deja ca lucreaza cu facturi) - pentru `afisjurcom`
inseamna un test suplimentar (ex. `id_set` intre valorile care corespund facturarii, sau
existenta unui rand in `vanzari` cu acel `cod`) inainte de a aplica garda eFactura/referinte -
pe alte tipuri de note aceste garzi nu au sens si nu trebuie sa apara.
- **Cel mai simplu 80/20**: o singura functie noua in `COMUN\programe\` (langa
`odocumente.prg` sau intr-un fisier nou `ofacturare_editare.prg`), ex.
`VerificaEditareFactura(tnCod, tnAn, tnLuna, tnIdFact)`, care ruleaza toate garzile
aplicabile facturii (eFactura + referinte; luna inchisa/curenta raman ca azi, duplicate local,
pentru ca deja exista identic in ambele clase) si intoarce `.T./.F.` + mesajul de eroare deja
afisat. Apelata din `frm_facturi` (actiune noua, S1) SI din `afisjurcom.do_modifica` (adaugare
minima, cateva linii), cu un test prealabil "e factura?" facut de fiecare apelant dupa
contextul lui.
### S1 - Actiunea noua in frm_facturi
- Metoda noua `do_editare_sume` (nume de discutat) pe `frm_facturi`
(`COMUN\clase\ofacturare_comun.vc2`), clonata dupa scheletul de garzi din `do_sterge`
(A1 pasii 1-7), dar FARA ramurile de stergere efectiva (pasii 8-12) - se opreste dupa garzi si
preda la S2/S3.
- Buton nou dupa modelul A8, cu `caption = do_editare_sume` (sau `inainte_de_do_editare_sume`
daca se doreste gating explicit prin `lactivN`), token nou in `gcAcces` (propun "5", primul
liber - A4) + `cbuton5` pe `frm_facturi`.
- Semnatura: fara parametri (citeste contextul din `crsfacturi`/pozitia curenta, ca `do_sterge`).
### S2 - Incarcarea cursoarelor (COMUN, refolosibila)
Extrage pasii 7-8 din A6 (incarcarea `vact_tot`/`vrul_tot`/`vrul_obinv_tot` in
`tact`/`trul`/`trul_obinv`, filtrate pe `cod`+`an`+`luna`) intr-o procedura comuna, ex.
`IncarcaCursoareModificareNota(tnCod, tnAn, tnLuna, tlAratasterse)` in `COMUN\programe\`, apelata
identic din `afisjurcom.do_modifica` (inlocuind codul inline de azi, refactorizare minima) si din
noua actiune din `frm_facturi`. Asta e singura cale sa se garanteze ca cele doua puncte de
intrare incarca EXACT acelasi lucru, cerinta explicita a lui Marius.
### S3 - Deschiderea frm_modific2024 (cod apelant ~40 linii)
Schita (in `frm_facturi.do_editare_sume`, dupa ce S1 a validat garzile si S2 a incarcat
cursoarele):
```foxpro
PROCEDURE do_editare_sume
* garzi S1 (eFactura, referinte, luna inchisa/curenta) - vezi A1, A3
...
Local lnCod, pnAn, pnLuna, lnIdSet, lnIdFact, lnIdFactD
* citeste cod/an/luna/id_set/id_fact/id_factd din crsfacturi, ca in A1 pas 3
If !IncarcaCursoareModificareNota(lnCod, pnAn, pnLuna, .F.) && S2, COMUN
Return
Endif
If Reccount('actactan') = 0
amessagebox("Nu exista nota contabila pentru aceasta factura.",0+48,"Atentie")
Return
Endif
Select tact
Local Omodif
Omodif = Createobject([frm_modific2024], lnIdSet)
Omodif.Show()
If Omodif.gnButon = 1 && sau variabila globala Buton, ca in A6 pas 10
If Thisform.do_deschide_tranzactie()
lnSucces = OSCRIE_IN_FISIERE(2,.T.,.T.)
If lnSucces > 0
* reconstruieste actactan/RUL_TEMP/RUL_TEMP_OBINV din tact/trul/trul_obinv, ca in A6
...
lnSucces = OSCRIE_IN_FISIERE(0,.T.,.T.)
Endif
If lnSucces > 0
lcSql = [begin pack_contafin.finalizeaza_modificare_nota(...); end;] && A6 pas 10
lnSucces = Iif(goExecutor.oExecuta(lcSql),1,-1)
Endif
Thisform.do_inchide_tranzactie(Iif(lnSucces<0,2,1))
If lnSucces > 0
Thisform.do_cauta()
Endif
Endif
Endif
* inchide actactan/rul_temp/rul_temp_obinv/tact/trul/trul_obinv
ENDPROC
```
Notă: `do_deschide_tranzactie`/`do_inchide_tranzactie` exista deja pe `_frmbase`
(`_frm_base.vc2:252-265` si un omolog de inchidere, de verificat numele exact la implementare -
`afisjurcom` il foloseste direct, A6 pas 10) - de reutilizat, nu de reprodus manual ca in
`do_sterge` (care foloseste `SQLSetprop` direct, tipar mai vechi).
### Fisiere atinse (estimare S1-S3)
| Fisier | Proiect | Ce se schimba |
|---|---|---|
| `COMUN\clase\ofacturare_comun.vc2` | COMUN (cross-project) | metoda noua `do_editare_sume` + buton nou pe `frm_facturi`, token nou in `cbuton*` |
| `COMUN\clase\comun.vc2` | COMUN (cross-project) | `afisjurcom.do_modifica` - apel la garda noua + la `IncarcaCursoareModificareNota` (inlocuind codul inline) |
| `COMUN\programe\odocumente.prg` sau fisier nou `COMUN\programe\ofacturare_editare.prg` | COMUN (cross-project) | functiile comune noi: garda eFactura extrasa, `IncarcaCursoareModificareNota` |
| `COMUN\clase\omodificari.vc2` | COMUN (cross-project) | NEATINS in S1-S3 (S4 adauga PAGE3) |
Orice modificare in `COMUN\clase\comun.vc2` (`afisjurcom`) afecteaza registrul jurnal din TOATE
produsele ROA care il folosesc (ROACONT, ROAGEST, posibil altele) - de tratat cu maxima grija si
testat separat de `frm_facturi`.
## D. Intrebari deschise
1. **Ce token numeric folosim pentru dreptul nou** si daca trebuie sa fie distinct de tokenul
"3" (modificare) existent, sau daca e acceptabil ca cine are drept de "modificare" (token 3)
sa capete automat si dreptul de editare sume. Propunere: token separat (ex. "5"), pentru ca
editarea sumelor are impact contabil mult mai mare decat editarea campurilor de antet/
explicatie - un utilizator ar trebui sa primeasca acest drept explicit, nu implicit prin
dreptul existent.
2. **Cum se inregistreaza practic un token nou in sistemul de drepturi** ca un administrator sa-l
poata acorda per grup din `frm_grupuri` (`COMUN\clase\drept_grupuri.vc2`). Am gasit
mecanismul tehnic (`gcAcces` -> `lactivN`/`cbutonN`, populat prin `vdef_util_obiecte` +
`PACK_DREPTURI.grupdreptmodproc`), dar nu am gasit un catalog editabil al semnificatiei
tokenilor per program - posibil sa fie o eticheta hardcodata undeva neindexat inca in cache-ul
text, sau sa fie nevoie de un rand nou in Oracle. De clarificat inainte de S1, altfel tokenul
nou risca sa fie "orfan" (functioneaza in cod dar nimeni nu-l poate acorda din UI).
3. **Cum se determina in `afisjurcom` ca documentul curent e o factura de vanzare**, ca sa aplice
garda eFactura/referinte doar atunci (S4 foloseste acelasi test pentru afisarea PAGE3). Optiuni:
test pe `id_set` (interval cunoscut pentru facturare) sau pe existenta unui rand in `vanzari`
cu `cod`-ul curent. A doua varianta e mai robusta (nu depinde de conventia de `id_set`) dar
costa un SELECT suplimentar la fiecare deschidere - de decis cu Marius pragul de cost acceptat.
4. ~~Numele exact al metodelor de tranzactie pe `_frmbase`~~ - rezolvat in cercetare:
`do_deschide_tranzactie` (`_frm_base.vc2:252-265`) si `do_inchide_tranzactie`
(`_frm_base.vc2:279`) exista amandoua pe `_frmbase`, deci reutilizabile ca atare in S3.