338 lines
20 KiB
Markdown
338 lines
20 KiB
Markdown
Cercetare S9: reemiterea unui document cu acelasi ID_FACT (SET_IDFACT + DOCUMENTE)
|
|
====================================================================================
|
|
|
|
Verdict (rezumat)
|
|
------------------
|
|
**DA, dar cu conditii — nu e o schimbare izolata.** `SET_IDFACT` activ (`PACK_CONTAFIN.pck:3037-3040`)
|
|
ia neconditionat un `ID_FACT` nou din `SEQ_IdFact`; niciun apelant din toata suita (~25-30 copii
|
|
identice ale `oscrie_in_fisiere.prg`, cate una per produs) ii impune un `ID_FACT`. Varianta comentata
|
|
(`:3016-3035`, cauta pe `NRACT+SERIE_ACT+DATAACT+ID_CTR` cu `STERS=0`) **nu rezolva S9** ca atare:
|
|
dupa stergerea soft a documentului vechi, `STERS` e deja 1, cautarea nu-l gaseste, si cade tot pe
|
|
secventa — plus riscul de coliziune cu un document viitor neinrudit care are aceleasi 4 campuri.
|
|
Blocajul real nu e in `SET_IDFACT`, ci in scrierea din `DOCUMENTE`: acolo e un `INSERT` simplu
|
|
(`:796-817`) pe `ID_DOC`, care e **PRIMARY KEY** (`PK_DOCUMENTE`, unic, `fn_script.sql:5192-5198`).
|
|
Stergerea (`STERGE_DIN_ACT:1835-1855`) e soft-delete pur — `ACT.STERS=1`, apoi `DOCUMENTE.STERS=1`
|
|
pentru id_fact-urile gasite pe acel `COD` — randul vechi **nu se sterge fizic**. Deci reemiterea cu
|
|
acelasi `ID_FACT`, cu codul de azi neschimbat, ar arunca `ORA-00001` la insertul in `DOCUMENTE`,
|
|
pentru ca randul cu acel `ID_DOC` inca exista (doar marcat `STERS=1`). Varianta `MERGE` deja
|
|
comentata (`:818-847`) nu ajuta din prima: are doar `WHEN NOT MATCHED`, fara `WHEN MATCHED`, deci
|
|
daca randul exista deja l-ar ignora tacit — documentul reemis ar ramane cu `DOCUMENTE.STERS=1`.
|
|
Concluzie operationala: reutilizarea e posibila, dar cere trei schimbari simultane (detaliate la C.7),
|
|
nu doar reactivarea codului comentat din `SET_IDFACT`.
|
|
|
|
A. SET_IDFACT
|
|
--------------
|
|
|
|
### A.1 — Ramura activa vs. ramura comentata
|
|
|
|
Cod integral, `PACK_CONTAFIN.pck:3014-3040`:
|
|
|
|
```
|
|
------------------------------------------------------------------------------------
|
|
/* -- 25.02.2013 : am comentat pentru ca se face unirea id_fact pe listarea din JC/JV
|
|
PROCEDURE SET_IDFACT(tdDataAct ACT_TEMP.DATAACT%TYPE,
|
|
tcSerie_Act ACT_TEMP.SERIE_ACT%TYPE,
|
|
tnNrAct ACT_TEMP.NRACT%TYPE,
|
|
tnId_Ctr ACT_TEMP.ID_CTR%TYPE) IS
|
|
V_ID_FACT DOCUMENTE.ID_DOC%TYPE;
|
|
BEGIN
|
|
BEGIN
|
|
SELECT ID_DOC
|
|
into pack_contafin.nIdFact
|
|
FROM DOCUMENTE
|
|
WHERE NRACT = tnNrAct
|
|
AND NVL(SERIE_ACT, '+-') = NVL(tcSerie_Act, '+-')
|
|
AND DATAACT = tdDataAct
|
|
AND NVL(ID_CTR, 0) = NVL(tnId_Ctr, 0)
|
|
AND STERS = 0;
|
|
EXCEPTION
|
|
WHEN NO_DATA_FOUND THEN
|
|
SELECT SEQ_IdFact.NEXTVAL into pack_contafin.nIdFact FROM DUAL;
|
|
END;
|
|
END SET_IDFACT;*/
|
|
------------------------------------------------------------------------------------
|
|
PROCEDURE SET_IDFACT(V_GCS IN VARCHAR2) IS
|
|
BEGIN
|
|
SELECT SEQ_IdFact.NEXTVAL into pack_contafin.nIdFact FROM DUAL;
|
|
END SET_IDFACT;
|
|
```
|
|
|
|
Diferenta de comportament daca s-ar reactiva varianta comentata: in loc sa genereze mereu un
|
|
`ID_FACT` nou, ar cauta intai in `DOCUMENTE` un document **nesters** (`STERS=0`) cu aceeasi
|
|
combinatie `NRACT + SERIE_ACT + DATAACT + ID_CTR`, si doar daca nu gaseste nimic ar cere secventa.
|
|
Doua probleme pentru S9:
|
|
- **nu se aplica la reemitere**: documentul vechi e deja marcat `STERS=1` inainte de rescriere
|
|
(vezi B.6), asa ca filtrul `STERS=0` nu-l gaseste — cade tot pe `SEQ_IdFact.NEXTVAL`, exact ca azi;
|
|
- **risc de coliziune**: daca NRACT/SERIE_ACT/DATAACT/ID_CTR ar coincide intamplator cu alt document
|
|
nesters (nu neaparat cel pe care il reemitem), i-ar imprumuta ID_FACT-ul aceluia.
|
|
Semnatura veche are 4 parametri de identitate diferiti de semnatura activa (1 parametru `V_GCS`,
|
|
folosit doar ca "user"/context, nefolosit in corp) — deci reactivarea ar cere fie o supraincarcare,
|
|
fie schimbarea semnaturii peste tot unde e chemata (vezi A.2).
|
|
|
|
### A.2 — Apelanti
|
|
|
|
**Un singur punct de apel in PL/SQL**: `PACK_CONTAFIN.pck:721`, in bucla din `SCRIE_IN_ACT`:
|
|
|
|
```
|
|
pack_contafin.set_idfact(V_GCS);
|
|
/* 25.02.2013 : se face cumularea id_fact pe listarea din RC/RJ
|
|
PACK_CONTAFIN.SET_IDFACT(itemfact.dataact, itemfact.serie_act, itemfact.nract, itemfact.id_ctr);*/
|
|
lnIdFact := get_idFact();
|
|
```
|
|
|
|
buclat pe grupuri distincte `(NRACT, DATAACT, DATAIREG, SERIE_ACT, ID_CTR, ID_SET)` extrase din
|
|
`ACT_TEMP WHERE ID_FACT = -1` (`:713`) — deci `-1` e sentinela "acest rand cere un `ID_FACT` nou".
|
|
|
|
`SCRIE_IN_ACT` insusi e apelat **doar pe drumul de scriere**, niciodata pe cel de stergere —
|
|
in `finalizeaza_scriere_act_rul` (`:8449-8459`):
|
|
|
|
```
|
|
if tnScrieSterge <> 2 then
|
|
pack_contafin.SCRIE_IN_ACT(user);
|
|
...
|
|
else
|
|
pack_contafin.STERGE_DIN_ACT(user, lnAn, lnLuna, tnCod, tnIdUtil, tnModificareNota);
|
|
...
|
|
```
|
|
|
|
Deci `SET_IDFACT` nu se atinge deloc la stergere — confirma ca azi cele doua operatii (stergere +
|
|
reemitere) sunt independente unele de altele in privinta ID_FACT.
|
|
|
|
**Cine cheama `final_scriere_act_rul_local` / `SCRIE_IN_ACT` din VFP**: acelasi fisier
|
|
`COMUN\programe\oscrie_in_fisiere.prg`, replicat identic in ~25-30 produse ROA (verificat prin grep
|
|
pe `*.prg` in tot `D:\ROA`): `ROAFACTURARE`, `ROACONT` (output), `ROAGEST`, `ROAIMOB`, `ROAEFACTURA`,
|
|
`ROADEVIZE`, `ROAVIN`, `ROACASA`, `ROASAL`, `ROAPRETURI`, `ROAOBINV`, `ROARESTAURANT`,
|
|
`ROACOMENZI`, `ROAAPROV`, `ROASITOP`, `ROASITFIN`, `ROADECL`, `ROASALSPEC`, `ROABAVERT`,
|
|
`ROACONIMPORT`, `ROAPRINT`, s.a. — plus doua variante care apeleaza `SCRIE_IN_ACT` direct, fara
|
|
wrapper-ul local: `CONTAFIN2ORA\VFP2ORA\Programe\oscrie_in_fisiere.prg:367`,
|
|
`ROADEFSALARII\COMUN\programe\oscrie_in_fisiere.prg:141`,
|
|
`ROARESTAURANTCONFIG\COMUN_ROA\programe\oscrie_in_fisiere.prg:135`.
|
|
Un al doilea import vechi (`COMUN\datemenu\xold\import_xdbf\oscrie_in_fisiere.prg`) apare in multe
|
|
produse dar e **comentat integral** (`*!*`) — inactiv.
|
|
|
|
**Niciun apelant nu impune un `ID_FACT`.** Toti trimit `ID_FACT = -1` in `ACT_TEMP` (via
|
|
`sql_temp_insert` in `oscrie_in_fisiere.prg:126-137`, care copiaza direct campurile din cursorul VFP,
|
|
inclusiv `id_fact`) si lasa `SCRIE_IN_ACT` sa-l completeze din secventa. Confirmare suplimentara in
|
|
`COMUN\clase\omodificari.vc2:4131-4132`: `"daca se schimba partenerul, se pune id_fact = -1 in loc
|
|
de 0 pentru a se putea genera un nou id_fact"` — exact sentinela pe care se bazeaza bucla din
|
|
`SCRIE_IN_ACT`.
|
|
|
|
### A.3 — Variabila/parametru existent pentru un ID_FACT dorit
|
|
|
|
**Nu exista azi.** `PACK_CONTAFIN` are o variabila de pachet `nIdFact` (setata de `SET_IDFACT`,
|
|
citita de `GET_IDFACT`), dar e scrisa neconditionat de fiecare apel al lui `SET_IDFACT` — nu poate
|
|
fi folosita ca "intrare" fara sa se schimbe corpul procedurii. Nu exista niciun `nid_...` global, nici
|
|
alt parametru de sesiune care sa transmita un `ID_FACT` dorit lui `SET_IDFACT` sau lui `SCRIE_IN_ACT`.
|
|
Ar trebui adaugata o variabila noua de pachet (ex. un "ID_FACT fortat", implicit `NULL`), citita
|
|
**doar** in corpul activ al lui `SET_IDFACT`, consumata si resetata la prima folosire — vezi C.8.
|
|
Acelasi diagnostic e deja notat in planul de proiect, `plan_13_unificare_formular_facturare.md:1717-1719`:
|
|
`"ID_FACT. Se citeste inainte de stergere ... si se impune documentului nou, printr-un comutator
|
|
folosit numai de regenerare. SET_IDFACT nu se schimba neconditionat — e cod comun intregii suite."`
|
|
|
|
B. DOCUMENTE la reemitere cu acelasi ID_FACT
|
|
----------------------------------------------
|
|
|
|
### B.4 — INSERT sau UPDATE/MERGE azi
|
|
|
|
`PACK_CONTAFIN.pck:788-817`, in interiorul buclei din `SCRIE_IN_ACT`, cod activ (INSERT simplu):
|
|
|
|
```
|
|
-- SCRIE IN DOCUMENTE
|
|
lnTvaIncasare := case when itemfact.tva_incasare > 0 then 1 else 0 end;
|
|
-- 25.02.2013 : am repus insertul pentru ca se face cumularea id_fact pe listarea din RC/RJ
|
|
INSERT INTO DOCUMENTE
|
|
(ID_DOC, ID_UTIL, DATAORA, TVA_INCASARE, SERIE_ACT, NRACT, DATAACT, DATAIREG, ID_CTR, ID_SET)
|
|
VALUES
|
|
(lnIdFact, lnID_Util, LD_DATAORA, lnTvaIncasare, itemfact.serie_act, itemfact.nract,
|
|
itemfact.dataact, itemfact.dataireg, decode(itemfact.id_ctr, 0, NULL, itemfact.id_ctr),
|
|
itemfact.id_set);
|
|
/*
|
|
-- modificare ROACONT v 2.4.0 (27.12.2012): am adaugat serie_act, nract, dataact
|
|
-- modificare 21.02.2013: am adaugat id_ctr
|
|
MERGE INTO DOCUMENTE A
|
|
USING (SELECT lnIdFact as ID_DOC, itemfact.serie_act as SERIE_ACT, itemfact.nract as NRACT,
|
|
itemfact.dataact as DATAACT,
|
|
decode(itemfact.id_ctr, 0, NULL, itemfact.id_ctr) AS ID_CTR
|
|
FROM DUAL) B
|
|
ON (A.ID_DOC = B.ID_DOC)
|
|
WHEN NOT MATCHED THEN
|
|
INSERT (ID_DOC, ID_UTIL, DATAORA, TVA_INCASARE, SERIE_ACT, NRACT, DATAACT, ID_CTR)
|
|
VALUES (B.ID_DOC, lnID_Util, LD_DATAORA, lnTvaIncasare, B.SERIE_ACT, B.NRACT, B.DATAACT, B.ID_CTR);*/
|
|
```
|
|
|
|
Deci **azi e mereu un INSERT nou** — pe drumul normal (ID_FACT vine din secventa, mereu inexistent
|
|
in `DOCUMENTE`) asta e corect, dar pentru cazul S9 (ID_FACT reutilizat, deja existent — chiar si
|
|
soft-sters) INSERT-ul ar da eroare de unicitate (vezi B.5). Varianta `MERGE` comentata are doar
|
|
`WHEN NOT MATCHED` — daca s-ar reactiva neschimbata, un `ID_DOC` deja existent ar fi pur si simplu
|
|
ignorat (fara `WHEN MATCHED`), documentul reemis ramanand cu randul vechi din `DOCUMENTE`
|
|
(cu `TVA_INCASARE`/`ID_SET` nemodificate si, mai grav, cu `STERS` neresetat — vezi B.6).
|
|
|
|
### B.5 — Constrangere de unicitate pe DOCUMENTE
|
|
|
|
DDL gasit in `D:\ROA\DATABASE\ALTELE\Creare_server_scripturi\FirmaNoua\fn_script.sql:5162-5198`:
|
|
|
|
```
|
|
CREATE TABLE "DOCUMENTE" ("ID_DOC" NUMBER(20, 0) NOT NULL ENABLE, "DATAORA" DATE NOT NULL ENABLE,
|
|
"ID_UTIL" NUMBER(5, 0) NOT NULL ENABLE, "STERS" NUMBER(1, 0) NOT NULL ENABLE,
|
|
"DATAORAS" DATE, "ID_UTILS" NUMBER(5, 0) NOT NULL ENABLE) ...
|
|
...
|
|
CREATE UNIQUE INDEX "PK_DOCUMENTE" ON "DOCUMENTE" ("ID_DOC") ...
|
|
ALTER TABLE "DOCUMENTE" ADD CONSTRAINT "PK_DOCUMENTE" PRIMARY KEY ("ID_DOC") USING INDEX ... ENABLE
|
|
```
|
|
|
|
**Da: `ID_DOC` e PRIMARY KEY, unic.** (Coloanele `SERIE_ACT/NRACT/DATAACT/DATAIREG/ID_CTR/ID_SET/
|
|
TVA_INCASARE` din INSERT-ul de la B.4 nu apar in acest script — script vechi de firma noua,
|
|
probabil tabela a fost alterata ulterior cu `ALTER TABLE ADD COLUMN`; constrangerea de PK insa e
|
|
stabila si nu are motiv sa fi fost scoasa.) Un `INSERT INTO DOCUMENTE (ID_DOC=...)` cu o valoare de
|
|
`ID_DOC` care exista deja (chiar si `STERS=1`) arunca `ORA-00001: unique constraint (PK_DOCUMENTE)
|
|
violated`. Nu am gasit alta constrangere de unicitate pe `DOCUMENTE`; nici FK de la `ACT.ID_FACT`
|
|
catre `DOCUMENTE.ID_DOC` (`ACT.ID_FACT` e doar indexat, `IDX_ID_FACT`, `fn_script.sql:1637`, fara
|
|
constrangere de integritate referentiala gasita) — deci reinserarea de randuri in `ACT` cu
|
|
`ID_FACT` reutilizat **nu** e blocata de vreo constrangere pe `ACT` insusi; blocajul e exclusiv pe
|
|
`DOCUMENTE`.
|
|
|
|
### B.6 — Randurile vechi la stergere: fizic sterse, STERS=1, sau raman
|
|
|
|
**Soft-delete pur, pe toate cele patru tabele relevante — nimic nu se sterge fizic.**
|
|
|
|
`STERGE_DIN_ACT` (`PACK_CONTAFIN.pck:1815-1859`), apelata din `finalizeaza_scriere_act_rul` cand
|
|
`tnScrieSterge = 2`:
|
|
|
|
```
|
|
PROCEDURE STERGE_DIN_ACT(V_GCS VARCHAR2, tnAn in number, tnLuna in number, tnCod in number,
|
|
tnId_utils in number, tnTip IN NUMBER) is
|
|
-- tnTip : 0 = modificare ; 1 = stergere
|
|
...
|
|
BEGIN
|
|
...
|
|
UPDATE /*+ index(ACT IDX_COD) */ ACT
|
|
SET STERS = 1, DATAORAS = LD_DATAORA, ID_UTILS = lnId_util
|
|
WHERE COD = tnCod and an = tnAn and luna = tnLuna;
|
|
|
|
IF lnTip = 1 THEN
|
|
UPDATE DOCUMENTE
|
|
SET STERS = 1, ID_UTILS = LNID_UTIL, DATAORAS = LD_DATAORA
|
|
WHERE ID_DOC IN
|
|
(SELECT /*+ index(ACT IDX_COD) */ DISTINCT ID_FACT
|
|
FROM ACT
|
|
WHERE COD = tnCod and an = tnAn and luna = tnLuna
|
|
AND ID_FACT <> 0
|
|
and ID_SET not in (90501, 90021)
|
|
AND NOT (SCD = '4426' AND SCC = '4428')
|
|
AND NOT (SCD = '4428' AND SCC = '4427'));
|
|
END IF;
|
|
|
|
update act_temp set suma = -suma, suma_val = -suma_val;
|
|
END STERGE_DIN_ACT;
|
|
```
|
|
|
|
`ACT` -> `STERS=1` (randurile raman fizic, pe acelasi `COD`). Cand `tnTip=1` (stergere, nu simpla
|
|
modificare), **`DOCUMENTE` primeste si el `STERS=1`**, pentru toate `ID_FACT` distincte gasite pe
|
|
acel `COD` in `ACT` (cu exceptiile de mai sus pentru seturi/conturi speciale). Nicaieri nu am gasit
|
|
un `UPDATE DOCUMENTE ... SET STERS = 0` — cautare exhaustiva in `PACK_CONTAFIN.pck` (`grep -i
|
|
"UPDATE DOCUMENTE"`) a dat un singur rezultat, cel de mai sus. Deci nu exista azi niciun mecanism
|
|
care sa "reinvie" un rand din `DOCUMENTE`.
|
|
|
|
La fel, `STERGE_DIN_RUL` / `STERGE_DIN_RUL_OBINV` (`:1861-1893`) fac `UPDATE ... SET STERS = 1` pe
|
|
`RUL`/`RUL_OBINV`, fara stergere fizica.
|
|
|
|
Pentru `IREG_PARTENERI` si `JV2007` situatia e diferita in mod util pentru S9: acestea nu sunt copii
|
|
1:1 ale documentului, ci **agregate recalculate prin `MERGE`** pe chei de business (an, luna, cont /
|
|
`ID_FDOC`, `ID_FACT`, `NRACT`, `SERIE_ACT`, `DATAACT`, `DATAIREG`, `ID_PART`, ...) — vezi
|
|
`SCRIE_JV_2007` (`:3328-3373+`) si `SCRIE_IN_IREG_PARTENERI`/`EXECUTA_SCRIE_IN_IREG` (`:7030+`,
|
|
`:7607+`). Ambele sunt apelate **si pe drumul de scriere, si pe cel de stergere**
|
|
(`finalizeaza_scriere_act_rul:8495-8578`, fara conditie pe `tnScrieSterge` in afara sursei: `act_temp`
|
|
la scriere/stergere, `act` la refacere). La stergere, `sterge_document` (`:7699-8118`) reinsereaza in
|
|
`ACT_TEMP` copii ale randurilor vechi din `ACT`/`RUL`/`RUL_OBINV`, **cu acelasi `ID_FACT` ca inainte**
|
|
(coloana `id_fact` e copiata direct din sursa, nu resetata la `-1`), asa ca `MERGE`-ul din
|
|
`SCRIE_JV_2007`/`SCRIE_IN_IREG_PARTENERI` recalculeaza (compenseaza) exact randul cu acel `ID_FACT`
|
|
— nu creeaza duplicate. Deci reutilizarea `ID_FACT`-ului **nu produce dubluri in `JV2007`/
|
|
`IREG_PARTENERI`**; problema e strict izolata la `DOCUMENTE`.
|
|
|
|
Nota din plan, care confirma independent aceasta zona de risc:
|
|
`plan_13_unificare_formular_facturare.md:1737`: `"De verificat si daca DOCUMENTE primeste un al
|
|
doilea rand pe acelasi ID_DOC sau il refoloseste."` — raspunsul, dupa aceasta cercetare: **niciuna
|
|
din cele doua, in starea actuala a codului — ar arunca eroare de unicitate**, nu ar produce liniste
|
|
tacuta cu duplicat sau refolosire.
|
|
|
|
C. Verdictul care conteaza
|
|
----------------------------
|
|
|
|
### C.7 — Se poate reemite cu acelasi ID_FACT fara sa se strice nimic?
|
|
|
|
**DA, dar cu conditii** — niciuna dintre ele nu e implementata azi:
|
|
|
|
1. **Nu folosi varianta comentata a lui `SET_IDFACT` ca atare.** Cautarea `STERS=0` nu gaseste
|
|
documentul (deja sters soft inainte de rescriere) si e vulnerabila la coliziuni pe chei de
|
|
business partajate cu alt document. In loc de cautare, ID_FACT-ul trebuie **citit explicit
|
|
inainte de stergere** (VFP il are deja in cursorul documentului editat) si **transmis** pe drumul
|
|
de scriere — exact ce zice planul S9.
|
|
2. **`SET_IDFACT` are nevoie de o cale de intrare noua, inerta implicit.** O variabila de pachet
|
|
noua (ex. "ID_FACT fortat", `NULL` default) + o procedura noua de setat-o explicit inainte de
|
|
scriere; corpul activ al `SET_IDFACT` verifica intai variabila, o consuma si o reseteaza; daca e
|
|
`NULL` (cazul general — toate celelalte ~25-30 apeluri din suita), comportamentul e identic cu
|
|
azi (secventa). Nu se toarna in semnatura existenta `SET_IDFACT(V_GCS)`, ca sa nu se schimbe
|
|
apelul de la niciun alt caller.
|
|
3. **Scrierea in `DOCUMENTE` trebuie sa devina un upsert real, cu `WHEN MATCHED`.** Nici INSERT-ul
|
|
activ, nici MERGE-ul comentat (fara `WHEN MATCHED`) nu revigoreaza un rand soft-sters. E nevoie de
|
|
un `MERGE ... WHEN MATCHED THEN UPDATE SET STERS = 0, DATAORA = ..., ID_UTIL = ..., TVA_INCASARE
|
|
= ..., SERIE_ACT = ..., NRACT = ..., DATAACT = ..., DATAIREG = ..., ID_CTR = ..., ID_SET = ...`
|
|
pe langa `WHEN NOT MATCHED THEN INSERT` (cazul normal, ID_FACT nou din secventa).
|
|
4. **Succesiunea corecta**, in aceeasi tranzactie (deja planificata in S9 la nivel de VFP — vezi
|
|
`plan_13...md:1713-1719`, mutarea stergerii in tranzactia deschisa de scriere): sterge documentul
|
|
vechi (soft-delete, ca azi) -> seteaza variabila de la punctul 2 cu `ID_FACT`-ul citit inainte de
|
|
stergere -> scrie documentul nou prin drumul obisnuit (`ACT_TEMP` cu `ID_FACT = -1` ca de obicei,
|
|
dar acum grupul respectiv va primi ID_FACT-ul fortat in loc de unul nou) -> commit doar dupa ce
|
|
ambele operatii au avut succes; orice eroare -> rollback total, documentul vechi ramane intact.
|
|
|
|
- **NU** (fara aceste conditii): `INSERT INTO DOCUMENTE` cu `ID_DOC` reutilizat, cat timp randul vechi
|
|
e inca prezent cu `STERS=1`, arunca `ORA-00001` pe `PK_DOCUMENTE` — asta e dovada, nu presupunere
|
|
(B.5 + B.4).
|
|
|
|
### C.8 — Suprafata de risc pentru restul suitei
|
|
|
|
- **~25-30 cai de apel** trebuie sa ramana neafectate: toate copiile `COMUN\programe\
|
|
oscrie_in_fisiere.prg` din fiecare produs ROA (listate in A.2), plus cele 3 variante care apeleaza
|
|
`SCRIE_IN_ACT` direct. Toate trec prin acelasi punct final: `SET_IDFACT(V_GCS)` in
|
|
`PACK_CONTAFIN.pck:3037`.
|
|
- **Garantia structurala propusa**: variabila de pachet noua, default `NULL`/inert, citita **doar**
|
|
in interiorul corpului activ al lui `SET_IDFACT` (nu in semnatura, nu in vreun parametru propagat
|
|
de apelanti); se seteaza explicit **doar** de codul de regenerare din ROAFACTURARE, chiar inainte
|
|
de a incepe scrierea documentului reemis, si se consuma/reseteaza la prima citire (fie in
|
|
`SET_IDFACT`, fie la finalul tranzactiei, ca sa nu "scurgi" valoarea catre urmatoarea scriere
|
|
neinrudita din aceeasi sesiune Oracle — relevant daca `goExecutor`/conexiunea e reutilizata intre
|
|
operatii ale aceluiasi utilizator in acelasi produs). Cu default inert si citire localizata strict
|
|
in corpul lui `SET_IDFACT`, toate celelalte ~25-30 cai raman byte-for-byte identice cu azi — nu e
|
|
nevoie sa se verifice fiecare apelant individual, garantia e la sursa (variabila neinitializata =
|
|
comportament vechi).
|
|
- **Riscul real nu e in `SET_IDFACT`, ci in `DOCUMENTE`.** Schimbarea INSERT->MERGE cu `WHEN MATCHED`
|
|
la `PACK_CONTAFIN.pck:796-817` e riscanta pentru toata suita in alt sens: `WHEN MATCHED` s-ar
|
|
declansa doar cand `ID_DOC` (generat din secventa) coincide cu unul existent — ceea ce, pe drumul
|
|
normal, nu se intampla niciodata (secventa e monoton crescatoare, nu se repeta), deci practic
|
|
ramura noua e inerta pentru toti apelantii actuali si activa doar cand variabila de la C.8 a fost
|
|
setata explicit. Totusi orice modificare la acest INSERT/MERGE e in cod comun apelat de toata
|
|
suita si trebuie testata pe cel putin un ciclu normal de scriere (fara variabila fortata) in
|
|
fiecare produs care scrie facturi/note, nu doar in ROAFACTURARE.
|
|
|
|
Ramas de verificat pe baza vie
|
|
--------------------------------
|
|
- Structura curenta reala a tabelei `DOCUMENTE` (DDL-ul citat e dintr-un script vechi de "firma
|
|
noua"; coloanele `SERIE_ACT/NRACT/DATAACT/DATAIREG/ID_CTR/ID_SET/TVA_INCASARE` folosite de
|
|
INSERT-ul activ nu apar in acel DDL — probabil adaugate ulterior prin `ALTER TABLE`). De rulat pe
|
|
baza vie: `SELECT column_name, nullable FROM user_tab_columns WHERE table_name = 'DOCUMENTE'
|
|
ORDER BY column_id;` si `SELECT constraint_name, constraint_type FROM user_constraints WHERE
|
|
table_name = 'DOCUMENTE';` — sa se confirme ca `PK_DOCUMENTE` e inca activa si ca nu exista alta
|
|
constrangere aparuta intre timp.
|
|
- Daca exista deja documente reale in productie unde `DOCUMENTE.ID_DOC` a fost, intr-un fel sau
|
|
altul, reutilizat (ex. printr-o interventie manuala) — de verificat cu
|
|
`SELECT id_doc, count(*) FROM documente GROUP BY id_doc HAVING count(*) > 1;` (ar trebui sa fie
|
|
gol, dat fiind PK-ul, dar merita confirmat inaintea oricarei schimbari).
|
|
- Comportamentul exact al `finalizeaza_stergere_nota`/`finalizeaza_modificare_nota` (`:8601+`,
|
|
nu au fost citate integral aici) fata de `ID_FACT`/`ID_FACTD` — relevante daca reemiterea schimba
|
|
seria/numarul, nu doar continutul (cazul S9 "de baza" e cel mai simplu: acelasi NRACT/SERIE_ACT).
|
|
- Comportamentul lui `EXECUTA_SCRIE_TVA`/`SCRIE_JC_2007` (mentionate la `:8504-8540`, cazul an <
|
|
2007 sau JC) fata de reutilizarea ID_FACT — nu au fost verificate in detaliu, doar `SCRIE_JV_2007`.
|
|
- Nu am putut testa efectiv (fara acces la baza vie) daca `ORA-00001` e chiar eroarea ridicata de
|
|
Oracle in acest scenariu exact — e o deductie directa din DDL (PK unic + INSERT simplu pe coloana
|
|
respectiva), dar merita o rulare de proba pe o baza de test inainte de a proiecta solutia finala.
|