# Cercetare — proforma, copiere document, puncte de intrare comanda/contract Investigatie read-only, 09.08.2026. Nicio modificare de cod. Vezi si `docs\plan_13_unificare_formular_facturare.md` si `docs\handoff_13_formular_unificat.md` (sesiune paralela, activa la data cercetarii — nu s-a atins `COMUN\clase\ofacturare_comun.vc2` si nici `COMUN\programe\ofacturare_editare.prg`, marcate acolo ca "in lucru"). ## 1. Proforma **Concluzie.** Proforma nu e un tip de document separat (`poDate.tip` ramane 1-52, ca la orice factura), ci un **atribut de numerotare/serie** (`poDate.nIdTipDoc = 23`, fata de `5` = FACTURA). Se seteaza dintr-un combo "Tip document" (FACTURA/PROFORMA/BON FISCAL) aflat direct pe formularul de antet unificat `frm_date_factura` — **acelasi formular** folosit si pentru facturi normale, fara formular separat. Combo-ul e vizibil doar cand `frm_date_factura` e instantiat, adica doar pentru tipuri de "factura" (nu si pentru avize, care merg pe `frm_date_aviz`, fara acest combo). Nu exista un buton/meniu dedicat "Proforma noua": utilizatorul apeleaza fluxul normal de facturare (`factureaza(tnTip)`) si comuta manual pe PROFORMA in antet. **Dovezi:** - `COMUN\programe\ofacturare_comun.prg:593-599` — setter-ul care leaga `nIdTipDoc` de `eProforma`: `This.eProforma = IIF(m.tnIdTipDoc = This.nIdTipDocProforma, 1, 0)` (`nIdTipDocProforma = 23`, `COMUN\programe\ofacturare_comun.prg:104`). - `COMUN\clase\ofacturare.vc2:9396-9403` — `frm_date_factura.do_schimba_tipdoc`: `lcTipDoc = UPPER(this.ct_clb_fdoc._combobox1.Value)` → mapare FACTURA/PROFORMA/BON FISCAL/AVIZ la `nIdTipDoc`. - `COMUN\clase\ofacturare.vc2:8745-8754` — combo-ul: `RowSource = "FACTURA,PROFORMA,BON FISCAL"`, `Value = FACTURA` (implicit). Owner confirmat cu `vfp_symbols.ps1 -Where`: `frm_date_factura [class] ofacturare.vc2:8482-9869`. - `COMUN\clase\ofacturare.vc2:9415,9427-9428` — la schimbarea tipului: `initializeaza_setari_document(-102)` pentru proforma, `poGeneratorNumere.dezaloca_numar(...)` + `creeaza_cursor_serii(poDate.nIdTipDoc)` — **serie/numar propriu**, realocat la comutare. - `COMUN\programe\ofacturare.prg:81-196` — `factureaza(tnTip, toFactura)`: la creare, `poDate.nIdTipDoc` se seteaza explicit la `5` (FACTURA) sau `6` (AVIZ) dupa `tnTip` (`:187-196`); PROFORMA (23) nu apare niciodata aici — se ajunge la ea **doar** din interactiunea cu combo-ul din antet. - **Fara note contabile pe proforma**: `COMUN\programe\ofacturare.prg:1960,1996,2052,2063,2103` — blocurile de scriere/actualizare nota contabila si atasamente sunt garzduite cu `poDate.eProforma = 0`. - **Continut specific de raport**: `COMUN\programe\ofacturare.prg:1119` (`Case poDate.eProforma = 1`) ramifica pe un SQL de antet propriu (parteneri/adresa facturare) pentru listare; `:1638-1643` (`Case ... And poDate.eProforma = 1` → `lcRaport = [PROFORMA]`) alege formularul `.fr2` dedicat (`COMUN\Rapoarte\proforma.fr2`, `proforma_orig.fr2`, `proforma_val.fr2`). - **Transformare in factura = copiere**: tooltip explicit, `COMUN\clase\ofacturare_comun.vc2:1409`: *"Copiere (CTRL+K) * Se foloseste si pentru generarea unei facturi din proforma prin copiere"*. Mecanismul: la copiere (`completeaza_setari_document`, vezi §2) linia care ar propaga `nIdTipDoc` de la documentul sursa e **comentata** (`COMUN\programe\ofacturare_comun.prg:370`: `*.nIdTipDoc = toDateAnterior.nIdTipDoc`), deci noul document porneste implicit la `nIdTipDoc=5` (FACTURA) indiferent ca sursa era proforma — functioneaza, dar prin omisiune, nu printr-o ramura dedicata "proforma → factura". - **Relistare proforma**: cale separata de `factureaza`, in gridul de facturi: `COMUN\clase\ofacturare_comun.vc2:7230-7264` (`PROCEDURE do_listare`, alt context decat `frm_facturi.do_listare`) — filtreaza `crsFacturi` dupa `id_proforma=`, forteaza `poDate.eProforma = 1` si `poDate.nRelistare = 1` (`:7258-7260`). - Referinta tipuri: `COMUN\docs\tipuri_documente_facturare.md` — confirma ca `TIP` (1-52) e ortogonal fata de proforma; niciun rand din tabel nu e "proforma" ca atare. **Ce e specific proformei, confirmat cu dovada:** 1. Serie/numar propriu (`nIdTipDoc=23`, realocare la comutare din combo). 2. Fara scriere de nota contabila / atasamente (gate `eProforma=0` in `ofacturare.prg`). 3. Raport de listare propriu (`.fr2` dedicate). 4. "Transformare in factura" = copiere obisnuita, care scapa tipul de document proforma pentru ca linia de propagare e comentata (efect secundar, nu design explicit). **Nu am putut confirma cu dovada** (vezi "Necunoscute ramase"): daca descarcarea de gestiune e efectiv sarita pentru proforma la nivel de Oracle (`PACK_FACTURARE`, sursa nu e in cache text local). ## 2. Copierea documentului **Concluzie.** Traseul e `frm_facturi.But_copiaza1.Click` → `do_copiaza` (degradeaza tipul) → `copiere_factura` → `factureaza(tip_degradat, toFactura)` → `frm_date_factura` cu antetul pre-completat din `completeaza_setari_document(toFactura, .T.)`. Se aloca **intotdeauna** numar nou (alocarea de serie ruleaza neconditionat in `factureaza`, indiferent de `llCopiere`). Campurile de antet raman editabile (nimic din traseu seteaza `Enabled=.F.` pe controale de antet la copiere); singurul efect vizibil e relabelarea campului "Altele" in "Nr. factura" cand tipul degradat e 1/5/10/48/49 sau 48/49 sub `gnScadereStoc=0`. **Dovezi:** - `COMUN\clase\ofacturare_comun.vc2:3628-3713` — `do_copiaza`: degradeaza tipul (tabelul deja cunoscut, ex. `T2/T3/T4/T8/... → T1`, `:3696-3710`), apoi `DO copiere_factura WITH loFactura IN oproceduri_facturare.prg` (`:3710`). **Bug observat, nu cerut de investigat**: ramura `CASE INLIST(loFactura.tip,T21,T24,T26,T30,...)` (`:3702-3703`) scrie `lnTip = T22` in loc de `loFactura.tip = T22` — variabila gresita, degradarea nu se aplica efectiv pe aceasta ramura (avize catre clienti din comanda/contract/retur etc.). - `COMUN\programe\oproceduri_facturare.prg:150-153` — `copiere_factura`: `factureaza(toFactura.Tip, toFactura)`. - `COMUN\programe\ofacturare.prg:111` — `llCopiere = (Type('toFactura') = 'O')`; `:203-206` — `If m.llCopiere: poDate.completeaza_setari_document(m.toFactura, .T.)`. - `COMUN\programe\ofacturare_comun.prg:362-412` — `completeaza_setari_document(toDateAnterior, tlFactura)`: ramura `tlFactura=.T.` (copiere) seteaza `.lCopiere=.T.` si precompleteaza lucrare/sectie/agent/delegat/masina/`listaid = toDateAnterior.id_vanzare`/`descriere` (serie+numar sursa)/client (`:368-390`); **nu** propaga `nIdTipDoc`, `id_responsabil`, `id_venchelt` (comentate, `:370,373,377`). - **Numar nou, mereu**: `COMUN\programe\ofacturare.prg:208,211` — `poGeneratorNumere.ResetNumere()` + `poDate.rezultat_serii = poGeneratorNumere.creeaza_cursor_serii(poDate.nIdTipDoc)` ruleaza in bucla principala a lui `factureaza`, inainte de a deschide formularul, **neconditionat de `llCopiere`**. Functia: `COMUN\programe\oserii_numere.prg:128-177` (`Function creeaza_cursor_serii`). - **Relabel antet la copiere**: `COMUN\clase\ofacturare.vc2:9622-9628,9652-9658` — `IF m.llCopiere: .ct_clb_altele.do_schimba_explicatia([Nr. factura])` (altfel campul e eliminat din formular pentru acele tipuri). - **Reutilizabil vs specific degradarii**: reutilizabil = `copiere_factura`/`factureaza(tip, toFactura)`/`completeaza_setari_document` (mecanismul general de copiere, indiferent de tip); strict legat de degradare = tabelul `#DEFINE T.../DO CASE` din `do_copiaza` (`:3629-3708`) — acolo se decide explicit "ce tip devine ce tip la copiere", nimic din asta nu se refoloseste in afara acestei metode. ## 3. Punctele de intrare "factura din comanda" / "factura din contract" **Concluzie.** Ambele exista deja, **cu precompletare reala**, dar pe cai diferite: - **Contract**: azi precompletarea vine **din ROACONTRACTE** (produs separat), nu din ROAFACTURARE. Butonul "Factura" de pe gridul de contracte populeaza globalul `goContract` din randul selectat si cheama acelasi `factureaza(2/6/52)` din COMUN. - **Comanda**: exista deja un buton de facturare **direct in ROAFACTURARE**, pe tab-ul Comenzi (`Page5.Ct_comenzi1`), care populeaza `goComanda` din randul de grid selectat inainte de a chema `factureaza(3)` — deci raspunsul la "exista deja un buton?" e **da**, nu ipotetic. - Exista si o cale **generica, nepre-completata**, in meniul principal al ROAFACTURARE (`Clase\ofundal_facturare.vc2`, tab Page2): pentru contract nu atinge `goContract`; pentru comanda **reseteaza explicit** `goComanda = ''` inainte de apel — utilizatorul alege manual din formular. **Semnatura `factureaza`:** ``` COMUN\programe\ofacturare.prg:81-82 Procedure factureaza Lparameters tnTip, toFactura ``` `tnTip` = tipul de business (1-52, tabelul din `tipuri_documente_facturare.md`); `toFactura` = obiect opational, folosit azi **doar** pentru copiere factura/aviz (nu pentru contract/comanda). Nu exista parametru dedicat pentru "contract precompletat" sau "comanda precompletata" — canalul e globalul `goContract`/`goComanda`, citit in `oDateFactura.Init`. **Dovezi — mecanismul comun (globale citite la creare `poDate`):** - `COMUN\programe\ofacturare_comun.prg:261-297` — `Init`, ramura `If INLIST(m.tnTip, 2, 6, 52) And Type('goContract') <> 'U'` → `.id_client = goContract.id_part`, `.listaid = goContract.id_ctr`, `.descriere = goContract.contract`, plus interogare `fact_vcontracte` pentru scadenta (`:274-296`). - `COMUN\programe\ofacturare_comun.prg:301-328` — ramura `If tnTip = 3 And Type('goComanda') = 'O'` → `.id_client = goComanda.id_part`, `.listaid = goComanda.id_comanda`, `.descriere = goComanda.nr_comanda`, plus interogare sectie (`:312-323`). **Dovezi — contract, din ROACONTRACTE:** - `D:\ROA\ROACONTRACTE\Clase\ferestre_contracte.vc2:1605` — `grid_contracte.AfterRowColChange`: `SCATTER NAME goContract MEMO` la fiecare schimbare de rand selectat. - `D:\ROA\ROACONTRACTE\Clase\ferestre_contracte.vc2:1538-1549` — `but_factura.Click`: meniu "Factura lei;Invoice;Factura fiscala in valuta" → `DO facturare_contracte WITH 'FACTURA LEI'/... IN oproceduri_facturare.prg` (copia locala din `ROACONTRACTE\COMUN`, acelasi cod ca in ROAFACTURARE). - `COMUN\programe\oproceduri_facturare.prg:118-136` — `facturare_contracte(tcTip)` → `factureaza(2)` / `factureaza(6)` / `factureaza(52)`. - **Cale generica, fara precompletare**, in ROAFACTURARE insusi: `Clase\ofundal_facturare.vc2:886-897` (`Page2.Cw2.do_actiune`) — acelasi meniu, aceeasi `facturare_contracte`, dar **nu** atinge `goContract` inainte — daca globalul nu a fost populat in sesiune (`Type('goContract') = 'U'`), ramura de precompletare din `Init` nu se activeaza si userul alege contractul manual din `frm_date_factura.do_cauta_contract` (`COMUN\clase\ofacturare.vc2:9067-9115`, deja cunoscut din context). **Dovezi — comanda, buton deja existent in ROAFACTURARE:** - `COMUN\clase\ocomenzi.vc2:1580-1596` — `ct_comenzi.do_factura`: `SELECT crsComenzi` → `SCATTER NAME goComanda MEMO` → `DO facturare_comenzi IN oproceduri_facturare.prg` → `this.do_cauta()`. - `COMUN\clase\ocomenzi.vc2:932-937` — butonul: `ADD OBJECT 'But_factura1' AS but_factura`, clasa de baza `COMUN\clase\cmd_butoane.vc2:96-107` (`DEFINE CLASS but_factura ... caction = do_factura`, `ToolTipText = "Factura"`, `Picture = factura1.bmp`). Vizibilitate conditionata de starea comenzii: `COMUN\clase\ocomenzi.vc2:2199-2203` (`grid_comenzi...`) — `this.Parent.but_factura1.Visible = (goComanda.facturat = 0)` (ascuns daca deja facturata). - **Montare in ROAFACTURARE**: `Clase\ofundal_facturare.vc2:604` — `ADD OBJECT 'Page5.Ct_comenzi1' AS ct_comenzi`; `Ferestre\fundal.sc2:206` — `Page5.Ct_comenzi1.But_factura1.Name = "But_factura1"` confirma montarea concreta pe formular (nu doar in clasa sursa). - `COMUN\programe\oproceduri_facturare.prg:138-141` — `facturare_comenzi` → `factureaza(3)`. - **Cale generica, fara precompletare**: `Clase\ofundal_facturare.vc2:899-902` (`Page2.Cw3.do_actiune`): `goComanda = ''` apoi `DO facturare_comenzi ...` — reseteaza explicit globalul inainte de apel, deci userul alege comanda manual in formular. **Concluzie combinata pentru "gazda naturala"**: pentru comanda, gazda exista deja (`COMUN\clase\ocomenzi.vc2`, buton `But_factura1`, montat in `Clase\ofundal_facturare.vc2` Page5). Pentru contract, gazda echivalenta **nu exista in ROAFACTURARE** — traieste azi doar in `ROACONTRACTE\Clase\ferestre_contracte.vc2`; daca s-ar dori acelasi tipar in ROAFACTURARE, ar trebui fie o pagina de contracte proprie (subiectul planului `docs\plan_10_integrare_contracte.md`, azi "propunere, neinceput", cu decizie go/no-go in asteptare), fie un buton similar montat direct pe o lista de contracte inexistenta azi in acest produs. ## Necunoscute ramase 1. **Descarcare de gestiune pe proforma**: n-am putut confirma/infirma daca `PACK_FACTURARE` (server-side Oracle) sare efectiv descarcarea de stoc pentru documente cu `nIdTipDoc=23`. Sursa pachetului nu e in cache text local (`COMUN\docs\PACK_FACTURARE.pck` nu exista; doar `PACK_CONTAFIN.pck`, `PACK_UPDATE.pck` etc.). Comentariul din `ofacturare.prg:52` ("daca este proforma, pun toate articolele negestionabile, ca sa nu mai arate stocul") sugereaza ca partea VFP trateaza stocul doar vizual, nu ca dovada asupra scrierii server-side. 2. **Campuri de antet blocate la copiere**: am confirmat ca traseul de copiere nu seteaza explicit `Enabled=.F.` pe controale de antet (nimic gasit in `frm_date_factura` pentru `llCopiere`), dar nu am verificat exhaustiv fiecare control individual — doar relabelarea campului "Altele". Tratati ca "probabil toate editabile", nu ca fapt verificat camp-cu-camp. 3. **Bug-ul din `do_copiaza` (`:3702-3703`, `lnTip` in loc de `loFactura.tip`)** e raportat ca dovada gasita in timpul cercetarii, nu ca urmare a unei cereri explicite de audit — nu a fost verificat efectul lui in productie (date de test). 4. **ROACONTRACTE nu are cod la fel de detaliat verificat ca ROAFACTURARE**: desi are cache text (203 fisiere `.vc2/.sc2`, contrar notei mai vechi din `plan_10_integrare_contracte.md` care spunea ca nu exista), nu am facut o trecere completa a formularului de contracte — doar traseul minim pentru `but_factura.Click`.