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
240 lines
16 KiB
Markdown
240 lines
16 KiB
Markdown
# 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:
|
|
```sql
|
|
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):
|
|
|
|
1. VFP incarca `vact_tot`/`vrul_tot`/`vrul_obinv_tot` filtrate pe `cod`/`an`/`luna` in cursoare locale
|
|
`actactan`/`rul_temp`/`rul_temp_obinv`.
|
|
2. **Daca exista randuri in `actactan`** (documentul are note contabile — cazul normal pentru orice
|
|
factura reala cu articole care genereaza `scrie_nota`, inclusiv orice articol gestionabil):
|
|
deschide confirmare, porneste tranzactie explicita, apoi
|
|
```
|
|
lnSucces = 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 de
|
|
`idfact_refolosire_si_documente.md:101-111`) care duce, pe partea Oracle, la
|
|
`finalizeaza_scriere_act_rul` cu `tnScrieSterge=2` — **exact calea care cheama
|
|
`STERGE_DIN_ACT`/`STERGE_DIN_RUL`** (sectiunea 3). `finalizeaza_stergere_nota`
|
|
(`PACK_CONTAFIN.pck:8312-8368`, corp citit integral) la randul ei cheama
|
|
`pack_facturare.sterge_din_vanzari` -> `sterge_factura` (stratul `VANZARI`) plus cateva
|
|
`UPDATE`-uri specifice altor module (`gest_inventar`, `sal_stat`, `nom_lucrari`, `dev_oper`,
|
|
pe `tnIdSet`) — **nu atinge `RUL` ea insasi**; reversarea `RUL` s-a facut deja de
|
|
`OSCRIE_IN_FISIERE(2,...)`, inainte.
|
|
3. **Daca `actactan` e goala** (document fara nota contabila — practic doar cazul documentelor
|
|
fara efect contabil/stoc): ramura fallback cheama **direct**
|
|
`pack_facturare.sterge_factura(...)`, fara `OSCRIE_IN_FISIERE`. Aici nu exista ce sa reverseze
|
|
in `RUL` (nu s-a scris nimic acolo la emitere, pentru ca fara `actactan` nu exista nici
|
|
`scrie_nota`, deci probabil nici `descarca_gestiune` n-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_fisiere` apare 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 de `do_scrie_articole`, inaintea primului `adauga_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:131` si `docs\cercetare\rec_s1_s3_intrare_editare.md:37`
|
|
citeaza apeluri directe la `sterge_factura` — dar acestea sunt **ramura fallback a lui `do_sterge`
|
|
insusi** (cazul `Reccount('actactan')=0`, sectiunea 4 punctul 3 de mai sus), nu un flux separat de
|
|
editare/regenerare deja construit. Nu exista azi (verificat prin grep pe `sterge_factura` in tot
|
|
`ROAFACTURARE`+`COMUN` local) un cod de "regenerare la editare" deja cablat care sa apeleze
|
|
`sterge_factura` singur, in afara de `do_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) e `INVALID` in baza de dev azi**
|
|
(`SELECT status FROM all_objects WHERE object_name='STERGE_DOCUMENT'` -> `INVALID`), pentru ca
|
|
apeleaza `pack_contafin.finalizeaza_document(...)` — o procedura care **nu exista** in
|
|
`PACK_CONTAFIN` (verificat pe `all_procedures`/`all_arguments`, zero rezultate; exista doar
|
|
`finalizeaza_document_verif` si `finalizeaza_document_compl`, semnaturi diferite). E o a doua cale
|
|
documentata (`garda_aviz_facturat.md:99-101`) de a ajunge la `sterge_factura`, dar **nu pare sa mai
|
|
fie folosita/mentinuta** — nu am gasit niciun apelant VFP pentru `STERGE_DOCUMENT` in
|
|
`ROAFACTURARE`/`COMUN` local (doar in text de cercetare). Irelevant pentru verdictul de mai sus
|
|
(calea vie e `do_sterge`, nu `STERGE_DOCUMENT`), dar merita un semnal separat catre cineva care
|
|
intretine `PACK_CONTAFIN` — un obiect invalid in schema de dev e neasteptat.
|
|
- **Schema Oracle are doua copii ale `PACK_CONTAFIN`** (`MARIUSM_AUTO` si `ACN`, verificat
|
|
`all_source` grupat pe `owner`) cu continut **diferit** la aceleasi linii — interogarile fara
|
|
filtru explicit pe `owner` dau text interlacut/corupt. Capcana noua, de adaugat la lista celor
|
|
cunoscute: orice interogare pe `all_source` in aceasta baza trebuie sa filtreze `owner=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_gestiune` scrie doar in `RUL_TEMP`, niciodata direct in `RUL` (regex exhaustiv pe EXPORT).
|
|
- `sterge_factura` nu atinge `RUL`/`STOC` (corp integral citit).
|
|
- `PACK_CONTAFIN.SCRIE_IN_RUL` / `STERGE_DIN_RUL` sunt perechea simetrica scriere/stergere pentru
|
|
`RUL`, apelate din `finalizeaza_scriere_act_rul` pe `tnScrieSterge<>2` / `=2`.
|
|
- `STERGE_DIN_RUL` face `UPDATE 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** — `RUL` are
|
|
propriul `STERS`, scris explicit, separat de `VANZARI.STERS`).
|
|
- `frm_facturi.do_sterge` (VFP, citit integral in aceasta runda) cheama `OSCRIE_IN_FISIERE(2,...)` +
|
|
`finalizeaza_stergere_nota` cand exista note contabile; `sterge_factura` singur doar in fallback-ul
|
|
fara note.
|
|
- `docs\plan_13...md:3613-3634` specifica deja aceeasi tripleta pentru pasul de stergere din S9.
|
|
- `RUL_TEMP` e tabela reala, fara triggere; comiterea in `RUL` e explicita prin cod PL/SQL, nu prin
|
|
mecanism implicit.
|
|
|
|
**Dedus, nu verificat exhaustiv:**
|
|
- Ca orice factura normala cu articole gestionabile genereaza intotdeauna randuri `ACT` (deci
|
|
`Reccount('actactan')>0` la stergere) — bazat pe `contabilizeaza_articol` scriind `scrie_nota`
|
|
pentru bucket-ul `ntip<=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_DOCUMENT` a ramas `INVALID` (cand/ de ce `finalizeaza_document` a disparut din
|
|
`PACK_CONTAFIN` fara ca apelantul sa fie actualizat) — posibil relevant pentru alte fluxuri
|
|
(import, migrare) care ar putea folosi acest apel, dar in afara perimetrului acestei intrebari.
|