ROAFACTURARE 2.11.15 (r18015): programe/ofacturare_editare.prg, programe/ofacturare_stoc.prg. docs: conventia de encoding .sc2/.vc2 corectata la cp1250; cercetarile trans-proiect mutate din ROAFACTURARE in docs/cercetare (r18014); actualizari reguli_lucru, oracle_export, flux-editare-vfp-text, scripturi-migrare-db, flux-modificare-stergere-nota-jurnal, todos. .gitignore: watchdog_out si PNG-urile din rularile headless (r18008). Text FoxBin2Prg regenerat: clase/comun.vc2, ferestre/frm_import_note_facturi_clienti.sc2, ferestre/frm_initializare_facturi_balanta.sc2. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AV7dQbTLAqvrtQbH7zxXxw
166 lines
11 KiB
Markdown
166 lines
11 KiB
Markdown
# Flux: modificare/stergere nota in Registrul Jurnal
|
|
|
|
Comportament CORECT (nu bug): la **modificarea** unei note din Registrul Jurnal, documentul
|
|
original nu se suprascrie. Se marcheaza `sters = 1` pe randurile vechi (`ACT`/`RUL`/`RUL_OBINV`),
|
|
apoi se scrie un document NOU cu alt `cod`, pastrand acelasi `id_fact`/`id_factd`. Ambele operatii
|
|
ruleaza intr-o tranzactie manuala unica (commit sau rollback pe amandoua).
|
|
|
|
## Unde
|
|
|
|
- `afisjurcom.do_modifica` - `COMUN\clase\comun.vc2:2222-2562`. Deschide tranzactia manuala
|
|
(`Thisform.do_deschide_tranzactie()`, linia 2448), apoi `oscrie_in_fisiere(2,...)` = STERGE
|
|
(linia 2451), apoi `oscrie_in_fisiere(0,...)` = SCRIE (linia 2479), apoi
|
|
`pack_contafin.finalizeaza_modificare_nota(...)` (2484-2486), apoi
|
|
`Thisform.do_inchide_tranzactie(...)` (linia 2535) - commit daca tot ce a rulat inainte a
|
|
reusit, rollback altfel.
|
|
- `do_deschide_tranzactie`/`do_inchide_tranzactie` (`_frmbase`, `COMUN\clase\_frm_base.vc2:252,279`;
|
|
varianta identica ca procedura globala in `COMUN\programe\oproceduri_rulaje.prg:287,303`):
|
|
`SQLSetProp(gnHandle,'Transactions',2)` la deschidere, `SQLCOMMIT`/`SQLROLLBACK` +
|
|
`SQLSetProp(...,'Transactions',1)` la inchidere.
|
|
- `oscrie_in_fisiere.prg` (`COMUN\programe\oscrie_in_fisiere.prg`): `tnScrie_Sterge` 0=scriere,
|
|
2=stergere. Apeleaza server-side `pack_contafin.init_scriere_act_rul_local` +
|
|
`final_scriere_act_rul_local` -> `finalizeaza_scriere_act_rul`, care ruleaza `SCRIE_IN_ACT`
|
|
(scriere) sau `STERGE_DIN_ACT` (stergere) din `PACK_CONTAFIN.pck`.
|
|
- `PACK_CONTAFIN.STERGE_DIN_ACT` (`COMUN\docs\PACK_CONTAFIN.pck:1815-1859`):
|
|
`UPDATE ACT SET STERS = 1 ... WHERE COD = tnCod` - marcheaza vechiul document, pe `cod`-ul vechi.
|
|
- `PACK_CONTAFIN.SCRIE_IN_ACT` (`PACK_CONTAFIN.pck:630-901`): `LN_COD := pack_contafin.GET_COD()`
|
|
(linia 648) aloca un `cod` nou; `UPDATE ACT_TEMP SET COD = LN_COD, ...` (linia 897) il scrie pe
|
|
noul document - `ID_FACT` nu e atins, ramane cel din documentul original.
|
|
- `PACK_CONTAFIN.finalizeaza_modificare_nota` (`PACK_CONTAFIN.pck:8601-8651`): aloca din nou
|
|
`lnCodNou := pack_contafin.get_cod()` si actualizeaza pe codul nou `vanzari`
|
|
(`pack_facturare.actualizeaza_vanzari`) si `atasamente_vanzari`. `nom_lucrari` se actualizeaza
|
|
DOAR pentru `id_set IN (31003,31004,31005,31011)` (repune `id_fact`), nu general. `gest_inventar`
|
|
NU se leaga de `cod`-ul nou - se identifica dupa `dataora_validat + an + luna` (cazul
|
|
`id_set = 90101`, note de inventariere).
|
|
|
|
## Atentie: nu e valabil la fel pentru stergerea simpla
|
|
|
|
`afisjurcom.do_sterge` (`comun.vc2:2565-2724`) ofera doua optiuni (`xmenu`, linia 2625):
|
|
- **Stergere document** (`lnOptiune = 1`): DOAR `OSCRIE_IN_FISIERE(2,...)` + `finalizeaza_stergere_nota`
|
|
- marcheaza `sters = 1`, NU se creeaza document nou.
|
|
- **Anulare document** (`lnOptiune = 2`): STERGE (linia 2698) + SCRIE (linia 2709, cu sumele puse pe
|
|
0) - creeaza si document nou, la fel ca la modificare - dar aici cele doua apeluri NU sunt
|
|
invelite intr-o tranzactie manuala comuna (nu apare `do_deschide_tranzactie`/
|
|
`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`).
|
|
|
|
## 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
|
|
|
|
- Codul (`cod`) unui document din Registrul Jurnal NU e stabil dupa modificare/anulare - se schimba
|
|
la fiecare editare. Cod hardcodat sau retinut dintr-o executare anterioara devine invalid.
|
|
- 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),
|
|
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`).
|