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
21 KiB
Plan #6 — editarea unei facturi emise, netrimisa inca in eFactura
Sursa: COMUN\docs\todos.txt punctul 6.
Ordine de executie: al treilea, dupa #8 si #7.
Stare: IN LUCRU. S1-S6 gata, S5 comis in git pe 10.08.2026. Ramase: S4b partial (actiunea de sincronizare), S7 neatins, S8 partial, S9 partial. Starea la zi si ordinea recomandata:
docs\handoff_punct6_dupa_s5.md. Deciziile 38-41, care corecteaza S5 fata de ce scrie mai jos:docs\handoff_s5.md.
Cerinta si directia aleasa
Factura emisa trebuie sa poata fi corectata cat timp nu a plecat in eFactura
(anaf_efactura.id_fact). Problema: notele contabile si rulajele se genereaza complicat la emitere,
iar editarea de azi nu le sincronizeaza.
Varianta respinsa: regenerarea prin re-emitere. Emiterea face verificari de stoc si alte protectii dependente de tipul documentului (lista de preturi, comanda, contract, retur, invoice); la regenerare acestea ar esua pe date care intre timp s-au schimbat.
Varianta aleasa: editare directa in frm_modific2024, extins cu partea de
vanzari/vanzari_detalii, ca sa nu se duplice un formular de editare de note si rulaje.
Doua puncte de intrare, o singura implementare (decizie Marius, 06.08.2026)
Editarea unei facturi de vanzare trebuie sa fie posibila si din ROACONT > registru jurnal > modificare, adica exact prin procedura existenta de editare de note contabile / rulaje — nu doar dintr-o actiune noua in formularul de facturi din ROAFACTURARE.
Consecinta pentru arhitectura: lucrarea nu e "cod apelant nou in ROAFACTURARE", ci
extinderea clasei comune frm_modific2024 + a partii server-side, de unde ambele puncte de
intrare o primesc automat. Cazul "documentul curent e o factura de vanzare" se detecteaza in
formular, nu in apelant.
ID_FACT nu se schimba — by design
id_fact se genereaza la introducerea documentului, din nract + dataact, si ramane acelasi la
modificarea notelor contabile; se schimba doar cod-ul setului de note/rulaje. Legatura initiala
cu ACT/RUL era vanzari.cod, dar intre timp s-a adaugat si perechea
vanzari.id_fact / act.id_fact / rul.id_fact / documente.id_doc, folosita de alte
functionalitati.
Deci VANZARI.ID_FACT ramane neatins la editare, iar realinierea priveste exclusiv cod-ul.
Orice ipoteza de rescriere a lui id_fact e gresita si a fost scoasa din plan.
Ce s-a stabilit din cod
Formularul exista deja si e direct utilizabil
frm_modific2024 e o clasa .vcx (nu .scx monolitic), definita in
COMUN\clase\omodificari.vc2 (clasa incepe la :6375, metodele proprii :12200-15319). E deja in
COMUN-ul ROAFACTURARE, deci nu trebuie portata nimic: COMUN\clase e deja in SET CLASSLIB /
SET PROCEDURE, iar clasa foloseste doar globale standard (gnAn, gnLuna, goExecutor, gcs,
gnIdUtil, glLunaInchisa), toate setate de Programe\roafacturare.prg.
Formularul editeaza doar cursoare in memorie; do_termin (mostenit din _frmbase) nu scrie
nimic, doar seteaza gnButon=1 si inchide. Scrierea e treaba codului apelant.
Acelasi formular e si "modificare registru jurnal" — apelat din afisjurcom.do_modifica
(comun.vc2:2222-2563). Fluxul e deja documentat in
D:\ROA\ROAGEST\COMUN\docs\flux-modificare-stergere-nota-jurnal.md, verificat linie cu linie.
Scrierea in ACT/RUL: o singura cale posibila
Nu exista niciun UPDATE/DELETE direct pe ACT sau RUL in tot codul VFP (cautat explicit).
Singura cale: cursoare -> ACT_TEMP/RUL_TEMP (INSERT-uri in oscrie_in_fisiere.prg:127-136,
:272-274) -> PACK_CONTAFIN.init_scriere_act_rul_local / final_scriere_act_rul_local.
Editarea nu suprascrie randul vechi: il marcheaza STERS = 1 si scrie un document nou, cu cod
nou. Comportament intentionat, nu efect secundar.
Sincronizarea cu VANZARI exista deja partial — si aici e lucrarea
pack_contafin.finalizeaza_modificare_nota (COMUN\docs\PACK_CONTAFIN.pck:8601-8651) apeleaza deja
pack_facturare.actualizeaza_vanzari(cod_vechi, cod_nou) cand cod-ul exista in vanzari
(iar finalizeaza_stergere_nota apeleaza sterge_din_vanzari).
Dar actualizeaza_vanzari (ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql:15951-15961) face exclusiv
realinierea legaturii:
UPDATE VANZARI_DETALII SET STERS = 0
WHERE ID_VANZARE IN (SELECT ID_VANZARE FROM VANZARI WHERE COD = V_COD_VECHI);
UPDATE VANZARI SET COD = V_COD_NOU, STERS = 0 WHERE COD = V_COD_VECHI;
Nu recalculeaza sume, nu atinge cantitati/preturi din VANZARI_DETALII, nu reactualizeaza totalurile
denormalizate din VANZARI (total_fara_tva, total_tva, total_cu_tva, valoare_achizitie,
discount_tva). Comentariul din cod (:15954) anticipeaza chiar aceasta extensie: "de modificat in
caz ca il las sa stearga manual inregistrari din VANZARI_DETALII".
Deci: azi, o editare de nota rescrie corect contabilitatea si pastreaza legatura cu factura, dar lasa sumele facturii la valorile vechi. Exact divergenta pe care o descrie cerinta.
Calea de scriere in VANZARI_DETALII (stabilit 08.08.2026)
Detaliu complet: docs\cercetare\rec_cale_vanzari_detalii.md.
La emitere, liniile nu se scriu din VFP in VANZARI_DETALII. VFP cheama, per linie din
crsfactura, pack_facturare.adauga_articol_factura (ofacturare.vc2:14069-14091), care insereaza
in VANZARI_DETALII_TEMP; trecerea in tabela reala o face scrie_in_vanzari, cu un
INSERT ... SELECT FROM VANZARI_DETALII_TEMP, potrivit pe (id_comanda, numar_act).
adauga_articol_factura nu e reutilizabila la editare: ramifica pe pack_facturare.ntip
(stare de sesiune) si re-deriva pretul, TVA-ul si valuta din documentul-sursa (comanda, aviz,
contract). La o factura deja emisa nu exista document-sursa de re-derivat, iar valorile editate de
utilizator ar fi suprascrise. VANZARI_DETALII_TEMP e GTT ON COMMIT DELETE ROWS, deci si
umplerea, si consumul ar trebui sa stea in aceeasi tranzactie.
Calea aleasa pentru #6: scriere directa in VANZARI_DETALII, fara sa treaca prin TEMP —
UPDATE tintit pe ID_VANZARE_DET pentru linii modificate, STERS = 1 pentru linii scoase,
INSERT pentru linii adaugate. Modelul exista deja: modifica_explicatie_articol. ID_VANZARE_DET
vine automat dintr-un trigger BEFORE INSERT pe SEQ_VANZARI_DETALII, deci un INSERT de
oriunde primeste cheia corect.
Alternativa (refolosirea TEMP) ar fi cerut fie atingerea lui adauga_articol_factura /
scrie_in_vanzari — cod critic de emitere — fie duplicarea lor, adica exact tiparul care a produs
problema reparata la #8.
Stergerea unei singure linii nu exista azi: sterge_factura / sterge_proforma marcheaza
STERS = 1 pe toate liniile documentului deodata. E functionalitate noua pentru #6.
Punctul de agatare si garda existenta
- Sablonul arhitectural cel mai apropiat e
frm_facturi.do_sterge(COMUN\clase\ofacturare_comun.vc2:4503-4719): incarca cursoarele pecod, porneste tranzactie manuala, ruleazaoscrie_in_fisiere, apoipack_contafin.finalizeaza_stergere_nota. Se cloneaza acesta, nudo_modifica(care doar deschide un formular de metadate). - Garda "nu edita daca a plecat in eFactura" exista deja, dar in
do_modifica, nu indo_sterge(ofacturare_comun.vc2:4426-4430:select count(*) from anaf_efactura where id_fact = ...+poRec.sters = 0 AND NVL(pnEFactura,0) = 0). Azi e o simpla conditie deIfcare deschide sau nu dialogul; pentru editare trebuie sa devina unReturncu mesaj, ca celelalte garzi, si sa fie extrasa inCOMUN\programe\ca sa fie apelabila si dinafisjurcom, care nu o are deloc. - Gating-ul de drepturi pe
frm_facturinu e prinnid_cw, ci prinThis.lactiv3/lactiv4+ tokeni in globalagcAcces. (Difera deofundal_facturare, unde se folosestenid_cw— de nu confundat cu planurile #11/#10.)
Stories
S1 — Actiunea noua pe formularul de facturi (punctul de intrare din ROAFACTURARE)
Al doilea punct de intrare, ROACONT > registru jurnal > modificare, exista deja si nu are nevoie de actiune noua — dar garzile de mai jos trebuie sa fie in formular sau in codul comun, ca sa se aplice si acolo, nu doar in ROAFACTURARE.
Cloneaza structura din do_sterge (ofacturare_comun.vc2:4503-4719) intr-o actiune noua de editare:
garda eFactura + sters=0 (refolosita din :4428-4432), plus garzile pe care do_modifica nu le are
azi dar do_sterge le are si care devin obligatorii cand se ating sumele: luna inchisa
(glLunaInchisa, :4518-4520), luna curenta (:4543-4546) si referinte de incasari/plati
(ReferinteDocumenteNota, :4565-4569).
Drepturi: sub tokenul "3" existent (decizia din 08.08.2026) — butonul nou se adauga in
cbuton3 alaturi de but_modifica1/But_modifica2, si actiunea trece prin This.lactiv3. Fara
token nou, fara interventie in tabelele de drepturi.
Gata cand: actiunea apare, e vizibila doar cu drept, si refuza corect facturile trimise in
eFactura, sterse, din luna inchisa sau referentiate.
S2 — Incarcarea cursoarelor notei
Dupa modelul afisjurcom.do_modifica (comun.vc2:2222-2563): incarca vact_tot / vrul_tot /
vrul_obinv_tot in cursoarele tact / trul / trul_obinv, filtrate pe cod + an + luna
(acelasi filtru ca la stergere).
Gata cand: pentru o factura data se incarca exact randurile ei de nota si de rulaj.
Depinde de: S1.
S3 — Deschiderea frm_modific2024 pe factura
Instantiaza clasa din COMUN\clase\omodificari.vc2 cu cursoarele din S2. Cod apelant ~40 de linii,
fara modificari in clasa.
Gata cand: formularul se deschide din ROAFACTURARE si arata nota facturii; gnButon=1 la
confirmare.
Depinde de: S2.
S4 — Pagina noua de articole factura in frm_modific2024
Editarea randului din vanzari si a randurilor din vanzari_detalii intra in acelasi formular,
pe o pagina noua a pageframe-ului existent, dupa modelul paginilor de rulaje.
Scop complet (decizia lui Marius, 08.08.2026): linii sterse, adaugate si modificate
(articol, cantitate, pret, flagul pret_cu_tva — vezi planul #7), plus discountul de document
(VANZARI.DISCOUNT) pe zona de antet.
Fara plafon de cantitate si fara verificare de stoc. Corectia unei facturi emise e raspunderea utilizatorului; formularul nu-l opreste. Asta inchide intrebarea lasata deschisa de #7 (de unde vine plafonul cand cursorul de stoc din formularul de compunere nu exista) — raspunsul e ca nu mai e nevoie de plafon. In schimb, obligatia se muta pe helpere si verificari, vezi S4b: totaluri calculate, propuneri de sincronizare si semnalarea necorelarilor cu notele si rulajele.
Drepturi: sub tokenul "3" existent (modificare). Fara token nou.
Liniile din seturi se trateaza ca orice alta linie — fara ramura speciala in formular si fara
blocarea facturilor care le contin. Consecinta pentru S5: agregarea din scrie_in_vanzari are
ramura proprie pe VANZARI_SETURI_TEMP, deci recalculul trebuie sa acopere si liniile de set,
altfel totalurile diverg tacut exact pe facturile cu seturi.
Ancora concreta: pgfArticole din omodificari.vc2 are azi
PAGE1.Caption = "Rulaje materii prime, materiale, marfuri, obiecte inventar (303)" cu grdRulaje si
PAGE2.Caption = "Rulaje obiecte inventar in folosinta (8039)" cu grdRulajeObinv (:8598-8601).
Se adauga PAGE3 cu un grid de articole legat de cursorul de vanzari_detalii, plus zona de antet
pentru randul din vanzari.
Pagina se afiseaza doar cand documentul curent are rand in vanzari; altfel formularul arata
exact ca azi. Asta e conditia ca registrul jurnal din ROACONT/ROAGEST sa nu se schimbe pentru
documentele care nu sunt facturi.
Respecta COMUN\docs\conventie_ux_formulare.md si, pentru 3 griduri,
COMUN\docs\capcana_grid_controlsource.md. Clasa e in COMUN\, deci schimbarea e cross-project.
Gata cand: pagina apare pe o factura de vanzare deschisa din ambele puncte de intrare, si lipseste
pe un document care nu e factura.
Depinde de: S3.
S4b — Helpere, totaluri si verificari de corelatie, explicit, niciodata silentios
Cerinta lui Marius: preturile si cantitatile din rulaje si cele din articolele facturii se pot desincroniza la editare, iar programul nu are voie sa le alinieze pe tacute. Trebuie sa arate utilizatorului ce nu se potriveste si sa propuna sincronizarea, ca actiune constienta.
Odata cu decizia din 08.08.2026 (S4 fara plafon si fara verificare de stoc), S4b devine partea grea a lui #6: singura plasa de siguranta a utilizatorului. Nu mai e un adaos peste S4, ci conditia care face editarea libera acceptabila. Acopera si liniile adaugate sau sterse, nu doar valorile modificate.
Continut:
- Totaluri de control vizibile in formular, pe trei surse: suma din
RUL, suma dinVANZARI_DETALIIsi suma dinACT. Cand cele trei nu coincid, diferenta se vede, nu se ascunde. - Indicator de stare a sincronizarii (label/culoare), nu doar un mesaj la salvare.
- Actiune explicita de sincronizare, cu enumerarea liniilor care s-ar modifica si a valorilor vechi/noi inainte de aplicare.
- Sincronizarea nu se declanseaza automat la
do_termin.
Directia sincronizarii (rulajul e sursa sau articolul e sursa) se stabileste la implementare, dar alegerea trebuie sa fie a utilizatorului, nu implicita. Gata cand: o editare care desincronizeaza cele trei surse produce un indicator vizibil si o propunere enumerata, iar refuzul propunerii lasa datele nemodificate. Depinde de: S4.
S5 — Scrierea sumelor editate in VANZARI (partea Oracle)
Procedura sora noua (ex. recalculeaza_totaluri_vanzari), apelata din
finalizeaza_modificare_nota dupa actualizeaza_vanzari — nu extinderea in-place a lui
actualizeaza_vanzari. Motivul: actualizeaza_vanzari ruleaza azi la ORICE editare de nota al
carei cod exista in VANZARI, inclusiv din registrul jurnal ROAGEST/ROACONT pe editari care nu
ating sumele; recalculul in-place ar propaga riscul in toata suita. Detaliu si sursa curenta:
docs\cercetare\rec_s5_oracle_vanzari.md.
Refoloseste acelasi calcul ca scrie_in_vanzari — nu o formula paralela, altfel cele doua cai
diverg exact ca in problema de la #8. Partea per-linie e deja extrasa in
calculeaza_total_fara_tva_fact / calculeaza_total_tva_fact, care ramifica deja pe
PRET_CU_TVA; de extras ramane doar blocul de agregare, parametrizat pe sursa
(VANZARI_DETALII_TEMP la emitere, VANZARI_DETALII la editare).
Doua constrangeri gasite la cercetare:
SERIE_INCASAT/NR_INCASAT/SUMA_INCASAT/TIP_INCASATnu se recalculeaza. Vin din stare de sesiune specifica emiterii unei facturi-cu-incasare si n-au sursa persistenta; o copiere naiva a intreguluiUPDATEdinscrie_in_vanzarile-ar puneNULLla fiecare editare, rupand legatura cu incasarea. Se scriu doar cele 11 coloane de totaluri/curs.VALVAL/TVAVAL/TOTVAL(totaluri in valuta) intra in recalcul, desi planul initial nu le enumera: sunt in acelasi bloc de agregare, costa zero in plus si altfel raman incoerente pe documentele in valuta.
Discountul de document e editabil (decizia din 08.08.2026), deci intra ca valoare noua in
recalcul, nu se citeste ca invariant din VANZARI.DISCOUNT.
Script de migrare conform COMUN\docs\scripturi-migrare-db.md: CRLF, idempotent, nivel Oracle 10.2,
versiune_db.txt actualizat.
Gata cand: dupa o editare de cantitate, total_fara_tva/total_tva/total_cu_tva din VANZARI
corespund sumei liniilor.
Depinde de: S4.
S6 — Legaturile care depind de cod
Editarea scrie un document nou cu cod nou, iar actualizeaza_vanzari realiniaza VANZARI.COD.
VANZARI.ID_FACT nu se schimba (by design — vezi mai sus), deci tot ce se leaga prin id_fact /
id_doc ramane valid: anaf_efactura, documente, si perechile act.id_fact / rul.id_fact.
Inchis pe cod la 08.08.2026 (docs\cercetare\rec_s5_oracle_vanzari.md, sectiunea C): toate
legaturile trec prin ID_FACT (ACT.id_factd/id_factc, DOCUMENTE.ID_DOC,
ANAF_EFACTURA.ID_FACT) sau prin ID_VANZARE (vanzari_coresp, marcheaza_facturat), niciodata
prin cod. actualizeaza_vanzari rescrie doar COD pe acelasi rand — ID_VANZARE nu se schimba
niciodata. ReferinteDocumenteNota e o garda pre-editare, nu o legatura persistenta. Fara lucru
suplimentar; ramane doar confirmarea pe fluxul real, in S8.
Depinde de: S5.
S7 — Rotunjirea la reeditare
verifica_total_document (:16009-16188) insereaza automat o linie de corectie in ACT_TEMP cand
totalul difera de suma din note. La editare se aplica din nou — de confirmat ca nu se acumuleaza
corectii succesive la editari repetate.
Gata cand: trei editari consecutive nu lasa trei linii de corectie.
Depinde de: S5.
S8 — Test pe fluxul real, din ambele puncte de intrare
Test headless (COMUN\docs\depanare_testare_vfp.md) + UI (COMUN\docs\testare-ui-vfp.md), pe cate un
caz din fiecare tip de sursa: lista de preturi, comanda, contract, aviz. Fiecare caz rulat de doua
ori: o data pornit din formularul de facturi (ROAFACTURARE), o data din registru jurnal (ROACONT).
Verifica: nota veche STERS=1, nota noua corecta, id_fact neschimbat, vanzari/vanzari_detalii
sincronizate, totalurile denormalizate corecte, rulajele refacute, totalurile de control din S4b
concordante, si ca nu s-au declansat verificarile de stoc de la emitere.
Al treilea caz obligatoriu: un document care nu e factura, deschis din registru jurnal — pagina
de articole nu apare si comportamentul e identic cu cel de azi.
Depinde de: S6, S7.
S9 — Diff, review, changelog, documentatie
Diff ca fisier in docs\, commit dupa aprobare, in doua repo-uri (ROAFACTURARE si COMUN). Changelog
:nou:. Propune actualizarea flux-modificare-stergere-nota-jurnal.md cu ramura de facturi.
Riscuri
- Cel mai mare:
omodificari.vc2e in COMUN si serveste si registrul jurnal din ROAGEST/ROACONT. O regresie acolo e mai grava decat lipsa functionalitatii aici. S4 trebuie sa pastreze modul "doar nota" complet neschimbat. - Modelul "sterge + scrie document nou cu cod nou" inseamna ca o factura editata isi schimba
cod-ul — orice raport sau integrare care tine mintecod-ul vechi il pierde. S6 exista tocmai pentru asta. - Fara garzile de luna inchisa / luna curenta / referinte (azi absente pe
do_modifica), editarea de sume ar putea modifica o perioada deja raportata. Sunt obligatorii, nu optionale. - Interactiunea cu #7: daca flagul
pret_cu_tvadevine editabil pe linie, editarea ulterioara trebuie sa il trateze la fel ca introducerea.
Dependente
- #7 — S4 include editarea flagului
pret_cu_tvape linie; se face dupa ce #7 stabileste comportamentul la introducere. - #8 — S5 refoloseste calculul totalurilor din
scrie_in_vanzari, care se atinge in #8.
Ce preda #7 catre S6 (consemnat 07.08.2026, decizia lui Marius)
Din #7 s-a livrat editarea flagului pret_cu_tva doar pe factura in curs de compunere
(inainte de salvare), prin frm_facturare_articole.do_modifica (buton But_modifica1 +
dublu-clic pe grd_factura), care redeschide dialogul frm_articol_factura. Detaliu complet:
docs\cercetare\rec_s2b_aplicare.md.
Editarea aceluiasi flag pe o factura deja salvata a fost mutata explicit in #6, prin decizia
lui Marius din 07.08.2026. Motivul, exact: butonul existent din frm_facturi (But_modifica2 ->
do_modifica_explicatie, nu do_modifica) deschide frm_modifica_articol_factura, care
editeaza doar explicatie si taxcode — doua campuri care nu ating nicio suma
(pack_facturare.modifica_explicatie_articol e un UPDATE de doua coloane). Cealalta actiune,
do_modifica, deschide frm_modifica_factura (antet: ruta, delegat, agent, serie/numar, date) —
tot fara sume.
Flagul pret_cu_tva e de alta natura: schimbarea lui reimparte baza si TVA-ul pe linie, deci
muta totalurile denormalizate din VANZARI si notele contabile — exact problema de fond a
punctului 6.
#7 lasa mostenire un model gata facut si verificat pentru partea de UI a acestei editari:
maparea de intrare crsfactura -> poArticol (AddProperty/RemoveProperty pe 7 perechi de
nume) si drumul invers (Gather+Replace), documentate in docs\cercetare\rec_s2b_aplicare.md.
Deci S4 nu trebuie sa reproiecteze dialogul, ci sa rezolve partea de persistenta/recalcul in
Oracle (vezi S5).
Limitarea ncantitatemax din #7 a fost eliminata tot in #7, prin decizia lui Marius din
07.08.2026: do_modifica recalculeaza plafonul din cursorul de stoc in loc sa il fixeze pe
cantitatea curenta a liniei, reconstituind cantitatea disponibila de dinainte ca linia curenta sa
o fi consumat. Mecanismul, pe scurt: regasire dupa id_c in crsarticole/crsarticole1 (alegerea
cursorului dupa opt_facturare), apoi reversul decrementarii pe care do_adauga_articol a
aplicat-o deja — cantitate + poArticol.cantitate la tipurile de document cu verificare de stoc,
cantitate - poArticol.cantitate la retur; fallback pe cantitatea liniei daca randul nu mai e in
cursor. Detaliu complet: docs\cercetare\rec_s2c_ncantitatemax.md.
Inchis pe 08.08.2026: intrebarea era de unde vine plafonul de cantitate la o factura deja
salvata, unde cursorul de stoc (crsarticole/crsarticole1) poate sa nu existe. Decizia lui
Marius: #6 nu are plafon si nu verifica stocul — corectia unei facturi emise e raspunderea
utilizatorului. Nu e nevoie de interogare de stoc proprie. Efortul se muta in S4b (helpere,
totaluri, verificari de corelatie cu ACT si RUL).