Files
roafacturare/docs/cercetare/proforma_copiere_puncte_intrare.md
Marius Mutu d9f5ca4226 docs: planurile, proiectarile si rapoartele de lucru intra in versionare
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
2026-08-11 22:17:17 +03:00

14 KiB

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.