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

200 lines
14 KiB
Markdown

# 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`.