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

26 KiB

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):

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.