# Cercetare + proiectare — S5: acoperirea tuturor tipurilor de document Proiectare pe cod, READ-ONLY (fara editari, fara `git_sync.ps1`/`txt2vcx.ps1`, fara commit, fara scriere pe Oracle — numai `SELECT`), pentru povestea **S5** din `docs\plan_13_unificare_formular_facturare.md` (`#### S5`). Nu s-a atins `COMUN\clase\ofacturare_comun.vc2` si `COMUN\programe\ofacturare_editare.prg` (perimetrul altei sarcini in lucru) — doar citite cand au aparut in cautari (n-a fost cazul). Sursa VFP: `COMUN\clase\ofacturare.vc2` (`frm_facturare_articole` = formularul de productie, `:10968-15739`; `frm_facturare_articole2` = prototipul, `:15741-19355` — **nu e subclasa** a primului, mostenesc separat din `_frmbase`, au `Init` propriu fiecare). Sursa de rutare: `COMUN\programe\ofacturare.prg` (`factureaza` = standard, `:81-...`; `factureaza2` = prototip, `:660-...`). Referinta de tipuri: `COMUN\docs\tipuri_documente_facturare.md`. ## Verdict (rezumat, citeste asta primul) 1. **`Do Case`-ul din `frm_facturare_articole.Init` (`ofacturare.vc2:15109-15248`) acopera 21 de valori de `tip`** (grupate in 14 ramuri): `1,2,3,4,5,6,7,8,9,10,21,22,23,24,25,26,28,29,41,42,47`. 2. **Patru tipuri sunt reale, reachable prin `factureaza()`, dar nu apar in niciun `Case`** — pierd titlu, cap de coloana, mesaj de stoc, vizibilitate discount, eliminare `cSerie`: **`45` (factura restaurant), `48`/`49` (custodie cu/fara descarcare K), `52` (contract, factura fiscala valuta)**. Confirmat pe meniuri (`Meniuri\politica.mn2:18,26,29`, `Meniuri\contracte.mn2:18`) si pe rutarea cursorului (`ofacturare.prg:271-282`), care **le recunoaste** — doar Init-ul formularului de articole nu le-a "prins" niciodata. **Nu doar `52`**, cum semnalase raportul S4b — sunt patru, nu unul. 3. **Cinci tipuri din referinta (`43,44,46,50,51`) nu sunt niciodata pasate lui `factureaza()` in tot arborele `D:\ROA`** (cautare exhaustiva, zero potriviri) — nu ajung la acest formular deloc azi. `50` e marcat explicit "in lucru" in sursa; `51` (ROAACNPRO) foloseste `id_set=50100`, un interval separat de restul (`25000+`), semn ca provine dintr-un flux Oracle direct al altui produs, nu din `factureaza()` local. 4. **Descoperire centrala, dincolo de ce cerea misiunea**: prototipul (`frm_facturare_articole2.Init`, `:18988-19080`) **nu e o versiune partiala a Do Case-ului standard — e aproape gol**. Singurul lucru pe care-l face pe tip e sa aleaga cuvantul `lcTipDoc` ("factura" vs "aviz"), pe o lista **mai scurta** (lipseste `24`). Nu seteaza titlu (nu exista `lb_titlu_alb_b121` in tot fisierul prototipului), nu schimba capul coloanei de cantitate, nu schimba mesajul de stoc, nu ascunde discountul, **nu are deloc conceptul de coloana `cSerie`** (gridul prototipului, `grd_factura`, n-are niciodata `RemoveObject('cSerie')` — cautare pe tot fisierul, zero potriviri in intervalul `15741-19355`). Daca formularul unificat porneste de la prototip (cum indica decizia de baza a planului), **toata diferentierea pe tip trebuie reconstruita de la zero**, nu doar completata. 5. **Rutarea cursorului diverge intre standard si prototip pe trei tipuri, nu doua**: `23` (confirmat deja de S4/S4b), plus **`52` si `24`, gasite aici** — pe prototip, `Case Inlist(tnTip, 2, 26, 6)` (`ofacturare.prg:762`) **omite `52`** fata de standard (`Inlist(tnTip, 2, 26, 6, 52)`, `:283`), si `Case Inlist(tnTip, 8, 9)` (`:819`) **omite `24`** fata de standard (`Inlist(tnTip, 8, 9, 24)`, `:307`). Daca cineva ar factura tip `52` sau `24` prin prototip azi (`gnFacturareNou=1`), `lcSqlCursor` ar ramane nedefinit — eroare, nu doar diferenta de comportament. 6. **Tipurile `26` si `52` n-au niciun bookkeeping `crsarticole`** (nici Rol A, nici Rol B) — inchis aici punctul lasat deschis de raportul S4 punctul 2: excluderea lor din toate cele patru `Case`-uri de bookkeeping din `do_adauga_articol`/`do_sterge` e totala (Do Case exhaustiv, fara ramura implicita), nu doar "neconfirmata". 7. **`27` si `30` raman pe calea lor** — confirmat pe cod, cu o nuanta importanta pentru `30`: nu e un formular separat, ci **acelasi `frm_facturare_articole`, instantiat si trecut prin acelasi `Init`/`Do Case`, dar niciodata aratat** (`ofacturare.prg:444-453`: calculeaza totalurile, apasa programatic `but_termin1.Click()`, apoi `Release()`, fara `Show()`). Tip `30` **e afectat de golurile din `Do Case`** exact ca oricare alt tip needitat — doar ca defectele (titlu, cap de coloana) nu se vad niciodata pe ecran. --- ## 0. Metoda de verificare — lista de referinta Lista completa de tipuri vine din `COMUN\docs\tipuri_documente_facturare.md` (sursa unica, deja verificata pe cod de acea cercetare). Tipuri incluse in tabelul de mai jos: toate cele din sectiunile "Facturi" si "Avize de expeditie" (documentele care intra prin `frm_facturare_articole`/`2`). Sectiunea "Tipuri negative" (`-1..-13`) **nu intra in acest formular** — sunt scrise de alte produse (ROAGEST, ROAAUTO) prin propriile lor fluxuri, niciodata prin `factureaza()` din ROAFACTURARE (cautare exhaustiva `factureaza(-` in tot `D:\ROA`, zero potriviri) — declarate aici explicit **ramase pe calea altui produs**, nu "neacoperite". --- ## 1. Tabelul complet, tip cu tip Coloane: `tip` = `VANZARI.TIP` · **Case propriu** = are ramura proprie in `frm_facturare_articole.Init` (`ofacturare.vc2:15109-15248`)? · **titlu** = ce seteaza pe `lb_titlu_alb_b121.Caption` · **cap cantitate** = ce seteaza pe `grd_articole.cCantitate.header1.Caption` (implicit ramane cel din design, `[Cantitate in stoc]`, daca nu e suprascris) · **mesaj stoc** = `This.cmesaj_cantitate` · **discount** = `clb_discount.Visible` · **`cSerie`** = coloana ramane (`Da`) sau se scoate (`Nu`) · **butoane** = ce se face vizibil (`but_urmator_tot1`/`but_retur`, ambele `.F.` la design) · **cursor standard** = ramura din `factureaza` (`ofacturare.prg:266-308`) · **cursor prototip** = ramura din `factureaza2` (`:748-822`, gol daca lipseste) · **Rol crsarticole** = A (cantitate ramasa de facturat) / B (plafon de sesiune) / — (fara bookkeeping), din `docs\cercetare\s4_punct2_registru_cantitate_ramasa.md` · **stare S5** = acoperit azi / gol de completat / ramas pe calea veche / neatins. ### Facturi | tip | denumire | Case propriu | titlu | cap cantitate | mesaj stoc | discount | `cSerie` | butoane vizibile | cursor standard | cursor prototip | Rol | stare S5 | |---|---|---|---|---|---|---|---|---|---|---|---|---| | 1 | lista de preturi (lei) | **Da** `:15122` (grup 1,5,7,10) | — (implicit) | "Cantitate in stoc" | "nu e pe stoc!" | vizibil (implicit) | **Nu** (scoasa) | `but_retur` | `cursor_preturi` (grup 1,22,5,29,7,10,23), `:279-282` | `cursor_preturi` (grup 1,22,5,29,7,10), `:758-761` | B (gestionabil, `1,22,29`) | acoperit azi, de portat | | 2 | contract (lei) | **Da** `:15129` (grup 2,6) | "FACTURA PE CTR. …" | "Cantitate in stoc" | "nu e pe stoc!" | vizibil | **Nu** | — | `cursor_contract` (grup 2,26,6,52), `:283-291` | `cursor_contract` (grup 2,26,6 — **fara 52**), `:762-769` | B doar pt. `opt_facturare=0`; — pe rest | acoperit azi, de portat | | 3 | comanda | **Da** `:15144` | "FACTURA LA COMANDA …" | "Cantitate comandata" | "cantitate comandata facturata" | vizibil | **Nu** | `but_urmator_tot1` | `cursor_comanda` (grup 3,21,25,28,42,47), `:292-293` | `cursor_comanda` (acelasi grup), `:771-773` | **A** | acoperit azi, de portat | | 4 | din avize | **Da** `:15151` | "FACTURA DIN AVIZE" | — (implicit) | "cantitate de pe aviz facturata" | **ascuns** (`.F.`, `:15154`) | Da (nu se scoate) | `but_urmator_tot1` | `cursor_avize`, `:294-295` | `cursor_avize`, `:774-775` | **A** | acoperit azi, de portat | | 5 | lista de preturi valuta | **Da** `:15122` (grup 1,5,7,10) | — | "Cantitate in stoc" | "nu e pe stoc!" | vizibil | **Nu** | `but_retur` | `cursor_preturi` | `cursor_preturi` | — | acoperit azi, de portat | | 6 | contract valuta | **Da** `:15129` (grup 2,6) | "FACTURA PE CTR. …" | "Cantitate in stoc" | "nu e pe stoc!" | vizibil | **Nu** | — | `cursor_contract` | `cursor_contract` | B partial (ca 2) | acoperit azi, de portat | | 7 | credit note | **Da** `:15122` (grup 1,5,7,10) | — | "Cantitate in stoc" | "nu e pe stoc!" | vizibil | **Nu** | `but_retur` | `cursor_preturi` | `cursor_preturi` | — | acoperit azi, de portat | | 8 | retur factura lei | **Da** `:15236` (grup 8,9) | — | "Cant. max. de returnat" | "nu se mai poate returna" | vizibil | Da (nu se scoate) | `but_urmator_tot1` | `cursor_retur`, `:306-307` | `cursor_retur` (grup 8,9), `:819-820` | B (invers) | acoperit azi, de portat | | 9 | retur factura valuta | **Da** `:15236` (grup 8,9) | — | "Cant. max. de returnat" | "nu se mai poate returna" | vizibil | Da | `but_urmator_tot1` | `cursor_retur` | `cursor_retur` | B (invers) | acoperit azi, de portat | | 10 | factura fiscala valuta | **Da** `:15122` (grup 1,5,7,10) | — | "Cantitate in stoc" | "nu e pe stoc!" | vizibil | **Nu** | `but_retur` | `cursor_preturi` | `cursor_preturi` | — | acoperit azi, de portat | | **43** | bon fiscal magazine (ROARETAIL) | Nu | — | — | — | — | — | — | *nicio ramura* | *nicio ramura* | n/a | **neatins** — niciodata pasat lui `factureaza()` (cautat in tot `D:\ROA`); colectat de la magazine prin alt flux | | **44** | factura hotel | Nu | — | — | — | — | — | — | *nicio ramura* | *nicio ramura* | n/a | **neatins** — la fel, zero apeluri `factureaza(44` | | **45** | factura restaurant | **Nu** — lipseste din `Do Case` | **nesetat** | **nesetat** (implicit) | **nesetat** (ramane "nu e pe stoc!" default, `:15108`) | **nesetat** (ramane vizibil) | **Da, ramane** (nescoasa) | **nesetat** | `cursor_preturi`, `:275-278` | `cursor_preturi`, `:754-757` | — (exclus explicit din bookkeeping, `:12871,17178`) | **gol real de completat** — reachable din `Meniuri\politica.mn2:18` | | **46** | nota de plata restaurant | Nu | — | — | — | — | — | — | *nicio ramura* | *nicio ramura* | n/a | **neatins** — zero apeluri `factureaza(46`; zero documente in date de test (`tipuri_documente_facturare.md`, capcana 2) | | **48** | custodie cu descarcare K | **Nu** — lipseste din `Do Case` | **nesetat** | **nesetat** | **nesetat** | **nesetat** | **Da, ramane** | **nesetat** | `cursor_articole_k`, `:271-273` | `cursor_articole_k`, `:750-752` | — | **gol real de completat** — reachable din `Meniuri\politica.mn2:29` (submeniu `Marfaincus`) | | **49** | custodie fara descarcare K | **Nu** — lipseste din `Do Case` | **nesetat** | **nesetat** | **nesetat** | **nesetat** | **Da, ramane** | **nesetat** | `cursor_articole_k` | `cursor_articole_k` | — | **gol real de completat** — reachable din `Meniuri\politica.mn2:26` | | **50** | *(in lucru)* retur custodie | Nu | — | — | — | — | — | — | *nicio ramura* | *nicio ramura* | n/a | **neatins**, marcat explicit "in lucru" in `tipuri_documente_facturare.md` | | **51** | factura ROAACNPRO | Nu | — | — | — | — | — | — | *nicio ramura* | *nicio ramura* | n/a | **neatins** — `id_set=50100`, interval separat; probabil scris direct de ROAACNPRO, nu prin `factureaza()` local | | **52** | contract, factura fiscala valuta | **Nu** — lipseste din `Do Case` | **nesetat** | **nesetat** | **nesetat** | **nesetat** | **Da, ramane** | **nesetat** | `cursor_contract` (grup 2,26,6,52) | ***lipseste*** din grupul contract (`:762`) — `lcSqlCursor` nedefinit pe prototip | — (confirmat, vezi §2) | **gol real de completat** — reachable din `Meniuri\contracte.mn2:18` | ### Avize de expeditie | tip | denumire | Case propriu | titlu | cap cantitate | mesaj stoc | discount | `cSerie` | butoane vizibile | cursor standard | cursor prototip | Rol | stare S5 | |---|---|---|---|---|---|---|---|---|---|---|---|---| | 21 | catre clienti, din comanda | **Da** `:15168` (grup 21,28,42,47) | "AVIZ DE EXPEDITIE DIN COMANDA" | — (implicit) | "avizata cantitatea comandata" | **ascuns** | **Nu** | `but_urmator_tot1` | `cursor_comanda` | `cursor_comanda` | **A** | acoperit azi, de portat | | 22 | catre clienti, din lista | **Da** `:15178` (grup 22,29) | "AVIZ DE EXPEDITIE DIN LISTA DE PRETURI" | — | "nu e pe stoc!" | **ascuns** | **Nu** | — | `cursor_preturi` | `cursor_preturi` | B | acoperit azi, de portat | | **23** | transfer subunitati, din lista | **Da** `:15187` | "TRANSFER INTRE SUBUNITATI" | — | "nu e pe stoc!" | **ascuns** | **Nu** | — | **`cursor_preturi`** (grup 1,22,5,29,7,10,**23**), `:279` | **`cursor_gestiune`** (grup **23**,41), `:776-778` | **B** (cod comun, indiferent de sursa) | acoperit azi, **dar sursa de cursor diverge intre forme — vezi §3** | | 24 | aviz retur | **Da** `:15242` | "RETUR AVIZ DE EXPEDITIE" | "Cant. max. de returnat" | "nu se mai poate returna" | (nemodificat aici) | **Nu** | `but_urmator_tot1` | `cursor_retur` (grup 8,9,**24**), `:306-307` | ***lipseste*** din grupul retur (`:819`, doar 8,9) — `lcSqlCursor` nedefinit pe prototip | B (invers) | acoperit azi, **dar prototipul n-are ramura de cursor — vezi §3** | | 25 | transfer subunitati, din comanda | **Da** `:15206` | "TRANSFER INTRE SUBUNITATI PE BAZA DE COMANDA" | — | "avizata cantitatea comandata" | **ascuns** | **Nu** | `but_urmator_tot1` | `cursor_comanda` | `cursor_comanda` | **A** | acoperit azi, de portat | | 26 | catre clienti, din contract | **Da** `:15216` | "AVIZ DE EXPEDITIE DIN CONTRACTUL …" | "Cantitate in stoc" | "nu e pe stoc!" | **ascuns** | **Nu** | — | `cursor_contract` (grup 2,26,6,52) | `cursor_contract` (grup 2,26,6 — fara 52, dar 26 e prezent) | — (confirmat, §2) | acoperit azi, de portat | | **27** | transfer subunitati, pe lucrare | n/a — **ramane pe calea lui** | n/a | n/a | n/a | n/a | n/a | n/a | `cursor_lucrare`, `:302-304` | `cursor_lucrare`, `:815-817` | n/a | **ramas pe calea veche** — `frm_avizare_lucrare`, confirmat §4 | | 28 | catre clienti debitori, din comanda | **Da** `:15168` (grup 21,28,42,47) | "AVIZ DE EXPEDITIE DIN COMANDA" | — | "avizata cantitatea comandata" | **ascuns** | **Nu** | `but_urmator_tot1` | `cursor_comanda` | `cursor_comanda` | **A** | acoperit azi, de portat | | 29 | catre clienti debitori, din lista | **Da** `:15178` (grup 22,29) | "AVIZ DE EXPEDITIE DIN LISTA DE PRETURI" | — | "nu e pe stoc!" | **ascuns** | **Nu** | — | `cursor_preturi` | `cursor_preturi` | B | acoperit azi, de portat | | **30** | transfer subunitati, pe NIR | n/a — **ramane pe calea lui, dar prin acelasi formular** | (irelevant — formular niciodata aratat) | (irelevant) | (irelevant) | (irelevant) | (irelevant) | (irelevant) | `cursor_aviz_nir`, `:299-300` | `cursor_aviz_nir`, `:813` | n/a | **ramas pe calea veche, cu nuanta** — vezi §4 | | 41 | retur transfer, lista pret | **Da** `:15197` | "RETUR TRANSFER" | — | "nu e pe stoc!" | **ascuns** | **Nu** | — | `cursor_gestiune`, `:296-298` | `cursor_gestiune` (grup 23,41) | **B** | acoperit azi, de portat | | 42 | catre clienti custodie, din comanda | **Da** `:15168` (grup 21,28,42,47) | "AVIZ DE EXPEDITIE DIN COMANDA" | — | "avizata cantitatea comandata" | **ascuns** | **Nu** | `but_urmator_tot1` | `cursor_comanda` | `cursor_comanda` | **A** | acoperit azi, de portat | | 47 | catre clienti custodie K, din comanda | **Da** `:15168` (grup 21,28,42,47) | "AVIZ DE EXPEDITIE DIN COMANDA" | — | "avizata cantitatea comandata" | **ascuns** | **Nu** | `but_urmator_tot1` | `cursor_comanda` | `cursor_comanda` | **A** | acoperit azi, de portat | | **50** | *(in lucru)* retur clienti custodie | Nu | — | — | — | — | — | — | *nicio ramura* | *nicio ramura* | n/a | **neatins**, "in lucru" | **Tipuri negative** (`-1..-13`, ROAGEST/ROAAUTO): **ramase pe calea altui produs** — nu trec niciodata prin `factureaza()`/`factureaza2` din ROAFACTURARE (cautare exhaustiva, zero potriviri), deci nu intra in perimetrul Do Case-ului acestui formular. Declarate aici explicit, nu omise. --- ## 2. Tipurile care nu intra in niciun `Case` — inventar complet Cerinta explicita a misiunii: "nu doar 52". Lista completa, verificata pe intreg `Do Case`-ul (`ofacturare.vc2:15109-15248`, citit integral, nu esantion) fata de lista de referinta: **Nu apar in niciun `Case` al `frm_facturare_articole.Init`:** | tip | reachable prin `factureaza()`? | ce pierde concret | |---|---|---| | 43 | Nu (0 apeluri in tot `D:\ROA`) | irelevant — nu ajunge la acest formular | | 44 | Nu | irelevant | | **45** | **Da** (`Meniuri\politica.mn2:18`) | titlu, cap coloana cantitate, mesaj de stoc, `cSerie` nescoasa (ramane vizibila, desi tip 45 e explicit exclus din bookkeeping-ul de cantitate — cele doua lucruri nu sunt legate) | | 46 | Nu | irelevant — zero documente si in datele de test | | **48** | **Da** (`Meniuri\politica.mn2:29`, submeniu `Marfaincus`) | idem 45 | | **49** | **Da** (`Meniuri\politica.mn2:26`) | idem 45 | | 50 | Nu, "in lucru" | irelevant azi | | 51 | Nu (interval `id_set` separat, alt produs) | irelevant pentru acest formular | | **52** | **Da** (`Meniuri\contracte.mn2:18`) | titlu (ramane cel implicit al formularului), `cSerie` nescoasa, cap coloana cantitate implicit — **cel mai vizibil defect, pentru ca 2/6 (acelasi grup logic) au titlu corect** | **Concluzie**: din cele noua tipuri fara `Case`, **patru sunt reale si vizibile utilizatorului azi** (`45, 48, 49, 52`) — acestea sunt golul de completat cu valoare, nu doar `52`. Celelalte cinci (`43,44,46,50,51`) nu ajung niciodata la acest formular in fluxul curent — nu au nevoie de ramura in `Do Case` **pana cand** ceva le conecteaza la `factureaza()` (posibil, dar in afara perimetrului observabil aici; de tratat ca risc, nu ca bug, la sectiunea 10). **De ce raman "invizibile" azi cu `cSerie`/titlu implicit, nu cu eroare**: `Do Case ... Endcase` fara ramura `Otherwise` in VFP nu genereaza nicio eroare cand nimic nu se potriveste — pur si simplu sare peste tot blocul. De-asta tip 45/48/49/52 "merg" (formularul se deschide, factureaza cu succes), doar cu UI-ul netratat pentru cazul lor specific — un defect tacut, nu un crash, motiv probabil pentru care n-a fost observat/raportat pana acum. --- ## 3. Divergentele standard vs. prototip | Aspect | Standard (`factureaza`) | Prototip (`factureaza2`) | Comportament corect de pastrat | |---|---|---|---| | **Cursor pe tip 23** | `cursor_preturi` (grup `1,22,5,29,7,10,23`, `:279`) — tratat ca lista de preturi | `cursor_gestiune` (grup `23,41`, `:776-778`) — tratat ca transfer | **`cursor_gestiune`**, impreuna cu 41 (deja stabilit de S4/S4b: transferul e o singura familie de tip, indiferent daca porneste "din lista" sau "retur"; tratarea ca lista de preturi pe standard e inconsistenta cu propriul titlu "TRANSFER INTRE SUBUNITATI" pe care tot standardul il afiseaza pentru tip 23) | | **Cursor pe tip 52** | prezent, grupat cu `2,26,6` (`:283`) | **absent** din grupul contract (`:762`, doar `2,26,6`) — `lcSqlCursor` ramane nedefinit daca cineva factureaza tip 52 prin prototip | **prezent**, grupat cu `2,6,26` — lipsa lui pe prototip e o eroare de portare, nu o alegere deliberata (nimic in cod sugereaza ca 52 trebuia tratat diferit de 2/6/26 la nivel de cursor) | | **Cursor pe tip 24** | prezent, grupat cu `8,9` (`:306-307`) | **absent** din grupul retur (`:819`, doar `8,9`) — `lcSqlCursor` nedefinit | **prezent**, grupat cu `8,9` — acelasi tip de omisiune ca la 52 | | **Init: diferentiere pe tip** | 14 ramuri, seteaza titlu/cap coloana/mesaj/discount/`cSerie`/butoane | practic nimic — doar `lcTipDoc` ("factura"/"aviz"), pe o lista **fara tip 24** | **toata logica standardului**, portata — prototipul nu are nimic de pastrat aici in afara de pozitia `lcTipDoc` | | **Coloana `cSerie`** | exista in grid prin design, se scoate condiționat (10 din 21 tipuri acoperite) | **nu exista deloc** ca si coloana in `grd_factura` (gridul unic al prototipului) | de decis explicit la proiectare (§5) — nu e o simpla portare, gridul insusi trebuie sa capete coloana | | **`but_urmator_tot1` (sau echivalentul lui)** | vizibil pe 9 din 21 de tipuri (§1) | nu exista conceptul in Init — prototipul nu are nimic care sa corespunda azi | de portat lista completa de vizibilitate din standard | | **`clb_discount.Visible`** | ascuns explicit pe toate tipurile de aviz (`21,28,42,47,22,29,23,41,25,26`) | niciodata atins in Init | de portat integral | **De ce conteaza asta pentru S5**: planul spune ca formularul unificat se bazeaza pe prototip (arhitectura lui: grid unic, editare inline, cautare pe server — deja deciziile S1-S4). Dar **diferentierea pe tip nu vine "aproape gata" din prototip** — vine aproape in intregime din standard, si trebuie portata, nu doar completata cu cele patru tipuri lipsa. Cele doua liste (tipuri lipsa din standard: 45/48/49/52; tot ce lipseste din prototip: aproape totul) sunt probleme **diferite**, care se rezolva **in aceeasi miscare** daca proiectarea de la §5 porneste de la o sursa unica de configurare portata integral din standard, cu cele patru completari incluse de la inceput (nu adaugate separat, dupa portare). --- ## 4. Tipurile speciale (27, 30) — confirmate pe cod ### Tip 27 — transfer pe baza de lucrare Confirmat la trei niveluri, toate in `ofacturare.prg`: - `Do Case tnTip = 27 -> poDate.nIdTipDoc = 6` (`:188-189`, tip document AVIZ); - `Do Case tnTip = 27 -> lcObiect = [frm_date_aviz_lucrare]` (`:218-219`) — **formular de antet diferit**, nu `frm_date_aviz`/`frm_date_factura`; - `Do Case tnTip = 27 -> lcObject = [frm_avizare_lucrare]` (`:386-387`) — **formular de articole diferit**, nu `frm_facturare_articole`. Cursorul sursa e si el propriu: `cursor_lucrare` (`:302-304`), populat pe `poDate.id_lucrare`, un camp pe care restul tipurilor nu-l au. **Ce il tine pe calea lui**: `id_lucrare` — o legatura pe care niciun alt tip de document n-o are (lucrare de service/executie, nu comanda/aviz/contract). `frm_avizare_lucrare` grupeaza gestiunile destinatie diferit (`crsgestiunidest`, `:388-393`, cu optiunea ``), o structura pe care `frm_facturare_articole`/`2` n-o au. **Formularul unificat n-ar avea `id_lucrare` si n-ar avea gruparea pe gestiuni destinatie** — motiv suficient sa ramana separat, confirmat pe cod, nu presupus. ### Tip 30 — transfer pe baza de NIR **Nuanta importanta, gasita aici**: tip 30 **nu ocoleste** `frm_facturare_articole` — il instantiaza, exact ca orice alt tip din grupul "otherwise" (`ofacturare.prg:395`, `lcObject = [frm_facturare_articole]`, ramura `Else` a lui `If tnTip = 27`). Trece prin acelasi `Init`, acelasi `Do Case` de la `:15109-15248` (unde `30` nu are ramura proprie — ar avea aceleasi goluri ca 45/48/49 daca ar fi vreodata aratat). Diferenta reala: **formularul nu e niciodata aratat** (`ofacturare.prg:444-453`): ``` IF tnTip = 30 && AVIZ DIN NIR ofrmdetaliifactura.do_calculeaza_totaluri() ofrmdetaliifactura.but_termin1.Click() plVizibil = .F. ... ELSE ... If plVizibil ofrmdetaliifactura.Show() Else ofrmdetaliifactura.Release() pnButon = 2 Endif ENDIF ``` **Ce il tine pe calea lui**: nu structura formularului (e acelasi obiect), ci **automatizarea completa a fluxului** — cursorul sursa (`cursor_aviz_nir`, populat din `VRUL`/tranzactii de receptie, nu din comanda/lista de preturi) vine deja complet, iar codul apeleaza direct metodele de finalizare fara interactiune. **Pentru formularul unificat**: daca arhitectura noua pastreaza acelasi tipar ("creeaza obiectul, populeaza, cheama finalizarea, `Release()` fara `Show()`"), tip 30 continua sa functioneze neschimbat — nu are nevoie de ramura in configurarea vizuala (§5), pentru ca vizualul nu se vede niciodata. **Singurul risc real**: daca `do_calculeaza_totaluri()`/`but_termin1.Click()` ale formularului unificat ajung sa citeasca vreo proprietate pe care doar `Do Case`-ul vizual o seteaza azi (de exemplu, un cod care ar verifica `This.cmesaj_cantitate` sau `lcTipDoc` in logica de calcul, nu doar in UI) — **de verificat explicit la implementare**, nu presupus ca "nu conteaza pentru ca nu se vede". --- ## 5. Ce structura inlocuieste `Do Case`-ul de 140 de linii ### Optiunile comparate **(a) Pastreaza `Do Case`, doar completeaza-l** (adauga ramuri pentru 45/48/49/52, porteaza restul in prototip). Cost minim imediat, dar **nu rezolva problema de fond**: un `Do Case` fara `Otherwise` nu semnaleaza niciodata un tip lipsa — exact mecanismul care a produs golul de azi (patru tipuri reale pierdute, ani la rand, fara nicio eroare). Orice tip nou de document adaugat in viitor (suita are deja `46,50` "in lucru", `43,44,51` din alte fluxuri) risca aceeasi soarta. **(b) Metoda separata per grup de tipuri** (`configureaza_lista_preturi()`, `configureaza_comanda()`, ...). Mai clar decat un `Do Case` unic, dar tot **implicit** — un tip nou tot nu declanseaza nicio eroare daca nimeni nu-l adauga in metoda corecta; doar muta problema din 140 de linii intr-un fisier cu mai multe metode mici, fara sa adauge un mecanism de detectie. **(c) Tabel de configurare per tip (RECOMANDAT)**. Un cursor/tabel cu **un rand per `tip`**, coloanele fiind exact proprietatile pe care `Do Case`-ul le seteaza azi: `titlu`, `cap_cantitate`, `mesaj_stoc`, `discount_vizibil` (`L`), `are_serie` (`L`), `tip_doc` (`factura`/`aviz`), `buton_tot_vizibil` (`L`), `buton_retur_vizibil` (`L`), `grup_sursa` (pentru meniul S4b: `lista/comanda/aviz-comanda/transfer/ retur/contract-articole/contract-rate`). Populat printr-un singur bloc de `INSERT INTO` (sau un DBF static, `configuratie_tip_document.dbf`, editabil fara compilare) — **un rand per tip din `tipuri_documente_facturare.md`**, inclusiv cele patru azi lipsa. `Init` devine: ``` SELECT * FROM configuratie_tip_document WHERE tip = poDate.tip INTO CURSOR crscfgtip If Reccount('crscfgtip') = 0 * tip necunoscut -- eroare explicita, nu formular netratat tacut AMESSAGEBOX("Tip de document necunoscut in configurare: " + Transform(poDate.tip), 16, "Eroare configurare") Thisform.Release() Return Endif This.lb_titlu_alb_b121.Caption = crscfgtip.titlu This.grd_articole.cCantitate.header1.Caption = crscfgtip.cap_cantitate This.cmesaj_cantitate = crscfgtip.mesaj_stoc This.clb_discount.Visible = crscfgtip.discount_vizibil If !crscfgtip.are_serie This.grd_articole.RemoveObject('cSerie') Endif This.but_urmator_tot1.Visible = crscfgtip.buton_tot_vizibil This.but_retur.Visible = crscfgtip.buton_retur_vizibil ``` **De ce e mai bun decat (a)/(b) pe cost de intretinere**: - **Un tip lipsa devine o eroare vizibila la deschidere**, nu un formular netratat tacut — exact defectul care a permis golul de azi sa treaca neobservat ani la rand. - **"Cat de usor se vede un tip lipsa" e mecanic, nu vizual** — vezi §8, o interogare simpla compara lista de tipuri din configurare cu lista de referinta din `tipuri_documente_facturare.md`, fara sa ruleze formularul. - **Grupurile identice raman explicite, nu implicite** — azi, "tipurile 21,28,42,47 au acelasi titlu" se vede doar citind `Inlist(...)`; intr-un tabel, acelasi lucru se vede ca patru randuri cu aceeasi valoare in coloana `titlu` — usor de generat cu un singur `INSERT` per grup (`FOR EACH tip IN (21,28,42,47) ... INSERT ...`), nu mai putin explicit, dar auditabil cu `SELECT titlu, COUNT(*) GROUP BY titlu`. - **Coloana `are_serie` rezolva si divergenta standard/prototip de la §3** — prototipul nu are azi conceptul deloc; cu configurarea noua, adaugarea coloanei `cSerie` in gridul unificat devine conditionata de aceeasi sursa unica, indiferent de forma de baza. **Cost**: portarea initiala a ~21 de randuri (14 ramuri distincte de azi + 4 completari + grupare explicita), plus un nou tabel/cursor de intretinut. Nu e cod nou complex — e date, nu logica; riscul de regresie e in acuratetea portarii (fiecare valoare trebuie sa corespunda exact cu ce face azi `Do Case`-ul), verificabil linie cu linie fata de tabelul din §1. **Recomandare finala**: **(c)**, cu tabelul de configurare implementat ca `DBF` static (nu cursor generat in cod) — editabil de oricine fara sa recompileze, si direct verificabil cu `SELECT` fara sa porneasca formularul (vezi §8). --- ## 6. Grupuri naturale de tipuri Din tabelul §1, grupurile care au azi (sau ar trebui sa aiba) valori identice pe toate coloanele: | Grup | Tipuri | Ce difera **in interiorul** grupului | |---|---|---| | **Lista de preturi, fara stoc special** | 1, 5, 7, 10 | Nimic in Init — difera doar valuta/tip document la nivel de antet (`poDate.in_valuta`, `nIdTipDoc`), nu in acest formular | | **Contract, factura** | 2, 6 (+ **52** de adaugat) | Nimic in Init dupa completare — `52` e valuta, ca `6`, dar cu alt `id_set`; titlul/coloanele sunt identice | | **Aviz din comanda (clienti/debitori/custodie)** | 21, 28, 42, 47 | Nimic in Init — difera doar destinatia comerciala (client normal/debitor/custodie), invizibila la acest nivel | | **Aviz din lista de preturi** | 22, 29 | Nimic — difera doar client normal/debitor | | **Retur facturi** | 8, 9 | Nimic — lei/valuta | | **Transfer subunitati** | 23, 41 | Sens (din lista vs. retur) — titlu diferit ("TRANSFER..." vs "RETUR TRANSFER"), restul identic; **trebuie unificate pe cursor** (§3) inainte de unificare vizuala | | **Comanda proprie** | 3 | Singur — cap de coloana propriu ("Cantitate comandata") | | **Avize proprii** | 4 | Singur — discount vizibil (spre deosebire de toate celelalte avize) | | **Aviz din contract** | 26 | Singur — titlu propriu, dar cursor comun cu grupul contract | | **Aviz retur** | 24 | Singur — cursor comun cu 8/9, dar titlu si `but_urmator_tot1` proprii | | **Custodie K** | 48, 49 | Identice ca structura vizuala (ambele lipsesc azi) — difera doar `cu`/`fara` descarcare K, invizibil la acest nivel | | **Restaurant** | 45 | Singur, azi lipsa | Observatie de proiectare: grupurile "aviz din comanda" (21/28/42/47) si "comanda" (3) au **acelasi** cap de coloana si mesaj de stoc conceptual ("cantitate comandata"), dar text usor diferit ("facturata"/"avizata") — pastrate distincte in tabelul de configurare (nu fortate identice), pentru ca diferenta e deliberata in codul de azi (`:15149` vs `:15176`, verb diferit). --- ## 7. Pasi de implementare, ordonati 1. **Extrage tabelul de configurare din `Do Case`-ul standard, exhaustiv** — un rand per tip din `tipuri_documente_facturare.md` care intra prin acest formular (Facturi + Avize, exclus 27/30/ negative), valorile copiate exact din §1. *Gata cand*: `SELECT DISTINCT tip FROM configuratie_tip_document` produce exact multimea `{1,2,3,4,5,6,7,8,9,10,21,22,23,24,25,26,28,29, 41,42,45,47,48,49,52}` (23 de tipuri) — nici unul in minus, nici unul in plus fata de lista calculata in §8. 2. **Completeaza cele patru randuri azi lipsa (45,48,49,52)** cu valori coerente cu grupul lor logic (45 langa lista de preturi cu stoc dezactivat conceptual; 48/49 langa custodie K; 52 langa 2/6) — decizie de continut, nu doar de structura; **de validat cu Marius inainte de a le considera "gata"**, pentru ca azi nu exista niciun titlu/mesaj de referinta pentru ele (nimeni nu l-a vazut pe ecran). *Gata cand*: cele patru randuri au valori nenule pe toate coloanele obligatorii (`titlu`, `cap_cantitate`, `mesaj_stoc`). 3. **Corecteaza rutarea cursorului**: `23` trece pe `cursor_gestiune` (unificat cu `41`, nu mai divide standard/prototip); `52` si `24` primesc ramura de cursor pe orice cale ramane vie din prototip (daca formularul unificat pastreaza `factureaza2`-stil, sau devine parte din calea unica daca `factureaza`/`factureaza2` se unesc — decizie separata, in afara acestei povesti). *Gata cand*: deschiderea formularului pe tip `23`, `24` si `52` prin calea noua produce acelasi continut in `crsarticole` ca varianta care functiona deja (`23`→prototip vechi pentru comparatie de continut, `24`/`52`→standard). 4. **Adauga coloana `cSerie` in gridul unificat, condiționata pe `are_serie`** — azi absenta din gridul prototipului; adaugata o singura data, aratata/ascunsa din configurare, nu prin `RemoveObject` scris de mana pe fiecare tip. *Gata cand*: pe un tip cu `are_serie=.T.` (ex. 4) coloana e vizibila; pe un tip cu `are_serie=.F.` (ex. 3) nu e. 5. **Inlocuieste `Do Case`-ul din `Init` cu citirea din configurare** (structura din §5), inclusiv ramura de eroare explicita pe tip necunoscut. *Gata cand*: pentru fiecare din cele 23 de tipuri, deschiderea formularului seteaza exact valorile din tabelul §1/pasul 2 (comparatie automata, nu vizuala — proprietatile sunt citibile headless). 6. **Verifica tipurile speciale raman neatinse**: 27 (cale total separata, neschimbata), 30 (acelasi formular, dar `do_calculeaza_totaluri`/`but_termin1.Click()` nu citesc nimic setat doar de vechiul `Do Case` vizual — verificare explicita, §4). *Gata cand*: un document tip 30 de test se finalizeaza cu acelasi rezultat in `VANZARI`/`VANZARI_DETALII` inainte si dupa migrare. 7. **Documenteaza tipurile neatinse (43,44,46,50,51) ca decizie explicita**, nu ca omisiune — un comentariu in tabelul de configurare (`* 43,44,46,50,51: neconectate la factureaza() in ROAFACTURARE, verificat `) ca viitorii cititori sa nu presupuna ca lipsesc din greseala. *Gata cand*: comentariul exista si linkeaza spre acest raport. *Depinde de*: S4 (cautarea articolelor pe server) pentru arhitectura gridului unic — pasul 4 de aici presupune ca gridul unificat exista deja in forma stabilita de S4; S4b (bara de butoane) pentru `buton_tot_vizibil`/`buton_retur_vizibil`, care alimenteaza si meniul `xmenu()` de acolo — coloanele `grup_sursa` din tabelul de configurare (§5) sunt exact ce cere S4b sectiunea 3. --- ## 8. Cum se verifica ca acoperirea e completa — proba mecanica **Nu o citire — o interogare care compara doua liste.** Doua surse de adevar: 1. **Lista de referinta**: tipurile din `COMUN\docs\tipuri_documente_facturare.md`, sectiunile "Facturi" si "Avize de expeditie", **minus** cele confirmate neatinse azi de acest formular (27, 30 raman — vezi nuanta §4 — dar 43,44,46,50,51 se exclud daca raman neconectate; de recalculat lista la fiecare rulare, nu de la o constanta inghetata). 2. **Lista din configurare** (dupa implementarea §5): `SELECT DISTINCT tip FROM configuratie_tip_document`. **Script de verificare** (headless, fara UI, rulabil oricand): ```foxpro * verifica_acoperire_tip.prg — proba mecanica pentru S5 LOCAL lnLipsa, lnInPlus * 1. lista de referinta -- tinuta manual sincron cu tipuri_documente_facturare.md * (facturi + avize, exclus negative; 27/30 raman in lista, tratate separat la pasul 3) DIMENSION laReferinta[23] laReferinta = [1,2,3,4,5,6,7,8,9,10,21,22,23,24,25,26,27,28,29,30,41,42,47,52] && + 45,48,49 dupa Pasul 2 * 2. lista din configurare SELECT DISTINCT tip FROM configuratie_tip_document INTO CURSOR crsCfg * 3. tipuri de referinta fara configurare (exclus 27, 30 -- cale separata confirmata) * 4. tipuri in configurare fara corespondent in referinta (config "orfana") * -- ambele liste trebuie sa fie goale la "gata" ``` Alternativ, **fara sa astepte implementarea §5**: acelasi principiu se aplica azi direct pe `Do Case`-ul din `ofacturare.vc2:15109-15248`, extragand tipurile din fiecare `Case ... Inlist/=` prin `vfp_symbols.ps1 -Grep 'Case (poDate\.tip|Inlist\(poDate\.tip'` si comparand rezultatul cu lista de referinta — exact tehnica folosita in aceasta cercetare pentru a produce tabelul din §1 (nu o citire vizuala, o extractie sistematica). **Pentru cursor (rutare, §3)**: acelasi principiu, pe `ofacturare.prg`, comparand tipurile din fiecare `Do Case`/`Inlist` de la `:266-308` (standard) cu cele de la `:748-822` (prototip) — orice tip prezent intr-una si absent in cealalta e o divergenta de raportat (asa au fost gasite `52` si `24` in aceasta sesiune). --- ## 9. Ce nu se poate testa headless - **Titlul, capul de coloana, mesajul de stoc ca text afisat efectiv pe ecran** — verificabile headless doar ca *proprietati setate* (`This.lb_titlu_alb_b121.Caption` dupa `Init()`, apelat direct cu un `poDate` de test), nu ca randare vizuala. Diferenta conteaza: o proprietate corect setata pe un control care nu exista (`lb_titlu_alb_b121` lipsa din prototip azi) ar trece "headless" fara sa arate nimic real — de confirmat mai intai ca ambele controale exista in formularul unificat. - **Coloanele de grid (`grd_articole`/`grd_factura`, coloana `cSerie` noua)** — capcana deja cunoscuta pe acest proiect: sub `-A -T` (rulare headless), `ColumnCount=0`/`RecordSource` raman artefacte, coloanele nu se materializeaza. Exista un harness UI **vizibil** care le citeste corect — orice verificare a `are_serie`/coloanelor trebuie sa treaca prin acela, nu prin `-A -T`. - **Tip 30 — fluxul complet fara `Show()`** — se poate rula headless (nu deschide nicio fereastra prin constructie), dar verificarea "rezultatul in Oracle e identic inainte/dupa" cere date de test reale (un NIR cu articole), nu doar apelul metodei. - **Popup-ul/dialogul viitor din S4b (`xmenu()`, `cauta_alfa`)**, daca `grup_sursa` din tabelul de configurare (§5/§6) ajunge sa-l alimenteze direct — mostenit ca limitare de la raportul S4b (`§8` de acolo): continutul `lcMeniu` verificabil ca text, popup-ul afisat nu. - **Comportamentul real al meniurilor `politica.mn2`/`contracte.mn2`** pentru tipurile 45/48/49/52 — se poate confirma ca exista intrarea de meniu (citire `.mn2`, facuta in aceasta cercetare), dar nu ca apasarea ei in productie deschide exact formularul asteptat, fara o rulare UI vizibila. --- ## 10. Riscuri si ce ramane de decis de Marius 1. **Continutul exact (titlu/mesaj) pentru cele patru tipuri azi netratate (45,48,49,52)** — codul nu ofera niciun precedent vizual (n-au fost vazute niciodata corect pe ecran), deci textele propuse in Pasul 2 (§7) sunt o **propunere**, nu o recuperare a unui text existent. **Recomandare**: 45 langa grupul "lista de preturi fara stoc" (e exclus explicit din bookkeeping de stoc, `:12871`); 48/49 cu titlu care mentioneaza "custodie" (singurul lucru care le distinge conceptual azi, in afara de coeficientul K, invizibil la acest nivel); 52 **identic cu 2/6** ("FACTURA PE CTR. ..."), pentru coerenta cu gruparea deja facuta corect in `frm_date_factura.Init` (`:9530,9632,9670`, grupul `2,6,52`). 2. **Daca 23 trece pe `cursor_gestiune` pe calea unificata, comportamentul vizibil pentru operator se schimba** (sursa de articole devine stocul din gestiune, nu lista de preturi) — **decizie de produs, nu doar tehnica**, deja semnalata de S4/S4b, dar repetata aici pentru ca afecteaza direct §5/§7 (tabelul de configurare trebuie sa reflecte alegerea finala, nu ambele variante). **Recomandare**: `cursor_gestiune`, argumentat de coerenta cu titlul "TRANSFER INTRE SUBUNITATI" pe care insusi standardul il afiseaza azi pentru 23 (titlul spune "transfer", cursorul azi spune "lista de preturi" — inconsistenta interna de rezolvat, nu de pastrat). 3. **Daca 43,44,46,50,51 raman permanent neconectate la `factureaza()`, sau exista planuri sa fie activate** — nu s-a gasit nicio dovada de cod ca ar fi in curs, dar nici o confirmare ca sunt abandonate definitiv (in afara de `50`, marcat explicit "in lucru" in sursa). **De intrebat pe Marius direct**, pentru ca raspunsul schimba daca tabelul de configurare (§5) trebuie sa le includa preventiv sau poate ramane cu 23 de randuri. 4. **Coloana `cSerie` pe gridul unificat — cost de adaugare** — prototipul n-are azi conceptul deloc; adaugarea ei presupune modificari de grid (nu doar de cod), posibil in afara perimetrului text-only (`.vc2`/`.sc2` prin `txt2vcx.ps1`) daca structura de coloane a gridului cere editare in IDE — **de confirmat la implementare**, nu presupus ca e o simpla proprietate. 5. **Tabel de configurare ca `DBF` static vs. `INSERT`-uri in cod** — recomandarea (§5) e DBF, pentru editabilitate fara recompilare, dar suita foloseste azi predominant cod pentru acest fel de configurare (niciun precedent de DBF static de configurare gasit in `frm_facturare_articole`/ `frm_date_factura`) — **de validat cu Marius daca abaterea de la conventia existenta merita beneficiul**, sau daca un cursor generat in cod (mai aproape de stilul actual, dar mai putin editabil) e preferat. ## Handoff Cercetare + proiectare incheiata in aceasta sesiune, fara sa fie nevoie de predare de context. Toate cele zece sectiuni cerute de misiune sunt completate, cu `fisier:linie` verificat direct pe fisierele text reale (`ofacturare.vc2`, `ofacturare.prg`, nu `.bak`), plus meniurile `.mn2` si raportul S4/S4b/S4_punct2 citate ca sursa pentru punctele deja stabilite (nereinvestigate). Descoperiri dincolo de cerinta explicita a misiunii, semnalate clar in text: (1) patru tipuri lipsa din `Do Case`, nu unul (45/48/49/52, sectiunea 2); (2) prototipul (`frm_facturare_articole2.Init`) e aproape complet gol pe diferentiere de tip, nu doar incomplet (sectiunea 3) — cea mai mare descoperire a acestei sesiuni, cu impact direct asupra efortului de implementare estimat pentru S5; (3) doua divergente noi de rutare a cursorului (52, 24), pe langa cea deja cunoscuta (23) (sectiunea 3); (4) tipurile 26 si 52 confirmate fara niciun bookkeeping `crsarticole`, inchizand punctul lasat deschis de raportul S4 punctul 2 (sectiunea 1, nota de subsol pe tabel). Niciun fisier de cod atins, niciun `git_sync.ps1`/`txt2vcx.ps1` rulat, nicio scriere pe Oracle (numai `Read`/`Grep`/`vfp_symbols.ps1` pe fisiere de pe disc).