Files
roafacturare/docs/cercetare/audit_vanzari_creare_modificare_stergere.md
2026-09-09 22:19:22 +03:00

17 KiB

Cercetare: coloane de audit pe VANZARI / VANZARI_DETALII (creare/modificare/stergere)

Status: COMPLET (read-only)

Intrebare

Marius cere pentru audit, pe documentele de facturare: data crearii, utilizatorul crearii, data modificarii si utilizatorul modificarii (daca e cazul), data stergerii si utilizatorul stergerii (daca e cazul).

1. Ce exista deja (structura DB)

Interogat direct all_tab_columns pe ROA_CENTRAL (schema live).

VANZARI — coloane relevante pentru audit:

Coloana Tip Nullable Rol
ID_UTIL NUMBER NOT NULL utilizatorul crearii — completat la fiecare INSERT
DATAORA DATE NOT NULL data/ora crearii — completat la fiecare INSERT
STERS NUMBER NOT NULL flag sters (0/1)
ID_UTILS NUMBER NULL utilizatorul care a sters — completat doar la stergere
DATAORAS DATE NULL data/ora stergerii — completata doar la stergere
DATA_ACT DATE NULL data contabila/de inregistrare (propaga in ACT, DOCUMENTE, JV2007, RUL), NU e "data modificarii" — vezi sectiunea 2
DATA_FACTURAT, ID_UTILFACT DATE / NUMBER NULL specifice actiunii "facturare din aviz", nu audit general pe document
DATAORA_EXP DATE NOT NULL data expedierii/listarii, nu e audit de scriere
DATAORA_DESCARCAT DATE NULL data descarcarii gestiunii, nu e audit de scriere
DATA_SCAD DATE NULL data scadenta, nimic de audit

Nu exista nicio coloana dedicata "utilizator modificare" / "data modificare" pe VANZARI (gen ID_UTIL_MODIF / DATA_MODIF). DATA_ACT a fost verificata explicit in cod (EXPORT:14439-14500, modifica_date_factura) si e o data contabila propagata in ACT/DOCUMENTE/ JV2007/RUL, nu un marcaj de audit "cine/cand a modificat".

Conventia casei (adaugat, verificat de sesiunea principala): VANZARI are deja tiparul o pereche utilizator+data per eveniment: ID_UTIL/DATAORA (creare), ID_UTILS/DATAORAS (stergere), ID_UTILFACT/DATA_FACTURAT (facturare din aviz — a treia pereche, omisa din inventarul initial). Cu aceasta a treia pereche vizibila, tiparul e limpede: o pereche noua de "modificare" (ID_UTIL_MODIF/DATA_MODIF sau echivalent) s-ar aseza natural langa celelalte trei, ca nume si ca forma — nu ar fi o conventie noua, ci continuarea uneia deja existente.

VANZARI_DETALII — coloane relevante:

Coloana Tip Nullable Rol
VALIDAT, ID_UTIL_VALID, DATAORA_VALID NUMBER/NUMBER/DATE NULL pe ultimele doua validare, alt concept decat creare
STERS, ID_UTILS, DATAORAS NUMBER/NUMBER/DATE NULL pe ultimele doua stergere linie
DATAORA_DESCARCAT DATE NULL descarcare gestiune

Pe VANZARI_DETALII nu exista nicio coloana de "creare" (nici ID_UTIL, nici DATAORA proprii liniei) — creatorul/data liniei se deduce indirect din antetul VANZARI al documentului parinte.

2. Cine scrie coloanele si cand

Creare (ID_UTIL, DATAORA pe VANZARI): scrise o singura data, la INSERT INTO VANZARI din PACK_FACTURARE.scrie_in_vanzari (EXPORT:13598-13640), apelata pe drumul principal de emitere (scrie_factura2, EXPORT:6020 -> lantul de finalizeaza_*). Valorile vin din pack_facturare.nid_util si V_DATAORA — utilizatorul si momentul sesiunii curente la INSERT. Exista un al doilea INSERT INTO VANZARI (EXPORT:14930, in finalizeaza_avize_lucrare, EXPORT:14854-...) — ruta specifica avizelor de lucrare, tot cu ID_UTIL/DATAORA completate la INSERT. Ambele rute de emitere completeaza consecvent aceste doua coloane — nu s-a gasit niciun INSERT in VANZARI care sa le lase NULL.

Nu exista niciun UPDATE VANZARI SET ID_UTIL = ... sau SET DATAORA = ... in tot pachetul (cautare directa, zero rezultate) — deci, in afara de INSERT-ul initial, aceste doua coloane nu sunt niciodata rescrise pe randul existent. Coerent cu design-ul de azi: singura cale de "modificare" a antetului identitar e modifica_date_factura (care NU atinge ID_UTIL/DATAORA, doar serie/numar/ data/scadenta/delegat/etc., vezi plan_13...md:796-801), sau stergere+reemitere ca document nou.

Stergere (ID_UTILS, DATAORAS, STERS): scrise consecvent in ambele proceduri de stergere:

  • sterge_factura (EXPORT:5432-5607): UPDATE VANZARI SET STERS = V_STERS, ID_UTILS = V_ID_UTIL, DATAORAS = V_DATAORA WHERE ID_VANZARE = ... (EXPORT:5496-5499) si acelasi tipar pe VANZARI_DETALII (EXPORT:5560-5564), pe COMENZI_ELEMENTE si CTR_RATE_FACTURI cand e cazul.
  • sterge_proforma (EXPORT:5610-...): acelasi tipar (verificat header-ul procedurii; corpul complet urmeaza acelasi model de UPDATE ... SET STERS/ID_UTILS/DATAORAS).

Concluzie punct 2: coloanele existente sunt scrise consecvent pe toate rutele identificate — nu exista ruta de creare care sa lase ID_UTIL/DATAORA NULL, nici ruta de stergere care sa sara peste ID_UTILS/DATAORAS.

CORECTIE (verificata de sesiunea principala, nu de mine): afirmatia initiala "#6 nu atinge niciun camp de audit" era gresita pentru VANZARI_DETALII. Pe partea de nota contabila (pack_contafin.finalizeaza_modificare_nota, apelat din oscrie_in_fisiere) ramane adevarat ca se realiniaza doar VANZARI.COD prin actualizeaza_vanzari (COMUN\docs\flux-modificare-stergere-nota-jurnal.md:95), iar VANZARI.ID_FACT "nu e atins de niciun pas al secventei" (:101-102) — dar editarea liniilor de factura din #6 (COMUN\programe\ofacturare_editare.prg) scrie id_utils/dataoras pe VANZARI_DETALII, in trei locuri:

  • ofacturare_editare.prg:492-494 — marcarea unei linii ca stearsa: sters = 1 impreuna cu id_utils/dataoras. Aici folosirea corespunde exact semanticii "stergere".
  • ofacturare_editare.prg:501-505 — UPDATE vanzari_detalii SET sters = 0, cantitate = ..., pret = ..., id_utils = ..., dataoras = sysdate — perechea de "stergere" e scrisa odata cu sters = 0, deci pe un rand viu, nesters.
  • ofacturare_editare.prg:522-525 — INSERT INTO vanzari_detalii (..., id_utils, dataoras) VALUES (...) — perechea e populata pe un rand proaspat inserat, care nu a fost sters niciodata.

Concluzia corecta: in codul livrat al lui #6, perechea ID_UTILS/DATAORAS pe VANZARI_DETALII e folosita ca marcaj "cine a umblat ultima data pe linia asta", nu strict ca "sters de/la". Consecinta pentru orice raport de audit: ID_UTILS/DATAORAS NU pot fi citite ca "sters de/la" fara sa se puna si STERS in conditie — altfel liniile adaugate sau modificate la o editare (nesterse) apar gresit drept sterse. Pe VANZARI (antet), ramane adevarat ca #6 atinge doar COD — nu s-a gasit nicio scriere pe ID_UTIL, DATAORA, DATA_ACT, ID_UTILS sau DATAORAS la nivel de antet in acest flux.

3. Ce se intampla la regenerare (stergere + reemitere, #13 / S9)

Important: acest mecanism NU e inca implementat. Descrierea "stergere + reemitere" e planul #13, sectiunea S9 (docs\plan_13_unificare_formular_facturare.md:3484-3568), marcata "PROIECTAT" / "VERIFICAT ca e realizabila", nu cod livrat. Feature-ul aflat azi in lucru pe branch-ul curent (#6) e alt mecanism (editare la nivel de linie de nota, sectiunea 2 mai sus), nu regenerare.

Raspuns la intrebarea critica: DA, se pierde, exact cum ai suspectat.

Mecanismul S9, asa cum e proiectat: documentul vechi primeste soft-delete (sterge_factura, ca azi) -> ID_UTILS/DATAORAS ale randului vechi devin utilizatorul/momentul editarii (corect, asta chiar e semantica lor). Documentul nou se scrie pe acelasi drum de emitere ca la creare (scrie_factura2 -> scrie_in_vanzari -> INSERT INTO VANZARI, sectiunea 2 de mai sus) — acelasi INSERT care completeaza ID_UTIL/DATAORA din utilizatorul si momentul curente. Niciun pas din S9 nu citeste sau transporta ID_UTIL/DATAORA ale documentului vechi catre cel nou — cautare directa in tot planul (ID_UTIL , DATAORA ) nu gaseste nicio mentiune a preservarii lor la regenerare. Deci, cu proiectarea de azi a S9: "data crearii" a documentului reemis devine data regenerarii, iar "utilizatorul crearii" devine cel care a declansat editarea — informatia despre cine/cand a fost creat initial documentul se pierde tacut, exact temerea din brief.

Atenuare (verificata de sesiunea principala): pierderea nu e totala, ci reconstruibila din lant, nu direct pe document. Randul vechi ramane in tabel cu STERS = 1 si cu ID_UTILS/ DATAORAS completate — iar acea stergere este momentul modificarii. Cum ID_FACT se pastreaza peste regenerare (sectiunea E/S9 mai jos), un raport de audit poate urca lantul ID_FACT -> gasi randul vechi sters -> citi DATAORA/ID_UTIL de pe acela ca fiind "data/utilizator crearii originale". Asta atenueaza, dar nu inlocuieste o pereche explicita: cere parcurgerea lantului de randuri sterse in loc de o citire directa pe documentul curent, si se rupe daca vreodata ID_FACT nu mai e pastrat identic (de exemplu la o a doua regenerare, daca lantul nu ramane liniar).

Precedentul ID_FACT exista si e citat corect in brief, si arata ca problema e cunoscuta ca tipar — dar rezolvata doar pentru ID_FACT, nu si generalizata la audit. Planul dedica un mecanism explicit ca sa evite pierderea lui ID_FACT:

  • Sectiunea E (:762-789): cerinta explicita ("documentul reemis pastreaza ID_FACT"), verificarea ca azi secventa l-ar regenera necondiționat, si decizia sa fie citit din documentul vechi inainte de stergere si impus celui nou.
  • S9 (:3505-3538): mecanismul concret — "ID_FACT se citeste inainte de stergere ... si se impune documentului nou, printr-un comutator folosit numai de regenerare"; plus tot efortul de a ocoli coliziunea ORA-00001 pe PK_DOCUMENTE cand se refoloseste acelasi ID_FACT.

Acelasi tipar de mecanism ("citeste din vechi inainte de stergere, transporta explicit la INSERT-ul nou") ar fi necesar si pentru ID_UTIL/DATAORA daca se vrea pastrata "data/utilizator creare originala" — dar acest pas nu exista nicaieri in plan azi. Nu e o eroare de implementare, e un gol de cerinta: planul #13 nu a fost scris cu "pastreaza si audit-ul de creare" ca obiectiv: sectiunea 1 a acestui raport (plan_13...md:1462-1467) chiar foloseste ID_UTILS/DATAORAS NULL ca dovada ca "nicio editare ulterioara nu s-a inregistrat" pe o factura din 2026 — ceea ce arata ca autorii planului tratau deja ID_UTILS/DATAORAS (stergere) ca semnal indirect de "a fost editat", dar fara sa discute explicit soarta lui ID_UTIL/DATAORA (creare) la regenerare.

4. Ce lipseste din cele sase cerute de Marius

Cerut Exista azi? Observatie
Data crearii DA — VANZARI.DATAORA Scrisa consecvent la INSERT (sectiunea 2). Sub #13/S9 asa cum e proiectat azi, s-ar suprascrie tacit la fiecare regenerare (sectiunea 3) — nimic nu o transporta din documentul vechi.
Utilizatorul crearii DA — VANZARI.ID_UTIL Idem: scris consecvent la INSERT, dar s-ar pierde la regenerare sub #13/S9 asa cum e proiectat azi.
Data modificarii (daca e cazul) NU exista coloana dedicata pe antet (VANZARI) Nu exista DATA_MODIF/echivalent. DATA_ACT exista dar e data contabila, nu audit. Pe VANZARI (antet), #6 nu scrie nimic. Pe VANZARI_DETALII (linie), #6 scrie dataoras chiar si pe randuri nesterse (ofacturare_editare.prg:501-505,522-525) — semnal de "ultima atingere", dar suprapus peste semantica de stergere, nu o coloana proprie de modificare. Sub #13/S9, singurul semnal indirect pe antet ar fi DATAORAS a randului vechi (marcat sters) — reconstruibil prin lant (vezi atenuarea din sectiunea 3), nu direct pe documentul curent.
Utilizatorul modificarii (daca e cazul) NU exista coloana dedicata pe antet (VANZARI) Acelasi rationament — nu exista ID_UTIL_MODIF. Pe VANZARI_DETALII, #6 scrie id_utils si pe randuri nesterse (acelasi loc de mai sus), cu aceeasi suprapunere peste semantica de stergere. Pe antet, #13/S9 ar lasa doar ID_UTILS pe randul vechi (sters), reconstruibil prin lant, nu pe cel curent.
Data stergerii DA — VANZARI.DATAORAS Scrisa consecvent in sterge_factura si sterge_proforma (sectiunea 2).
Utilizatorul stergerii DA — VANZARI.ID_UTILS Idem, scris consecvent.

Rezumat: 4 din 6 cerinte au deja coloana dedicata si scriere consecventa pe antet (creare x2, stergere x2) — dar cele doua de "creare" sunt fragile fata de regenerarea planificata in #13, riscand sa fie suprascrise silentios daca S9 nu adauga un pas explicit de transport (dupa modelul deja folosit pentru ID_FACT), atenuat de faptul ca raman reconstruibile prin lant (sectiunea 3). Cele doua de "modificare" nu au coloana proprie pe antet: pe VANZARI nici azi (#6 atinge doar COD), nici in proiectarea #13 (regenerarea confunda "modificare" cu "creare noua" + "stergere veche"); pe VANZARI_DETALII, #6 reutilizeaza ID_UTILS/DATAORAS ca semnal de "ultima atingere" chiar pe linii nesterse — util ca indiciu, dar ambiguu fara STERS in conditie, si tot nu e o pereche explicita de "modificare" pe care un raport sa o citeasca direct fara ambiguitate.

Verificat direct vs dedus vs neacoperit

Nota de provenienta: sectiunile 1-2 si structura raportului sunt cercetarea mea initiala. Corectia despre ofacturare_editare.prg:492-494,501-505,522-525 (sectiunea 2, editarea #6 pe VANZARI_DETALII), perechea ID_UTILFACT/DATA_FACTURAT (sectiunea 1) si atenuarea prin lant ID_FACT (sectiunea 3) au fost verificate si furnizate de sesiunea principala, nu de mine — le-am integrat ca atare, marcate explicit in text la locul lor.

Verificat direct (citit in cod / rulat pe DB):

  • Structura all_tab_columns pentru VANZARI si VANZARI_DETALII (interogare live pe ROA_CENTRAL, sectiunea 1) — a mea; reconfirmata independent de sesiunea principala, inclusiv filtrarea explicita pe %MODIF% (zero rezultate).
  • INSERT INTO VANZARI din scrie_in_vanzari (EXPORT:13598-13640) si al doilea din finalizeaza_avize_lucrare (EXPORT:14930) — sursa lui ID_UTIL/DATAORA — a mea.
  • Zero rezultate la cautarea UPDATE VANZARI SET ... ID_UTIL/DATAORA in tot pachetul — confirmat prin grep direct pe fisierul export — a mea.
  • sterge_factura complet (EXPORT:5432-5607) — scrierea STERS/ID_UTILS/DATAORAS pe VANZARI (:5496-5499) si VANZARI_DETALII (:5560-5564) — a mea.
  • modifica_date_factura (EXPORT:14439-14500) — confirmat ca DATA_ACT e propagata catre ACT/DOCUMENTE/JV2007/RUL, deci e data contabila, nu audit — a mea.
  • COMUN\docs\flux-modificare-stergere-nota-jurnal.md:95,101-102 — editarea #6 (nota contabila) atinge doar VANZARI.COD, nu ID_FACT, si nu s-a gasit nicio scriere pe coloanele de audit de antet in acel flux — a mea, ramane corecta doar pentru VANZARI, nu pentru VANZARI_DETALII.
  • ofacturare_editare.prg:492-494, 501-505, 522-525 — scrierea id_utils/dataoras pe VANZARI_DETALII, inclusiv pe randuri nesterse — a sesiunii principale, eu nu am citit acest fisier (nu era in perimetrul cercetarii initiale, care s-a concentrat pe pachetul PL/SQL).
  • Sectiunile E si S9 din docs\plan_13_unificare_formular_facturare.md (mecanismul de pastrare a ID_FACT) si absenta oricarei mentiuni ID_UTIL/DATAORA in tot documentul (cautare directa, singurele hit-uri sunt in alt context, sectiunea 1 din acest raport) — a mea.

Dedus (nu verificat direct, dar sustinut de dovezile de mai sus):

  • Ca S9, DACA se implementeaza exact cum e proiectat azi in plan, ar suprascrie ID_UTIL/DATAORA la regenerare — dedus din faptul ca reemiterea foloseste acelasi INSERT INTO VANZARI ca emiterea normala, si niciun pas de transport nu e mentionat in plan. Nu exista inca implementare de rulat.
  • sterge_proforma (EXPORT:5610-...) urmeaza acelasi tipar ca sterge_factura — verificat doar header-ul si inceputul; nu am citit tot corpul procedurii linie cu linie (structura generala insa se potriveste, fiind aceeasi familie de proceduri din acelasi pachet).

Neacoperit:

  • Nu am verificat daca exista si alte cai de INSERT/UPDATE pe VANZARI in afara PACK_FACTURARE (de exemplu PACK_MIGRARE, migrari istorice) care ar putea lasa ID_UTIL/DATAORA NULL sau cu alta semantica pe date vechi — nu era in scopul intrebarii (audit pe fluxul curent). plan_13...md:844-847 mentioneaza ca a existat deja o cautare exhaustiva pe toate UPDATE VANZARI (13 aparitii) in runda 7, dar cu alt scop (antet, nu audit) — nu am reluat-o eu.
  • Nu am verificat daca exista rapoarte/ecrane in aplicatie care deja afiseaza vreuna din aceste coloane catre utilizator (relevant pentru UX, nu pentru intrebarea de audit DB pusa aici).
  • Nu am rulat interogari pe date reale (cate facturi au ID_UTILS/DATAORAS populate azi in productie) — brief-ul cerea structura si rutele de scriere, nu statistici.