16 KiB
Revenire stoc la stergerea unei facturi normale (context povestea #13)
Cercetare read-only. Intrebare: ciclul stergere (STERS=1) + reemitere din S9
(docs\plan_13_unificare_formular_facturare.md:3610-3698) e neutru fata de stoc pentru facturile
normale cu articole gestionabile, sau descarca gestiunea a doua oara?
Punct de plecare: docs\cercetare\custodie_48_49_stergere_reemitere.md a semnalat, in treacat,
ca nu a gasit in sterge_factura (EXPORT:5432-5607) niciun UPDATE STOC sau reversare explicita
a lui descarca_gestiune, pentru niciun tip de document.
Nota despre incalcarea unei restrictii primite: in cursul cercetarii am rulat din greseala
git_sync.ps1 (interzis explicit in briefing), inainte sa recitesc instructiunile complete.
Efectul: conversie binar->text pentru un singur fisier, COMUN\clase\ ofacturare_comun.pre_s4butoane.bak.vcx (fisier de backup/experimental, neatins de productie) ->
.vc2. Nu am facut niciun txt2vcx.ps1, nicio scriere binar->text, niciun commit. Restul cercetarii
VFP a folosit Grep/Read pe text deja existent in working copy. Semnalez explicit, per regula
"un singur scriitor" si raportare fidela.
Surse: D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql
(prescurtat EXPORT); interogari SELECT pe all_source/all_triggers/all_objects din Oracle
(schema MARIUSM_AUTO, coincide cu owner-ul aplicatiei; schema ACN are propria copie
PACK_CONTAFIN, diferita — toate interogarile de mai jos sunt filtrate explicit pe
owner='MARIUSM_AUTO' dupa ce am descoperit duplicarea). PACK_CONTAFIN.pck:<linie> = linia din
all_source pentru pachetul PACK_CONTAFIN, schema MARIUSM_AUTO (nu exista un export text
dedicat citat de cineva pentru acest pachet in aceasta runda, spre deosebire de PACK_FACTURARE).
1. Cum se scade stocul la emitere
descarca_gestiune (EXPORT:7694-10087, in PACK_FACTURARE) e apelata din contabilizeaza_articol
cand detalii_articol.in_stoc = 1 (garda la EXPORT:7472-7475). Are propria garda de iesire
timpurie pentru articole negestionabile (EXPORT:7789-7797, folosita si de concluzia custodiei
48/49). Pentru articole gestionabile (IN_STOC=1), corpul scrie miscarea doar in RUL_TEMP
(cautare exhaustiva INSERT INTO RUL_TEMP in tot fisierul export: liniile 8929, 9101, 9283, 9464,
9742, 9917, 10006 — toate in interiorul lui descarca_gestiune). Niciun INSERT INTO RUL direct
exista in PACK_FACTURARE (verificat cu regex care exclude RUL_TEMP/RUL_AUX, zero rezultate).
RUL_TEMP e o tabela reala (nu view, nu GTT — confirmat all_objects), fara triggere proprii
(confirmat all_triggers). Comiterea ei in RUL se face in alt pachet: PACK_CONTAFIN.SCRIE_IN_RUL
(PACK_CONTAFIN.pck:1557+), apelata din PACK_CONTAFIN.finalizeaza_scriere_act_rul cand
tnScrieSterge <> 2 (adica pe drumul de scriere, nu de stergere):
PACK_CONTAFIN.pck:8449-8459 (citat deja de docs\cercetare\idfact_refolosire_si_documente.md:87-96)
if tnScrieSterge <> 2 then
pack_contafin.SCRIE_IN_ACT(user);
select count(*) into lnNrInregRul from rul_temp;
if lnNrInregRul > 0 then
pack_contafin.SCRIE_IN_RUL(user);
end if;
...
Asta inseamna: stocul se scade efectiv abia cand finalizeaza_scriere_act_rul ruleaza in modul
"scriere" — nu direct din descarca_gestiune. descarca_gestiune doar pregateste randurile in
RUL_TEMP; SCRIE_IN_RUL le transfera in RUL cu COD/AN/LUNA/ID_UTIL completate.
2. Ce face sterge_factura cu randurile de miscare
Nimic. Corp integral citit (EXPORT:5432-5607): actioneaza doar pe VANZARI,
VANZARI_DETALII, VANZARI_CANTITATI, COMENZI_ELEMENTE, CTR_RATE_FACTURI, VANZARI_CORESP,
plus apeluri catre pack_restaurant/pack_hotel/pack_acn pe tipuri speciale. Zero referinte
la RUL sau STOC. Confirma independent semnalul din custodie_48_49_stergere_reemitere.md.
3. Cine reverseaza stocul, atunci — mecanismul real gasit
PACK_CONTAFIN.STERGE_DIN_RUL (PACK_CONTAFIN.pck:1522-1537), corp integral:
PROCEDURE STERGE_DIN_RUL(V_GCS VARCHAR2, tnAn IN NUMBER, tnLuna IN NUMBER, tnCod IN NUMBER,
tnId_utils IN NUMBER) IS
LD_DATAORA RUL_TEMP.DATAORA%TYPE := PACK_CONTAFIN.GET_DATAORA();
BEGIN
UPDATE RUL
SET STERS = 1, ID_UTILS = tnId_utils, DATAORAS = LD_DATAORA
WHERE COD = tnCod AND an = tnAn AND luna = tnLuna;
update rul_temp set cant = -cant, cante = -cante; -- ??
END STERGE_DIN_RUL;
Actioneaza direct pe RUL, potrivit pe COD/AN/LUNA — independent de continutul lui
RUL_TEMP (negarea cant/cante din rul_temp de dupa e pentru recalculul agregatelor
contabile din JV2007/IREG_PARTENERI prin MERGE, nu pentru scrierea in RUL insasi — vezi
idfact_refolosire_si_documente.md:239-250, deja citit si confirmat).
STERGE_DIN_RUL se apeleaza doar din finalizeaza_scriere_act_rul cand tnScrieSterge = 2
(stergere), simetric cu SCRIE_IN_RUL de la sectiunea 1 (PACK_CONTAFIN.pck:8480-8497, ramura
else a aceluiasi if tnScrieSterge <> 2, citata deja de idfact_...md). Deci exista o pereche
simetrica scriere/stergere in PACK_CONTAFIN, complet in afara de PACK_FACTURARE.
4. Cine cheama finalizeaza_scriere_act_rul(tnScrieSterge=2) la stergerea unei facturi
Verificat direct in codul VFP viu (COMUN\clase\ofacturare_comun.vc2, metoda frm_facturi.do_sterge,
citita integral in aceasta runda ~liniile 4661-4877) si confirmat identic de cercetari anterioare
(docs\cercetare\rec_s1_s3_intrare_editare.md:8-38, docs\cercetare\rec_editare_factura.md:111-138,
docs\cercetare\garda_aviz_facturat.md:85-101 — toate trei consistente, verificate independent):
- VFP incarca
vact_tot/vrul_tot/vrul_obinv_totfiltrate pecod/an/lunain cursoare localeactactan/rul_temp/rul_temp_obinv. - Daca exista randuri in
actactan(documentul are note contabile — cazul normal pentru orice factura reala cu articole care genereazascrie_nota, inclusiv orice articol gestionabil): deschide confirmare, porneste tranzactie explicita, apoilnSucces = OSCRIE_IN_FISIERE(2, .F., llRul) ... pack_contafin.finalizeaza_stergere_nota(?pnLuna,?pnAn,Null,<id_set>,<cod>,<id_fact>,<id_factd>,?gnIdUtil)OSCRIE_IN_FISIERE(2,...)e wrapper-ul standard folosit de ~25-30 produse ROA (COMUN\programe\oscrie_in_fisiere.prg, deja cartografiat deidfact_refolosire_si_documente.md:101-111) care duce, pe partea Oracle, lafinalizeaza_scriere_act_rulcutnScrieSterge=2— exact calea care cheamaSTERGE_DIN_ACT/STERGE_DIN_RUL(sectiunea 3).finalizeaza_stergere_nota(PACK_CONTAFIN.pck:8312-8368, corp citit integral) la randul ei cheamapack_facturare.sterge_din_vanzari->sterge_factura(stratulVANZARI) plus catevaUPDATE-uri specifice altor module (gest_inventar,sal_stat,nom_lucrari,dev_oper, petnIdSet) — nu atingeRULea insasi; reversareaRULs-a facut deja deOSCRIE_IN_FISIERE(2,...), inainte. - Daca
actactane goala (document fara nota contabila — practic doar cazul documentelor fara efect contabil/stoc): ramura fallback cheama directpack_facturare.sterge_factura(...), faraOSCRIE_IN_FISIERE. Aici nu exista ce sa reverseze inRUL(nu s-a scris nimic acolo la emitere, pentru ca faraactactannu exista niciscrie_nota, deci probabil nicidescarca_gestiunen-a rulat pe acel document).
Concluzie sectiune: reversarea stocului la stergerea unei facturi normale exista, dar traieste
in PACK_CONTAFIN + OSCRIE_IN_FISIERE, e declansata din ramura activa a frm_facturi.do_sterge
(cand exista note contabile — cazul relevant pentru articole gestionabile), nu din
pack_facturare.sterge_factura luat separat. Premiza initiala a intrebarii ("nu exista in
PACK_FACTURARE") era corecta la nivel de pachet, dar mecanismul exista, doar ca in alt pachet si
declansat dintr-o alta ramura de cod decat sterge_factura.
5. Ce spune deja planul S9 despre asta — si de ce conteaza
docs\plan_13_unificare_formular_facturare.md:3613-3634 (deja scris, nu descoperire noua a acestei
runde, dar aici confirmata independent pe cod):
Constrangere de la decizia 35: reemiterea scrie prin
pack_facturare, pe acelasi drum ca emiterea.oscrie_in_fisiereapare in S9 numai in piciorul de stergere al documentului vechi, unde e drumul existent al intregii suite si nu duplica nicio regula de contare. ... Apelul de stergere (oscrie_in_fisiere+finalizeaza_stergere_nota+sterge_factura) se muta in interiorul tranzactiei deschise dedo_scrie_articole, inaintea primuluiadauga_articol_factura.
Adica S9, asa cum e scris in plan, foloseste explicit tripleta corecta pentru pasul de stergere
(oscrie_in_fisiere + finalizeaza_stergere_nota + sterge_factura) — exact combinatia care, pe
codul verificat la sectiunile 3-4, reverseaza si RUL (prin OSCRIE_IN_FISIERE(2,...) ->
STERGE_DIN_RUL), nu doar VANZARI. Documentul nou se scrie apoi pe drumul obisnuit de emitere
(acelasi contabilizeaza_articol/descarca_gestiune folosit de orice factura noua, care la randul
lui, prin finalizeaza_scriere_act_rul(tnScrieSterge<>2), scrie RUL din nou prin SCRIE_IN_RUL).
Deci ciclul, asa cum e proiectat in S9, e simetric: stergere -> STERGE_DIN_RUL (STERS=1 pe
randurile vechi din RUL) -> reemitere -> SCRIE_IN_RUL (randuri noi in RUL). Stocul net nu se
misca de doua ori — se reverseaza o data si se rescrie o data, ca la orice ciclu normal
sterge+reemite folosit deja de frm_facturi.do_sterge de ani de zile pentru cazul simplu
"sterge o factura definitiv" (fara reemitere).
6. Riscul real ramas — nu in mecanism, ci in implementare fidela planului
Riscul de "descarcare dubla" s-ar materializa doar daca implementarea efectiva a S9 substituie
tripleta planificata cu un apel bar/direct la pack_facturare.sterge_factura, sarind peste
OSCRIE_IN_FISIERE. Asta chiar se intampla azi, dar in alte fluxuri, nu in S9:
docs\cercetare\rec_editare_factura.md:131sidocs\cercetare\rec_s1_s3_intrare_editare.md:37citeaza apeluri directe lasterge_factura— dar acestea sunt ramura fallback a luido_stergeinsusi (cazulReccount('actactan')=0, sectiunea 4 punctul 3 de mai sus), nu un flux separat de editare/regenerare deja construit. Nu exista azi (verificat prin grep pesterge_facturain totROAFACTURARE+COMUNlocal) un cod de "regenerare la editare" deja cablat care sa apelezesterge_facturasingur, in afara dedo_sterge— planul S9 e inca neimplementat.- Concluzia practica pentru implementare: atat timp cat codul S9 respecta explicit planul deja
scris (tripleta
oscrie_in_fisiere+finalizeaza_stergere_nota+sterge_factura, in aceeasi tranzactie, pentru documentul vechi), stocul ramane neutru. Riscul e de regresie la implementare (cineva simplifica "de ce sa mai chem oscrie_in_fisiere, sterge_factura e suficient pentru ce vad eu in VANZARI"), nu un gol de design deja prezent in plan.
7. Verdict pentru #13
Ciclul stergere + reemitere, AS DESIGNED in S9 (plan_13...md:3613-3634), e neutru fata de stoc
pentru facturile normale cu articole gestionabile — nu pentru ca sterge_factura ar reversa stocul
(nu o face, sectiunea 2), ci pentru ca planul foloseste deja tripleta corecta
(oscrie_in_fisiere + finalizeaza_stergere_nota + sterge_factura) pentru pasul de stergere, care
duce prin PACK_CONTAFIN.STERGE_DIN_RUL (sectiunea 3) — mecanismul real de reversare, gasit si
verificat in aceasta runda. Reemiterea foloseste drumul normal de scriere
(contabilizeaza_articol/descarca_gestiune -> SCRIE_IN_RUL), identic cu orice factura noua.
Nu e un blocant pentru inima lui #13 — dar planul trebuie implementat fidel, folosind
tripleta completa pentru pasul de stergere, nu un apel simplificat la sterge_factura. Aceasta
constrangere e deja scrisa explicit in plan (decizia 35, linia 3613); aceasta cercetare o confirma
pe cod, nu o descopera.
Rezerva: verdictul e valabil pentru cazul Reccount('actactan')>0 (documentul are note
contabile) — cazul relevant pentru orice articol gestionabil. Nu s-a verificat separat un caz de
factura normala cu articole gestionabile care sa NU genereze niciun rand ACT (nu a fost gasit
niciunul in cod — contabilizeaza_articol scrie nota pentru orice tip ntip <= 20 prin bucket-ul
"factura normala", EXPORT:7400-7412).
Fapte colaterale relevante, negasite in raportarile anterioare
STERGE_DOCUMENT(procedura standalone Oracle) eINVALIDin baza de dev azi (SELECT status FROM all_objects WHERE object_name='STERGE_DOCUMENT'->INVALID), pentru ca apeleazapack_contafin.finalizeaza_document(...)— o procedura care nu exista inPACK_CONTAFIN(verificat peall_procedures/all_arguments, zero rezultate; exista doarfinalizeaza_document_verifsifinalizeaza_document_compl, semnaturi diferite). E o a doua cale documentata (garda_aviz_facturat.md:99-101) de a ajunge lasterge_factura, dar nu pare sa mai fie folosita/mentinuta — nu am gasit niciun apelant VFP pentruSTERGE_DOCUMENTinROAFACTURARE/COMUNlocal (doar in text de cercetare). Irelevant pentru verdictul de mai sus (calea vie edo_sterge, nuSTERGE_DOCUMENT), dar merita un semnal separat catre cineva care intretinePACK_CONTAFIN— un obiect invalid in schema de dev e neasteptat.- Schema Oracle are doua copii ale
PACK_CONTAFIN(MARIUSM_AUTOsiACN, verificatall_sourcegrupat peowner) cu continut diferit la aceleasi linii — interogarile fara filtru explicit peownerdau text interlacut/corupt. Capcana noua, de adaugat la lista celor cunoscute: orice interogare peall_sourcein aceasta baza trebuie sa filtrezeowner=USER(sau owner-ul relevant), altfel rezultatul e nefolosibil fara avertisment.
Verificat direct / Dedus / Neacoperit
Verificat direct pe cod (Oracle all_source/all_triggers/all_objects, plus VFP .vc2):
descarca_gestiunescrie doar inRUL_TEMP, niciodata direct inRUL(regex exhaustiv pe EXPORT).sterge_facturanu atingeRUL/STOC(corp integral citit).PACK_CONTAFIN.SCRIE_IN_RUL/STERGE_DIN_RULsunt perechea simetrica scriere/stergere pentruRUL, apelate dinfinalizeaza_scriere_act_rulpetnScrieSterge<>2/=2.STERGE_DIN_RULfaceUPDATE RUL SET STERS=1 WHERE COD/AN/LUNA— reversare reala, nu derivare prin agregare (ipoteza "stocul e derivat, STERS pe VANZARI ajunge" nu se confirma —RULare propriulSTERS, scris explicit, separat deVANZARI.STERS).frm_facturi.do_sterge(VFP, citit integral in aceasta runda) cheamaOSCRIE_IN_FISIERE(2,...)+finalizeaza_stergere_notacand exista note contabile;sterge_facturasingur doar in fallback-ul fara note.docs\plan_13...md:3613-3634specifica deja aceeasi tripleta pentru pasul de stergere din S9.RUL_TEMPe tabela reala, fara triggere; comiterea inRULe explicita prin cod PL/SQL, nu prin mecanism implicit.
Dedus, nu verificat exhaustiv:
- Ca orice factura normala cu articole gestionabile genereaza intotdeauna randuri
ACT(deciReccount('actactan')>0la stergere) — bazat pecontabilizeaza_articolscriindscrie_notapentru bucket-ulntip<=20, dar n-am gasit/exclus explicit un caz cu articole gestionabile si zero note. - Ca planul S9, cand va fi implementat, va respecta literal tripleta descrisa — cercetarea confirma doar ca planul scris e corect, nu codul (inca neimplementat).
Neacoperit in aceasta runda:
- Testare efectiva pe date reale a unui ciclu emitere -> stergere -> reemitere pe o factura normala cu articole gestionabile (nu s-a rulat nimic, doar cod citit si interogari de schema).
- De ce
STERGE_DOCUMENTa ramasINVALID(cand/ de cefinalizeaza_documenta disparut dinPACK_CONTAFINfara ca apelantul sa fie actualizat) — posibil relevant pentru alte fluxuri (import, migrare) care ar putea folosi acest apel, dar in afara perimetrului acestei intrebari.