#6 editare factura emisa: S9 - ramura de facturi in fluxul notei de jurnal

flux-modificare-stergere-nota-jurnal.md descria doar nota contabila. Documentul
capata ramura de facturi: cele doua puncte de intrare cu garzile lor, pasul nou
din tranzactia manuala, contractul ScrieArticoleFacturaEditate, recalculul din
Oracle si comportamentul gridului de articole.

Doua lucruri contraintuitive, scrise explicit: ID_FACT nu se schimba la reeditare
(COD se realiniaza), deci tot ce se leaga prin id_fact supravietuieste; si garda
de referinte lipseste intentionat pe editarea generica de note din Registrul
Jurnal - protejeaza incasarile la operatia care sterge efectiv factura.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
This commit is contained in:
2026-08-10 23:43:30 +03:00
parent 2dfbef40dc
commit a96b6a6eef

View File

@@ -44,6 +44,113 @@ ruleaza intr-o tranzactie manuala unica (commit sau rollback pe amandoua).
`do_inchide_tranzactie` in `do_sterge`); fiecare `OSCRIE_IN_FISIERE` isi gestioneaza singur `do_inchide_tranzactie` in `do_sterge`); fiecare `OSCRIE_IN_FISIERE` isi gestioneaza singur
commit-ul (vezi `tlModificare`/`llManualTransactions` in `oscrie_in_fisiere.prg:111-165`). commit-ul (vezi `tlModificare`/`llManualTransactions` in `oscrie_in_fisiere.prg:111-165`).
## Ramura noua: editare factura de vanzare (VANZARI/VANZARI_DETALII)
Cand documentul modificat prin `frm_modific2024` are un rand corespunzator in `VANZARI`, clasa
adauga o pagina noua in pageframe-ul de rulaje, `PAGE3 "Articole factura"`
(`COMUN\clase\omodificari.vc2:8707`), cu un grid legat pe cursorul `tvd` (structura view-ului
`VVANZARI_ARTICOLE`). Pe orice alt document (nota fara factura) formularul ramane neschimbat -
pageframe-ul are `PageCount = 2`, ca azi.
Ramura e activa doar cand `COMUN\programe\ofacturare_editare.prg` e incarcat in `SET PROCEDURE`
(verificat prin `"OFACTURARE_EDITARE" $ Upper(Set("Procedure"))`) - inregistrat la pornire de toate
trei aplicatiile care folosesc `frm_modific2024`: `ROAFACTURARE\Programe\roafacturare.prg:214`,
`ROACONT\Programe\roacont.prg:212`, `ROAGEST\Programe\roagest.prg:260`.
### Doua puncte de intrare
- `frm_facturi.do_editare_factura` (`COMUN\clase\ofacturare_comun.vc2:3715-3872`), actiune noua pe
formularul de facturi din ROAFACTURARE. Refuza editarea daca documentul e sters, e proforma, nu e
din luna curenta (`:3742-3755`), are referinte de incasari/plati (`ReferinteDocumenteNota`,
`:3758`) sau a fost trimis in eFactura (`EsteInEFactura`, in `ofacturare_editare.prg`, `:3764`).
Inainte de `Createobject([frm_modific2024])` incarca `crsArticoleFactura` cu
`IncarcaArticoleFactura` (`:3793`), ca gridul din PAGE3 sa se lege o singura data pe cursorul deja
plin.
- `afisjurcom.do_modifica` (`COMUN\clase\comun.vc2:2222-2567`) - acelasi punct folosit pentru orice
nota din Registrul Jurnal, neschimbat pentru documentele care nu sunt facturi de vanzare. Inainte
de `Createobject`, `PregatesteArticoleFacturaEditare('tact')` (`:2436`, in
`ofacturare_editare.prg`) cauta randul din `VANZARI` corespunzator notei (pe combinatiile
`cod/nract/serie_act/dataact` din `tact`) si, daca il gaseste, pre-incarca articolele. Pe acest
punct de intrare nu se verifica garda eFactura si nici cea de referinte de incasari/plati - doar
restrictia de luna curenta, deja existenta pentru orice nota (`:2265-2268`). Diferenta e
intentionata: garda de referinte protejeaza incasarile legate prin `id_fact` la operatia care
sterge efectiv factura; pe editarea de sume din ROAFACTURARE se aplica pentru ca stergerea si
rescrierea notei sunt parte din acelasi pas, dar pe editarea generica de note din Registrul
Jurnal (care poate sa nu priveasca deloc o factura) nu se aplica.
Daca apelantul nu a putut pregati articolele dinainte, `frm_modific2024.Show` reface legatura prin
`IncarcaVanzareDinNota` ca fallback si decide acolo daca arata `PAGE3`
(`omodificari.vc2:14769-14794`).
### Scrierea, in aceeasi tranzactie manuala
La `buton = 1` (Terminat), pasul nou se adauga la coada secventei existente de
stergere+scriere+realiniere, in aceeasi tranzactie manuala unica, identic pe ambele puncte de
intrare (`ofacturare_comun.vc2:3828-3830`, `comun.vc2:2491-2493`):
```
do_deschide_tranzactie()
oscrie_in_fisiere(2,...) -- sterge nota veche (ACT/RUL)
oscrie_in_fisiere(0,...) -- scrie nota noua, cod nou
pack_contafin.finalizeaza_modificare_nota(...) -- realiniaza VANZARI.COD (actualizeaza_vanzari)
ScrieArticoleFacturaEditate(tvanz.id_vanzare) -- NOU
do_inchide_tranzactie(...)
```
Agatarea ruleaza doar cand `tvanz` e deschis cu exact un rand (documentul are factura asociata).
`VANZARI.ID_FACT` nu e atins de niciun pas al secventei - ramane cel alocat la emiterea initiala a
facturii, la fel ca la orice alta nota (vezi "Implicatii practice"); doar `VANZARI.COD` se
realiniaza pe codul nou al notei. Tot ce se leaga prin `id_fact` (`ANAF_EFACTURA`, `DOCUMENTE`,
`ACT.id_factd`/`id_factc`) sau prin `ID_VANZARE` supravietuieste neschimbat unei reeditari; doar ce
ar tine minte `cod`-ul vechi il pierde.
`pack_facturare.actualizeaza_vanzari`, apelata din `finalizeaza_modificare_nota`, face
`UPDATE VANZARI_DETALII SET STERS = 0` pe tot documentul, fara nicio garda pe linie - reseteaza si
liniile sterse la o editare anterioara. De aceea `ScrieArticoleFacturaEditate` ruleaza DUPA
`finalizeaza_modificare_nota`, nu inauntrul ei: scrierea liniilor trebuie sa vina dupa acest reset,
ca sa-l corecteze, nu inaintea lui.
`ScrieArticoleFacturaEditate` (`COMUN\programe\ofacturare_editare.prg:468-555`):
1. marcheaza `sters = 1` pe tot documentul din `VANZARI_DETALII` (`:489-491`);
2. invie si actualizeaza liniile pastrate din `tvd` (cantitate, pret, pret_cu_tva - `pret_achizitie`
se omite, ramane valoarea persistata) (`:497-506`);
3. insereaza liniile noi (`id_vanzare_det = 0`), fara `id_vanzare_det` explicit - il genereaza
trigger-ul `TRG_VANZARI_DET_BEFOINS` (`:518-535`);
4. apeleaza `pack_facturare.recalculeaza_totaluri_vanzari(id_vanzare, discount)` (`:544-548`), cu
discountul luat din `tvanz.discount`; `NULL` pastreaza valoarea curenta din `VANZARI` in loc s-o
zeroeze.
O linie stearsa de utilizator la o editare ramane stearsa si dupa reeditari ulterioare - fiecare
salvare reface pasii 1-2 pe starea curenta din `tvd`, deci resetul din `actualizeaza_vanzari` e
mereu corectat inainte sa ajunga vizibil.
`pack_facturare.recalculeaza_totaluri_vanzari` (script de migrare
`ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql`) recalculeaza din `VANZARI_DETALII` - liniile proprii
si, separat, liniile din seturi agregate din `VANZARI_SETURI` - coloanele `discount`,
`discount_tva`, `valoare_achizitie`, `total_fara_tva`, `total_tva`, `total_cu_tva`, `valval`,
`tvaval`, `totval`, `id_valuta`, `curs`, `multiplicator`, cu acelasi calcul per-linie ca la emitere
(`calculeaza_total_fara_tva_fact`/`calculeaza_total_tva_fact`). Coloanele de incasare
(`serie_incasat`/`nr_incasat`/`suma_incasat`/`tip_incasat`) nu sunt atinse.
View-ul `VVANZARI_ARTICOLE` (script de migrare `ff_2026_08_09_02_COMUN_VVANZARI_ARTICOLE.sql`)
expune direct `VANZARI_DETALII`, cu `id_vanzare_set` si `pret_achizitie` printre coloanele proprii
ale tabelei, plus denumire/codmat/nume_gestiune/nume_val din join-uri - sursa cursorului `tvd`.
### Editarea in grid
Gridul `pgfArticole.PAGE3.grdArticoleFactura` (`omodificari.vc2:12320-...`) e legat pe `tvd`. Linia
provenita dintr-un set (`id_vanzare_set <> 0`) e needitabila (cantitate, pret, `pret_cu_tva`) si
apare intr-o culoare distincta in grid (`DynamicForeColor`); coloana `pret_achizitie` e editabila
doar pe liniile noi (`id_vanzare_set = 0 AND id_vanzare_det = 0`), doar-afisare pe restul
(`:16526-16552`). Stergerea unei linii e logica - `cmdStergeArticol.Click` comuta `sters` pe randul
curent din `tvd`, ramane vizibila grizata pana la salvare (`:16508-16517`). Adaugarea reutilizeaza
dialogul `frm_articol_factura` de la compunerea facturii (`:16497-16505`).
Inainte de salvare (`inainte_de_do_termin`, `:14329-14386`, activa doar cand
`ofacturare_editare.prg` e incarcat si `tvd` exista), pentru fiecare linie activa din `tvd`: opreste
salvarea daca are cantitate <= 0, pret nul sau nu are articol asociat; cere confirmare daca o linie
noua are pretul de achizitie 0, respectiv daca toate liniile facturii au fost sterse.
## Implicatii practice ## Implicatii practice
- Codul (`cod`) unui document din Registrul Jurnal NU e stabil dupa modificare/anulare - se schimba - Codul (`cod`) unui document din Registrul Jurnal NU e stabil dupa modificare/anulare - se schimba
@@ -51,3 +158,8 @@ ruleaza intr-o tranzactie manuala unica (commit sau rollback pe amandoua).
- Regasirea documentului editat se face dupa `id_fact` (sau alt marcaj stabil), niciodata dupa `cod`. - Regasirea documentului editat se face dupa `id_fact` (sau alt marcaj stabil), niciodata dupa `cod`.
- Randurile `sters = 1` ramase in `ACT`/`RUL`/`RUL_OBINV` dupa o modificare sunt normale (istoric), - Randurile `sters = 1` ramase in `ACT`/`RUL`/`RUL_OBINV` dupa o modificare sunt normale (istoric),
nu date corupte sau duplicate de curatat. nu date corupte sau duplicate de curatat.
- Editarea unei facturi de vanzare (document cu rand in `VANZARI`) reface si liniile si totalurile
denormalizate din `VANZARI`/`VANZARI_DETALII`, in aceeasi tranzactie cu nota - vezi ramura de mai
sus.
- Documentele care nu sunt facturi de vanzare nu sunt atinse de aceasta ramura - pagina de articole
nu apare si scrierea in `VANZARI_DETALII` nu se declanseaza (garda: `Reccount('tvanz') = 1`).