# S5C — Factura din proforma (proiectare) Status: INCHEIAT ## Sarcina Cerinta noua (decizia 43, runda 12): dintr-o proforma emisa sa se poata genera o FACTURA ca document NOU (nu prin comutarea tipului pe acelasi document — comutarea PROFORMA -> FACTURA cu linii e deja blocata cu mesaj). Mecanismul pare sa existe deja pe calea de copiere (`do_copiaza`). ## (a) Poate fi azi o proforma aleasa ca sursa de copiere? **Da, fara nicio excludere.** Trei dovezi convergente: 1. `COMUN\clase\ofacturare_comun.vc2:4964-4974` — `frm_facturi.IsCopy(tnTip)`: ``` RETURN .T. && POT SA COPIEZ ORICE, TRATEZ TIPURILE IN DO_COPIAZA *!* RETURN INLIST(m.lnTip, 1,5,7,10,22,23,43) && pot sa copii doar avize si facturi pret de lista, ... ``` Varianta veche (restrictiva, comentata) verifica doar `tip` (1-52) — niciodata `eproforma`. Varianta activa returneaza necondiționat `.T.`. Nu exista, si n-a existat vreodata in acest cod, o excludere pe `eproforma`. 2. `COMUN\clase\ofacturare_comun.vc2:5110` — vizibilitatea butonului de copiere pe randul selectat: `Thisform.but_copiaza1.Visible = Thisform.IsCopy(crsFacturi.tip)` — acelasi apel, acelasi rezultat necondiționat. 3. `COMUN\clase\ofacturare_comun.vc2:5082-5083` — gridul de facturi are un filtru dedicat pe `eproforma`, cu proforma tratata ca subset normal, nu ascuns: ``` "Facturi&Avize\nofiled\E\(eproforma = 0)\" + crlf + ; "Proforme\nofiled\E\(eproforma=1)\" + crlf + ; ``` Chiar filtrul "Proforme" arata explicit ca proformele sunt navigabile si selectabile normal in acelasi grid — butonul de copiere ramane vizibil identic pe orice rand selectat din acest filtru. **Concluzie**: azi orice utilizator poate selecta o proforma in grid si apasa "Copiere (CTRL+K)" (tooltip-ul insusi anunta explicit acest caz de folosire — vezi citatul din `s5b_proiectare_proforma_copiere.md` §"1.4"/`proforma_copiere_puncte_intrare.md:41-47`). Nu exista nicio garda de blocat, la niciun nivel (`IsCopy`, vizibilitate buton, filtru grid). ## (b) Ce tip rezulta din copierea unei proforme? **Rezultatul e intotdeauna `nIdTipDoc=5` (FACTURA)** — corect pentru o factura fiscala — dar tipul de business (`VANZARI.TIP`, 1-52) degradeaza dupa tabelul deja existent din `do_copiaza`, **nemodificat pentru cazul proforma**: nu exista nicio ramura speciala pe `eproforma` in `do_copiaza` (`COMUN\clase\ofacturare_comun.vc2:3628-3713`) — degradarea se face **strict dupa `loFactura.tip`**, indiferent daca documentul sursa era proforma sau nu. **Pasul 1 — degradarea de tip business** (`:3693-3708`, tabel deja confirmat in `s5b_proiectare_proforma_copiere.md` §2.1): - Proforma poate exista doar pe tipuri "de factura" (combo-ul `Ct_clb_fdoc` traieste in `frm_date_factura`, nu si in `frm_date_aviz` — cf. `proforma_copiere_puncte_intrare.md` §1). Setul posibil de `loFactura.tip` pentru o proforma e deci printre `{1,2,3,4,5,6,7,8,9,10,43,44,45,47,48,49,51}` (grupul "Facturi" din `COMUN\docs\tipuri_documente_facturare.md`). - Din acest set: `{1,5,7,10}` raman neschimbate (`CASE INLIST(loFactura.tip,T1,T5,T7,T10,T22,T23)`, `:3694`); `{2,3,4,8,43,44,45,47,48,49,51}` degradeaza la `T1` (`:3696-3697`); `{6}` la `T10` (`:3698-3699`); `{9}` la `T5` (`:3700-3701`). - Deci, pentru orice proforma emisa astazi (indiferent de tipul de business original), documentul copiat va avea `TIP` in `{1,5,7,10}` — nucleul "lista de preturi" (lei/valuta) sau credit note. **Pasul 2 — `nIdTipDoc` NU se propaga** (confirmat deja in `s5b_proiectare_proforma_copiere.md` §2.3, `COMUN\programe\ofacturare_comun.prg:370`: `*.nIdTipDoc = toDateAnterior.nIdTipDoc` — comentata). Documentul nou primeste `nIdTipDoc` implicit dupa tipul degradat: `Do Case` la `COMUN\programe\ofacturare.prg:187-196`, toate valorile din `{1,5,7,10}` cad sub `5` (FACTURA) → `poDate.eProforma = 0` pe documentul nou, **indiferent ca sursa era proforma**. **Concluzie pentru (b)**: mecanismul de copiere transforma azi orice proforma intr-o **FACTURA reala (`nIdTipDoc=5`, `eproforma=0`)**, de tip business `1` (lista de preturi, cel mai frecvent caz — orice tip din `{2,3,4,8,43,44,45,47,48,49,51}` cade tot pe `T1`), `5`/`10` (daca sursa era deja pe lista de preturi in valuta/factura valuta), sau `7` (credit note, ramas neschimbat). Tipul rezultat **e cel bun pentru o factura fiscala** din perspectiva `nIdTipDoc`/`eproforma` (nu ramane proforma), dar tipul de business e intotdeauna **degradat catre "lista de preturi"** — proforma emisa dintr-o comanda (`tip=3`) sau dintr-un aviz (`tip=4`) devine, dupa copiere, o factura "banala" `tip=1`, **la fel ca la orice alta copiere non-proforma** (comportament deja documentat si acceptat in S5b §7 punctul 5: "degradarea de tip din `do_copiaza` ramane pentru copiere si nu se aplica la regenerare" — nicio schimbare ceruta aici fata de acel raport). ## (c) Legatura proforma -> factura (VANZARI_CORESP.TIP) ### Structura tabelei (confirmata pe schema vie, `MARIUSM_AUTO`) ``` ID_VANZARE_CORESP NUMBER NOT NULL (PK, populat de trigger BEFORE INSERT din SEQ_VANZARI_CORESP) ID_VANZARE_FACT NUMBER NOT NULL ID_VANZARE_AVIZ NUMBER NOT NULL (nume generic mostenit — nu neaparat un aviz, vezi mai jos) STERS NUMBER NULL TIP NUMBER NOT NULL ``` Singurul trigger gasit pe tabela (`TRG_VANZARI_CORESP_BEFOINS`, prezent identic in schemele `ACN` si `MARIUSM_AUTO`) doar genereaza PK-ul din secventa — nu atinge/valideaza `TIP`. ### Cine scrie in tabela — un singur punct, in tot codul Oracle `grep` pe `all_source` (schema vie) dupa `VANZARI_CORESP` gaseste **un singur writer**: `pack_facturare.scrie_corespondente_vanzari` (`PACK_FACTURARE:15481-15516`, singurul `INSERT INTO VANZARI_CORESP` din toata baza). Nu exista alt pachet, trigger sau produs ROA (ROAGEST, ROAIMOB, ROACONTRACTE, ROAACNPRO etc.) care sa scrie in aceasta tabela — `PACK_FACTURARE` traieste in `COMUN`, partajat de toata suita, deci **orice** consumator ar trece prin acelasi punct. ### Valorile de `TIP` deja folosite — confirmate cod + date **Cod** (singurele 3 apeluri la `scrie_corespondente_vanzari` din tot `PACK_FACTURARE`, `:14818-14839`, in `finalizeaza_factura`): - `TIP=1`: `WHEN pack_facturare.ntip = 4 THEN ... scrie_corespondente_vanzari(1)` — factura scrisa dintr-un aviz (`ntip=4` = "FACT. DIN AVIZ"). Foloseste `pack_facturare.clistaid_avize` (lista separata, populata pentru facturare-din-aviz cu selectie multipla). - `TIP=2`: `WHEN pack_facturare.ntip = 24 THEN ... scrie_corespondente_vanzari(2)` — aviz de retur (`ntip=24`). - `TIP=3`: `WHEN pack_facturare.ntip IN (8, 9) THEN ... scrie_corespondente_vanzari(3)` — factura de retur. Toate trei folosesc `pack_facturare.nid_vanzare` (documentul curent, tocmai scris) ca `ID_VANZARE_FACT`; pentru `TIP=1` sursa vine din `clistaid_avize`, pentru `TIP=2`/`TIP=3` (ramura `ELSE` din `scrie_corespondente_vanzari`, `:15490-15491`) din `pack_facturare.clistaid` generic. **Date** (schema `MARIUSM_AUTO`, interogare directa `SELECT tip, COUNT(*) FROM vanzari_coresp GROUP BY tip`): `TIP=1` → 6 randuri, `TIP=2` → 1, `TIP=3` → 1. **Zero randuri cu alt `TIP`.** Coerent cu codul (nu exista alt loc care sa scrie alte valori) — dovada dubla (cod + date), nu doar una din ele (per memoria de proiect "zero cazuri in date nu e dovada": aici avem *si* absenta din date, *si* absenta structurala in cod, ceea ce e o dovada tare, nu doar un data point izolat). ### Valoare noua libera **`TIP=4` e liber**, confirmat pe ambele fronturi (cod: niciun apel existent la `scrie_corespondente_vanzari(4)`; date: zero randuri `TIP=4` in schema testata). Recomandare: **`TIP=4` = "factura scrisa dintr-o proforma"**, urmatorul numar disponibil in secventa deja folosita (1,2,3), fara conflict cu niciun consumator existent (nu exista alt produs ROA care sa scrie sau sa citeasca `VANZARI_CORESP` in afara de `PACK_FACTURARE`). Structura tabelei **nu se schimba** — doar o noua valoare de enum in coloana `TIP`, exact cum a cerut misiunea. ### Unde s-ar scrie corespondenta — punct de intrare, cu rezerva importanta Tiparul de azi (`TIP=1/2/3`) scrie corespondenta **din interiorul** `finalizeaza_factura`, intr-un `CASE` cheie **`pack_facturare.ntip`** — semnalul de business-type al documentului nou scris. Aceasta cheie **nu poate distinge** "factura rezultata dintr-o copiere de proforma" de "orice alta factura obisnuita cu acelasi tip degradat" (vezi (b): rezultatul copierii unei proforme cade intotdeauna in `{1,5,7,10}`, niciodata `4`/`24`/`8`/`9` — deci nu exista azi nicio ramura `WHEN` pe care s-o extinda, si niciuna nu s-ar putea scrie corect doar din `ntip`, pentru ca acelasi `ntip=1` rezulta si dintr-o copiere obisnuita de factura, nelegata de nicio proforma). Vezi Capcana (i) pentru raspunsul complet la "de unde stie Oracle ca sursa a fost o proforma" si propunerea de proiectare pentru rezolvare. ## Capcana (i): supravietuieste id_fact/id_vanzare al sursei pana la scrierea corespondentei? **Da, `id_vanzare` al proformei supravietuieste — dovedit pas cu pas — dar faptul ca sursa "era o proforma" (nu doar "era un document oarecare") NU supravietuieste nicaieri azi. Asta e golul real.** **Partea care functioneaza deja, neschimbata:** 1. `do_copiaza` (`COMUN\clase\ofacturare_comun.vc2:3690-3691`): `SELECT crsFacturi / SCATTER NAME loFactura MEMO` — `loFactura` e o copie completa a randului sursa din grid, **inclusiv `loFactura.id_vanzare`** (campul cheie) si `loFactura.eproforma` (coloana de grid confirmata la `ofacturare_comun.vc2:2494`, `Column37.ControlSource = "eproforma"`) — **ambele disponibile in acest moment**, inainte ca degradarea de tip (`:3693-3708`) sa ruleze. 2. `copiere_factura` (`COMUN\programe\oproceduri_facturare.prg:150-153`) → `factureaza(loFactura.tip, loFactura)` — `loFactura` intreg (cu `id_vanzare` si `eproforma` inca pe el) devine `toFactura`, parametrul opțional. 3. `completeaza_setari_document(toDateAnterior, .T.)` (`COMUN\programe\ofacturare_comun.prg:362-412`), ramura de copiere: **`.listaid = toDateAnterior.id_vanzare`** (`:387`) — **aici** `id_vanzare` al proformei ajunge in `poDate`, proprietate care **nu e atinsa de degradarea de tip** (aceea opereaza doar pe `loFactura.tip`, variabila locala din `do_copiaza`, complet separata de `poDate`). 4. `poDate.listaid` calatoreste neschimbat prin toata sesiunea (folosit si la §2.5 din `s5b_proiectare_proforma_copiere.md` pentru `cursor_retur_document`), pana la scriere: `do_scrie_articole` (`COMUN\clase\ofacturare.vc2:6104`): `Alltrim(Nvl(poDate.listaid,''))` e trimis ca parametru `V_LISTAID` catre `pack_facturare.initializeaza_date_factura`, care il pune in `pack_facturare.clistaid := V_LISTAID` (`PACK_FACTURARE:1883`) — **inainte** ca `do_scrie_factura` sa aleaga `scrie_factura2`/`finalizeaza_factura`. La momentul in care `scrie_corespondente_vanzari` ar rula, `pack_facturare.clistaid` **este deja** `id_vanzare`-ul proformei (ca text), exact valoarea pe care ramura `ELSE` a lui `scrie_corespondente_vanzari` (`:15490-15491`, folosita azi de `TIP=2` si `TIP=3`) o citeste. **Partea care NU exista azi — golul real:** `completeaza_setari_document` (pasul 3 de mai sus) copiaza explicit `id_lucrare`, `nrord`, `id_sectie`, `sectie`, `id_agent`, `nume_agent`, `id_delegat`, `nume_delegat`, `BIdelegat`, `CNPdelegat`, `nrinmat`, `id_masina`, `listaid`, `descriere`, `id_client`, `nume_client` de pe `toDateAnterior` — **dar niciodata `.eproforma`**. Documentul nou stie "din ce `id_vanzare` a fost copiat" (`.listaid`), dar **nu stie daca acel document sursa era o proforma sau o factura obisnuita** — informatia se pierde exact la acest pas, inainte sa ajunga la Oracle. **De ce conteaza**: `finalizeaza_factura` (Oracle) decide azi ce `TIP` de corespondenta sa scrie uitandu-se **doar** la `pack_facturare.ntip` (business-type-ul documentului nou). Cum am stabilit la (b), rezultatul unei copieri de proforma cade intotdeauna in `{1,5,7,10}` — **acelasi interval** in care cade si o copiere obisnuita (proforma sau nu). Oracle **nu poate reconstitui** din `ntip` singur daca documentul curent a fost copiat dintr-o proforma sau dintr-o factura normala — nu exista niciun semnal in `pack_facturare` care sa poarte aceasta distinctie. **Ce trebuie adaugat, minimal** (propunere, nu implementare): 1. **VFP**: la `completeaza_setari_document:387`, langa `.listaid = toDateAnterior.id_vanzare`, adauga o proprietate noua, de exemplu `.lProformaSursa = (toDateAnterior.eproforma = 1)` — un simplu boolean client-side, capturat in acelasi moment si din acelasi obiect sursa unde `listaid` e deja capturat (zero risc suplimentar de "se pierde intre timp", pentru ca foloseste exact acelasi tipar dovedit la pasul 3-4 de mai sus). 2. **Scrierea corespondentei, NU prin `finalizeaza_factura`/`ntip`**: pentru ca `ntip` nu poate purta distinctia (vezi mai sus), cea mai sigura ruta e un apel Oracle **explicit, separat**, facut din VFP imediat dupa ce `do_scrie_factura` confirma succesul scrierii documentului nou, gardat de `poDate.lProformaSursa`: ``` IF poDate.lCopiere AND poDate.lProformaSursa lcSql = [{call pack_facturare.scrie_corespondente_vanzari(4)}] * ... goExecutor.oExecute(lcSql) ... ENDIF ``` Aceasta reutilizeaza **exact** procedura Oracle existenta, neschimbata (ramura `ELSE`, `pack_facturare.clistaid`/`pack_facturare.nid_vanzare` inca valide in sesiune la acel moment, per pasul 4 de mai sus) — **zero cod PL/SQL nou**, doar un nou punct de apel VFP si o noua valoare de `TIP`. Alternativa (adaugarea unei ramuri noi in `CASE`-ul din `finalizeaza_factura`, cheie pe un parametru nou trimis prin `V_PARAMETRU_ADITIONAL` sau similar) ar fi mai fragila: acel `CASE` e punctul comun al **oricarei** facturi/aviz/retur scrise in tot codul, folosit de toate produsele ROA prin `PACK_FACTURARE` partajat — o ramura noua acolo, keyed pe o combinatie de `ntip` + un flag nou, ar creste suprafata unui switch deja incarcat, pentru un caz care oricum nu poate fi exprimat corect doar din `ntip`. Apelul explicit izolat e mai simplu si nu atinge deloc `finalizeaza_factura`. 3. **Ordinea conteaza**: apelul explicit trebuie sa ruleze **inainte** ca orice alt cod Oracle din aceeasi sesiune sa resetteze `pack_facturare.nid_vanzare`/`clistaid` (de exemplu, o alta scriere de document in acelasi batch) — de plasat imediat dupa `do_scrie_factura`, inainte de listare/atasamente (care oricum nu ating Oracle pentru partea de scriere). Daca se prefera robustete completa (fara dependenta de stare de sesiune Oracle), varianta alternativa e sa se paseze explicit `V_ID_VANZARE_FACT` (= `poDate.id_vanzare`, cunoscut client-side dupa scriere) si `V_ID_VANZARE_PROFORMA` (= `poDate.listaid`, deja cunoscut) direct ca parametri, printr-o mica procedura Oracle noua care ocoleste `clistaid`/`nid_vanzare` cu totul — cost: un nou obiect PL/SQL in loc de zero, beneficiu: independenta de ordinea altor apeluri din sesiune. **Alegere ramasa lui Marius** (vezi propunerea finala). ## Capcana (ii): `marcheaza_facturat` pe proforma — corect sau nu? **Nu trebuie chemat pe proforma. Confirmat cu dovada, pe patru argumente convergente.** **Ce face, exact** (`PACK_FACTURARE:15381-15418`): ```sql PROCEDURE marcheaza_facturat(V_VERIFICARE IN NUMBER) IS BEGIN IF V_VERIFICARE = 0 THEN UPDATE VANZARI SET FACTURAT = 1, ID_UTILFACT = pack_facturare.nid_util WHERE ID_VANZARE IN (SELECT id_vanzare_aviz FROM vanzari_coresp WHERE id_vanzare_Fact = pack_facturare.nid_vanzare AND sters = 0 AND tip <> 3) AND FACTURAT = 0; ELSE -- varianta "verificare cantitate ramasa": marcheaza FACTURAT=1 doar daca toata cantitatea -- din VANZARI_DETALII a documentului sursa a fost deja consumata in VANZARI_CANTITATI ... END IF; END; ``` Flipeaza `VANZARI.FACTURAT=1` (+`ID_UTILFACT`) pe **documentul(ele) sursa** legate prin `VANZARI_CORESP` de documentul tocmai scris — fie neconditionat (`V_VERIFICARE=0`), fie doar cand cantitatea documentului sursa a fost epuizata (`V_VERIFICARE=1`, mecanismul de **facturare partiala** a avizelor, bazat pe `VANZARI_CANTITATI`). **Argumentul 1 — nu exista un `TIP` cu care sa se cupleze corect azi.** `marcheaza_facturat` se cheama azi **doar** din `finalizeaza_factura`, in aceleasi doua ramuri `WHEN pack_facturare.ntip = 4` si `WHEN pack_facturare.ntip = 24` care scriu si corespondenta (`:14823-14831`) — cuplate mereu impreuna cu `scrie_corespondente_vanzari(1)`/`(2)`, niciodata separat. Cum am stabilit la Capcana (i), calea propusa pentru `TIP=4` (factura din proforma) e un **apel explicit separat**, in afara acestui `CASE` — deci n-ar exista niciun loc "natural" unde `marcheaza_facturat` sa se agate fara sa introduca exact acelasi tip de cod nou-scris ca la corespondenta insasi. **Argumentul 2 — mecanismul de "cantitate ramasa" (`V_VERIFICARE=1`) nu are pe ce sa opereze pentru o proforma.** Verificarea citeste `VANZARI_CANTITATI` (populat **doar** de `scrie_cantitati_vanzari_avize`, apelata **doar** in ramura `ntip=4` a lui `finalizeaza_factura`). Proforma nu trece niciodata prin `finalizeaza_factura` (confirmat in `s5b_proiectare_proforma_copiere.md`, "Descoperire centrala": `scrie_proforma` cheama doar `scrie_in_vanzari`) — deci **nu exista niciodata randuri `VANZARI_CANTITATI` pentru o proforma**. Varianta `V_VERIFICARE=1` a lui `marcheaza_facturat` ar gasi mereu "cantitate ramasa = cantitate totala" (nimic consumat), fie nu ar marca niciodata `FACTURAT=1` (comportament inutil), fie (daca s-ar folosi gresit `V_VERIFICARE=0`) ar marca neconditionat, ca la punctul urmator. **Argumentul 3 — asimetrie la stergere: proforma ar ramane blocata `FACTURAT=1` definitiv.** `sterge_factura` (`PACK_FACTURARE:5501-5533`) reface `FACTURAT=0` pe documentele sursa **doar** pentru `V_TIP=24` (aviz retur, `:5502-5510`) si `V_TIP=4` (factura din aviz, `:5525-5533`) — tipurile care azi chiar cheama `marcheaza_facturat`. Rezultatul copierii unei proforme cade intotdeauna in `{1,5,7,10}` (per (b)) — **niciuna din aceste valori nu are ramura in `CASE`-ul de stergere**. Daca s-ar chema `marcheaza_facturat` la scrierea facturii din proforma, iar utilizatorul ar sterge ulterior acea factura, **proforma sursa ar ramane cu `FACTURAT=1` pentru totdeauna** — o stare orfana, fara niciun cod care s-o repare, introdusa exact de acest apel. Corespondenta `VANZARI_CORESP` insasi nu are aceeasi problema (nimic n-o citeste ca sa se strice daca ramane "orfana" dupa stergerea facturii — cel mult devine o legatura catre un document sters, inofensiv). **Argumentul 4 — nimic nu filtreaza azi proformele dupa `FACTURAT`, deci n-ar exista niciun beneficiu de blocat.** Spre deosebire de avize (`cursor_avize`/candidatii de facturat, filtrati implicit prin fluxul dedicat "Factura din aviz") si comenzi (`VCOMENZI.FACTURAT=0`, folosit explicit in `cauta_date_comanda`/`cauta_date_comanda_gest`, `PACK_FACTURARE:15659,15685`, ca sa nu ofere din nou o comanda deja facturata), **nimic in codul citit** filtreaza dupa `FACTURAT` cand se alege o proforma ca sursa de copiere — confirmat la (a): `IsCopy`/vizibilitatea butonului/filtrul de grid nu se uita niciodata la `facturat`. Marcarea n-ar preveni nicio re-copiere accidentala a aceleiasi proforme (care oricum ramane posibila, vezi propunerea finala, punctul de decizie 2). **Concluzie**: `marcheaza_facturat` **nu trebuie chemat** pentru "factura din proforma". Se scrie **doar** corespondenta (`VANZARI_CORESP`, `TIP=4`), fara actualizare de `VANZARI.FACTURAT` pe proforma. Confirma explicit suspiciunea din misiune ("proforma nu e document de livrare") cu evidenta concreta: proforma n-are urma in `VANZARI_CANTITATI` (Argumentul 2), n-are ramura de reversare la stergere (Argumentul 3), si n-are niciun consumator care sa citeasca `FACTURAT` pe ea (Argumentul 4). ## Propunere de proiectare Mecanismul de baza **ramane copierea existenta** (`do_copiaza`/`copiere_factura`/`factureaza`, neschimbata in structura ei) — cerinta "document nou, nu comutare pe acelasi document" e deja satisfacuta de calea de azi (confirmat la (a)/(b)). Ce lipseste e strict **legatura persistata** proforma → factura si excluderea explicita a lui `marcheaza_facturat`. Pasi, in ordine: 1. **Captureaza `eproforma` al sursei la copiere.** In `completeaza_setari_document` (`COMUN\programe\ofacturare_comun.prg:387`, ramura `tlFactura=.T.`), langa `.listaid = toDateAnterior.id_vanzare`, adauga o proprietate noua pe `poDate` (ex. `.lProformaSursa`), citind `toDateAnterior.eproforma` — singurul loc unde informatia mai e disponibila, inainte sa se piarda (Capcana (i)). *Gata cand:* dupa copierea unei proforme, `poDate.lProformaSursa = .T.`; dupa copierea oricarui alt document, `.F.`. 2. **Rezerva `TIP=4`** in `VANZARI_CORESP` pentru "factura scrisa dintr-o proforma" — doar o conventie documentata (ca la 1/2/3), zero schimbare de schema (confirmat la (c): tabela ramane `ID_VANZARE_FACT, ID_VANZARE_AVIZ, TIP, STERS`). 3. **Scrie corespondenta cu un apel Oracle explicit, separat de `finalizeaza_factura`.** Imediat dupa ce `do_scrie_factura` confirma succesul (acelasi punct unde azi se decid listarea/atasamentele), daca `poDate.lCopiere AND poDate.lProformaSursa`: `{call pack_facturare.scrie_corespondente_vanzari(4)}` — **reutilizeaza procedura Oracle existenta, neschimbata** (ramura `ELSE`, deja scrisa pentru `TIP=2`/`3`). Zero cod PL/SQL nou pentru scriere. *Alternativa mai robusta, cu cost:* o mica procedura Oracle noua care primeste explicit `V_ID_VANZARE_FACT`/`V_ID_VANZARE_PROFORMA` ca parametri (nu se bazeaza pe `pack_facturare.clistaid`/`nid_vanzare` inca valide in sesiune) — de ales intre simplitate (varianta de mai sus) si robustete fata de ordinea apelurilor (varianta cu parametri expliciti); vezi punctul de decizie 1 mai jos. 4. **NU cheama `marcheaza_facturat`.** Confirmat cu 4 argumente independente la Capcana (ii) — proforma nu are `VANZARI_CANTITATI`, nu are ramura de reversare la stergere, nimic n-o filtreaza dupa `FACTURAT`, si oricum n-ar exista un `WHEN pack_facturare.ntip=...` natural de unde s-o cheme (calea aleasa la pasul 3 e explicit separata de `finalizeaza_factura`). 5. **Afisare optionala "provine din proforma X"** pe factura noua — se poate construi din `VANZARI_CORESP` (`TIP=4`) la fel ca tiparul deja folosit pentru retur (`legatura_linie_retur.md` §5): la nivel de **document**, nu de linie (nicio schimbare fata de tiparul deja acceptat pentru retur — nu exista niciun tabel de legatura la nivel de linie in tot codul citit, per acelasi raport). Nu e cerut explicit de misiune, dar e disponibil "gratis" din legatura scrisa la pasul 3. **Ce NU se schimba** (confirmat, fara nevoie de atingere): - `IsCopy`, vizibilitatea `But_copiaza1`, filtrul de grid "Facturi&Avize / Proforme" — proforma ramane selectabila ca sursa exact ca azi (a). - Degradarea de tip din `do_copiaza` (`{1,5,7,10}` pentru orice proforma) si alocarea de numar nou — raman neschimbate, deja produc `nIdTipDoc=5`/`eproforma=0` corect pentru documentul nou (b). - `cursor_retur_document`, restaurarea `GESTIONABIL=B.IN_STOC` la copiere — neschimbat, mecanism deja corect pentru orice copiere (mostenit din `s5b_proiectare_proforma_copiere.md` §7). - `scrie_corespondente_vanzari` insasi — zero cod PL/SQL nou (varianta recomandata la pasul 3). ### Riscuri si ce ramane de decis de Marius 1. **Apel explicit pe stare de sesiune (`clistaid`/`nid_vanzare`) vs. procedura noua cu parametri expliciti** (pasul 3) — simplitate (zero cod Oracle nou, dar depinde ca nimic altceva sa nu resetteze starea pachetului intre scrierea facturii si apelul de corespondenta) vs. robustete (un obiect PL/SQL nou, insensibil la ordine). Recomandare: varianta simpla, **daca** apelul se plaseaza imediat dupa `do_scrie_factura`, inainte de orice alt apel Oracle din acelasi flux (listare/atasamente nu ating Oracle pentru scriere) — de verificat pe cod exact la implementare ca nu exista un apel Oracle intercalat care ar reseta `pack_facturare.nid_vanzare`. 2. **Poate fi copiata de mai multe ori aceeasi proforma?** Azi nu exista nicio garda (FACTURAT nu se marcheaza — decizia de la Capcana (ii)), deci un utilizator poate genera N facturi din aceeasi proforma, fiecare cu propriul rand `TIP=4` in `VANZARI_CORESP` catre aceeasi proforma sursa. E comportamentul implicit al oricarei copieri azi (nimic n-o limiteaza nici pentru facturi/avize normale) — de confirmat daca e acceptabil sau daca se doreste un avertisment (nu o blocare, pentru ca ar contrazice tiparul existent de copiere liber-repetabila). 3. **Guard simetric la stergere?** `sterge_factura` blocheaza azi stergerea unui aviz/unei facturi care are deja o factura de retur legata (`TIP=3`) sau facturi/avize-retur legate (`TIP IN (1,2)`, `PACK_FACTURARE:5450-5476`). Nu exista cerinta explicita in misiune pentru un guard simetric pe `TIP=4` (ex. "nu poti sterge o proforma care are deja o factura generata din ea") — de decis daca se doreste, sau daca proforma ramane liber stersa oricand (comportament actual, neschimbat daca nu se adauga nimic). 4. **Afisarea "provine din proforma X"** (pasul 5) — optionala, nu ceruta explicit; de decis daca merita implementata acum sau ramane pentru o poveste ulterioara (costul e mic, data fiind legatura deja scrisa la pasul 3). 5. **`TIP=4` ca valoare aleasa** — libera si fara conflict azi (confirmat cod+date), dar e o alocare ireversibila din punct de vedere al datelor odata folosita in productie; de confirmat explicit de Marius inainte de implementare (nu doar acceptata tacit). ## STARE / CE RAMANE **Cercetare + proiectare incheiate.** Toate cele trei intrebari (a/b/c) si ambele capcane (i/ii) au raspuns cu dovada `fisier:linie`, verificat pe fisierele text reale (`ofacturare_comun.vc2`, `ofacturare.vc2`, `ofacturare_comun.prg`, `ofacturare.prg` — nu `.bak`) si pe `PACK_FACTURARE` (`ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql`), plus verificare directa pe schema Oracle vie (`MARIUSM_AUTO`: structura `VANZARI_CORESP`, distributia `TIP` din date, singurul trigger existent). Descoperirea centrala a acestei cercetari: mecanismul de copiere de azi rezolva deja "document nou" si "tip corect" (a, b) fara nicio schimbare, dar **pierde tacit** informatia "sursa era o proforma" chiar in metoda care ar trebui s-o pastreze (`completeaza_setari_document:387`, care copiaza `listaid` dar nu si `eproforma`) — motiv pentru care legatura `VANZARI_CORESP` nu se poate agata de `CASE`-ul existent din `finalizeaza_factura` (cheie doar pe `ntip`, care nu poarta aceasta distinctie) si are nevoie de un semnal nou, client-side, plus un apel Oracle explicit separat (pasii 1 si 3 din propunere). Niciun fisier de cod atins, niciun `git_sync.ps1`/`txt2vcx.ps1` rulat, niciun commit, nicio scriere pe Oracle (doar `SELECT`, rulat cu `sqlplus.exe` pe schema `MARIUSM_AUTO`).