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.