Curatenie ceruta dupa inchiderea lui #6. Folderul cercetare\ NU se putea sterge in bloc: plan_13 se sprijina pe el cu 85 de trimiteri, deci e baza de dovezi a planului aflat in lucru. Impartirea: - 14 cercetari trans-proiect trec in COMUN\docs\cercetare\ - valuta si curs, TVA/VANZARI, consumatorii VANZARI din toata suita, integrarile #10/#11/#12, watchdog VFP, proiectarea Oracle a lui S5, view-ul VVANZARI_ARTICOLE. Nu sunt ale ROAFACTURARE, iar #10/#11/#12 se reiau chiar din ele. - 20 de rapoarte de executie ale lui #6, nereferite de nimic viu, sterse. - 91 raman, neatinse. Trimiterile catre handoff-urile si diff-urile intermediare deja desfiintate au fost curatate peste tot (39 de fisiere): 50 catre handoff-uri, 37 catre diff-uri aplicate, plus caile celor mutate in COMUN. Zero trimiteri rupte ramase. progres.md preia rolul de predare: ce ramane din #6 (cele sase documente parazite, cele doua esecuri reale din S8 pe factura din aviz), cifrele de test citite din log, si cele doua capcane de mediu platite - .FXP vechi executat in locul .prg-ului, si GETFONT() care atarna un formular instantiat fara goApp. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
607 lines
41 KiB
Markdown
607 lines
41 KiB
Markdown
# S4b — Bara de butoane si meniul de adaugare
|
|
|
|
Proiectare pe cod, READ-ONLY (fara editari, fara `git_sync.ps1`/`txt2vcx.ps1`, fara commit), pentru
|
|
povestea **S4b** din `docs\plan_13_unificare_formular_facturare.md:1890-1899` (textul decis in
|
|
sectiunea J, `:911-1101`). Nu s-a atins `COMUN\clase\ofacturare_comun.vc2` si
|
|
`COMUN\programe\ofacturare_editare.prg` (perimetrul #6) — doar citite, cand au aparut in cautari.
|
|
|
|
## Verdict (esenta, 10 randuri)
|
|
|
|
Cele trei bucati din decizia 13 sunt implementabile fara cod nou major, dar cu **trei corectii fata
|
|
de textul din plan**, toate in favoarea utilizatorului: (1) golul de contract nu e doar
|
|
`but_urmator_tot1.Visible` lipsa pe tip 2/6/26 — pe **tip 52 formularul nu intra deloc in ramura
|
|
lui**, `Do Case` nu are niciun `Case` care sa-l prinda, deci pierde si titlul, si eliminarea coloanei
|
|
`cSerie`, nu doar butonul "tot"; (2) tiparul RORIS (`frm_tranzit`, dialog bespoke) **nu e cel mai
|
|
ieftin de refolosit** — suita are deja, folosit chiar in acest formular pentru retur
|
|
(`do_cauta_facturi`), un mecanism generic de selectie multipla cu bifare, `cauta_alfa(...,
|
|
tnTipReturn=1)`, mai aproape de cerinta („dialog modal cu coloana de bifat si criterii de cautare")
|
|
decat un formular nou; (3) „unitatea de selectie e rata" pe contract **nu e valabil pentru toate
|
|
contractele** — cursorul `crsarticole1` are doua ramuri disjuncte, `OPT_FACTURARE=3` (articole reale)
|
|
si `OPT_FACTURARE IN (1,2)` (rate de scadentar), iar un contract e mereu pe una singura; eticheta
|
|
„Alege ratele de facturat…" e corecta doar pe ramura a doua. Echivalenta „tot" = „alege total" tine
|
|
azi pe o singura rutina comuna, `do_adauga_articol`, dar `do_adauga_tot` **nu parcurge `crsarticole1`
|
|
deloc** — pe contract, „adauga tot" ar trebui sa fie scris, nu doar facut vizibil. Detaliile, cu
|
|
`fisier:linie`, mai jos.
|
|
|
|
---
|
|
|
|
## 1. Inventarul butoanelor de azi
|
|
|
|
### 1.1 `frm_facturare_articole` (formularul de compunere in productie, `ofacturare.vc2:10968-15739`)
|
|
|
|
Grid sursa (comanda/lista preturi) = `grd_articole` (`RecordSource=crsarticole`,
|
|
`ofacturare.vc2:11570`). Grid sursa-contract = `grd_contracte` (`RecordSource=crsarticole1`,
|
|
`:11891`). Grid destinatie (linii factura) = `grd_factura` (`RecordSource=crsfactura`, `:12263`).
|
|
|
|
| Control | Clasa | Caption/Picture | L/T/W/H | ToolTipText | `fisier:linie` |
|
|
|---|---|---|---|---|---|
|
|
| `But_modifica1` | `but_modifica` | (fara caption) `modific_sus.bmp` | 773/61/30/27 | "Modificare (CTRL+M)" | `:11192` |
|
|
| `But_sterge1` | `but_sterge` | (fara caption) `sterg_sus.bmp` | 811/61/30/27 | "Stergere (CTRL+D)" | `:11229` |
|
|
| `But_renunt1` | `but_renunt` | (fara caption) `renunt_sus.bmp` | 792/1/30/27 | "Renuntare (ESC)" | `:11202` |
|
|
| `But_reset1` | `but_reset` | (fara caption) `reset_sus.bmp` | 303/295/30/27 | "Reseteaza" | `:11213` |
|
|
| `But_urmator1` | `but_urmator`, `caction=do_urmator` | `urmator1.bmp` | 343/348/30/27 | "Verificare" | `:11237` |
|
|
| `But_urmator2` | `but_urmator`, `caction=do_urmator2` | `urmator1.bmp` | 343/143/30/27 | "Verificare" | `:11247` |
|
|
| **`But_urmator_tot1`** | `but_urmator_tot`, `caction=do_adauga_tot` | `urmator1_tot.bmp`, **fara Caption, fara ToolTipText** (clasa insasi nu are niciuna din ele — `cmd_butoane.vc2:414-425`) | 343/378/30/27, `Visible=.F.` implicit | — | `:11257` |
|
|
| `But_retur` | `but_retur`, `caction=do_retur` | `retur1.bmp`, `Visible=.F.` implicit | 343/407/30/27 | "Retur" | `:11221` |
|
|
|
|
Niciun buton "linie noua" (`but_nou`) — o linie se adauga alegand un rand din `grd_articole` /
|
|
`grd_contracte` si apeland `do_adauga_articol` (dublu-click / Enter, mecanism de grid standard, nu
|
|
citit exhaustiv aici), nu prin `APPEND BLANK` pe `crsfactura`. "Detalii linie" nu exista ca buton
|
|
separat — `But_modifica1` **e** azi echivalentul: deschide `frm_articol_factura` pe randul curent din
|
|
`crsfactura` (`do_modifica`, `:13746-13914`), reface plafonul de cantitate din cursorul sursa
|
|
(`crsarticole` sau `crsarticole1`, ales prin `poArticol.opt_facturare`, `:13778`) si reconstruieste
|
|
proprietatile de discount/pret in valuta.
|
|
|
|
**"Adauga tot" — `But_urmator_tot1.Click -> do_adauga_tot`** (`:13169-13198`):
|
|
|
|
```
|
|
PROCEDURE do_adauga_tot
|
|
If Used('crsarticole') And Reccount('crsarticole') > 0
|
|
Select crsarticole
|
|
Scan
|
|
...
|
|
Thisform.do_adauga_articol(.T.) && tlContract = omis => .F. implicit
|
|
...
|
|
Endscan
|
|
Else
|
|
aMessageBox("Nu exista articole de adaugat!", 48, "Atentie")
|
|
Endif
|
|
ENDPROC
|
|
```
|
|
|
|
**Parcurge exclusiv `crsarticole`.** Nu exista nicio ramura care sa parcurga `crsarticole1` — deci
|
|
chiar daca s-ar face vizibil pe tip 2/6/26/52, "adauga tot" **nu ar aduce nimic** pe un contract al
|
|
carui `grd_contracte`/`crsarticole1` are randuri (rate sau articole de contract), pentru ca butonul
|
|
citeste doar cursorul celalalt. E un gol de **cod**, nu doar de vizibilitate — vezi sectiunea 5.
|
|
|
|
**Conventia de clase de butoane** (confirmat, `inventar_controale_formulare.md`): clasa de baza
|
|
`buton` (`_cmd_base.vc2:16`) are `Caption=""` implicit — butoanele sunt doar-imagine 30x27px prin
|
|
design. `but_nou` (`cmd_butoane.vc2:214-227`, `caption=do_adauga`, `ToolTipText="Adaugare
|
|
(CTRL+N)"`) si `but_sterge` (`:354-366`, `caption=inainte_de_do_sterge`, tot fara Caption propriu la
|
|
nivel de clasa) au deja `ToolTipText`, dar niciodata `Caption` — "eticheta, nu iconita muta" ceruta de
|
|
decizia 13 e o schimbare reala, nu o simpla refolosire a clasei: fie se seteaza `Caption` pe instanta
|
|
(clasa `buton` are proprietatea, pur si simplu nefolosita azi), fie se creeaza o varianta de clasa cu
|
|
`Caption` implicit.
|
|
|
|
### 1.2 `frm_facturare_articole2` (prototip, `ofacturare.vc2:15741-19355`)
|
|
|
|
Arhitectura diferita: **un singur grid** `grd_factura` cu editare inline prin combo-uri in celule
|
|
(`cCodMat.cboCodmat`, `cDenumire.cCboDenumire`) — nu exista `grd_articole`/`crsarticole` separat.
|
|
|
|
| Control | Clasa | Caption/Picture | L/T/W/H | ToolTipText | `fisier:linie` |
|
|
|---|---|---|---|---|---|
|
|
| **`But_nou1`** | `but_nou` (caption suprascris pe instanta, vezi mai jos) | `nou_sus.bmp` | 719/175/30/27 | "Adaugare (CTRL+N)" | `:15936` |
|
|
| `But_sterge1` | `but_sterge` | `sterg_sus.bmp` | 747/175/30/27 | "Stergere (CTRL+D)" | `:15955` |
|
|
| `But_renunt1` | `but_renunt` | `renunt_sus.bmp` | 716/1/30/27 | "Renuntare (ESC)" | `:15944` |
|
|
|
|
**Sunt deja unde trebuie**: `Top=175`, gridul la `Top=204` (`:15936`, `:15955`) — **deasupra
|
|
tabelului**, exact pozitionarea ceruta de decizia 13.
|
|
|
|
**`But_nou1.Click -> do_adauga`** (`:17118-17122`, override propriu pe instanta, nu `caction`
|
|
mostenit de la clasa `but_nou`):
|
|
|
|
```
|
|
PROCEDURE do_adauga
|
|
Select crsFactura
|
|
APPEND BLANK
|
|
this.grd_factura.SetFocus()
|
|
ENDPROC
|
|
```
|
|
|
|
Adauga direct un rand gol si da focus in grid — **nu** cheama `do_adauga_articol`, nu verifica stoc,
|
|
nu deschide niciun dialog. Completarea articolului se face **dupa**, prin editare inline in celule
|
|
(`cboCodmat`/`cCboDenumire`) — acesta e tiparul care se leaga direct de S4 (cautare pe server, vezi
|
|
sectiunea 6), nu de meniul de adaugare in masa.
|
|
|
|
Nu exista `But_modifica`/`detalii linie` in acest prototip — editarea se face inline, in celula.
|
|
|
|
### 1.3 Tabel comparativ
|
|
|
|
| | `frm_facturare_articole` (productie) | `frm_facturare_articole2` (prototip) |
|
|
|---|---|---|
|
|
| Pozitia butoanelor de linie | lateral, intre cele doua griduri (`Left=773+`) | deasupra gridului (`Top=175`, gridul la `Top=204`) — cerinta decizie 13 |
|
|
| "Linie noua" | nu exista — se alege dintr-un grid sursa | `But_nou1` -> `APPEND BLANK` + focus |
|
|
| "Sterge linie" | `But_sterge1`, lateral | `But_sterge1`, deasupra |
|
|
| "Detalii linie" | `But_modifica1` -> `frm_articol_factura` (dialog complet) | nu exista — editare inline |
|
|
| Sursa de articole | 2 griduri separate, `crsarticole`/`crsarticole1` | niciunul — combo pe cod/denumire in celula |
|
|
| Caption pe butoane | fara, peste tot (doar iconite) | fara, peste tot (doar iconite) — nici prototipul nu rezolva "eticheta" |
|
|
|
|
Concluzie pentru implementare: **pozitionarea** se ia din prototip, **comportamentul de adaugare in
|
|
masa** (`do_adauga_tot`/dialoage de alegere) se ia din formularul de productie (prototipul nu are deloc
|
|
aceasta logica — n-a fost construit pentru documente cu sursa), iar **eticheta pe buton** nu exista
|
|
azi in niciunul din cele doua, e de adaugat explicit in ambele cazuri.
|
|
|
|
---
|
|
|
|
## 2. `xmenu()` — contract si exemple
|
|
|
|
**Definitie**: `COMUN\programe\proceduri_comune.prg:755-822` (identica, byte-cu-byte in structura, cu
|
|
`COMUN\programe\oproceduri_comune.prg:1550-1617` — a doua e cea incarcata efectiv, SET PROCEDURE
|
|
ADDITIVE peste prima, dar comportamentul e acelasi).
|
|
|
|
```
|
|
Procedure XMENU
|
|
Lparameters TCITEMS, TNBAR
|
|
&& TCITEMS = optiuni separate prin ";" ; "\-" = separator vizual (bara, nu optiune selectabila,
|
|
&& nu se trece prin ALLTRIM); "\<X" in fata unei litere = accelerator de tastatura
|
|
&& TNBAR = optiunea initial selectata (default 1)
|
|
...
|
|
RETURN IIF( LASTKEY()=27, 0, m.NSELECT ) && 0 la ESC sau la orice tastatura care nu alege
|
|
ENDPROC
|
|
```
|
|
|
|
- Popup-ul apare la pozitia mouse-ului (`Mrow()/Mcol()`), cu `DEFINE BAR` cate unul per optiune.
|
|
- Selectia se prinde in `GETCHOICE` (`oproceduri_comune.prg:1660-1666`): `m.NSELECT = Bar()`.
|
|
- **Returul e 1-based** (numarul barei alese), **`0` daca s-a apasat ESC** (`Lastkey()=27`) — verificat
|
|
prin `Empty(m.lnOptiune)` in tot codul (0 e Empty pentru numeric).
|
|
- Nu exista parametru de "titlu" separat — primul item e primul rand din popup, nu un header.
|
|
|
|
**Trei exemple reale, gata de copiat:**
|
|
|
|
1. **`inainte_de_do_modifica`** (`ofacturare_comun.vc2:4928-4935`) — meniu static, doua optiuni,
|
|
exact tiparul pe care planul il citeaza ca precedent pentru butonul unic:
|
|
```
|
|
PROCEDURE inainte_de_do_modifica
|
|
Local lnOptiune
|
|
lnOptiune = xmenu('Modificare \<date factura;Editare \<factura (articole, cantitati, preturi)')
|
|
Do Case
|
|
Case lnOptiune = 1
|
|
This.do_modifica()
|
|
Case lnOptiune = 2
|
|
This.do_editare_factura()
|
|
Endcase
|
|
ENDPROC
|
|
```
|
|
|
|
2. **`do_verifica`** (`ofacturare_comun.vc2:4879-4886`) — meniu static, trei optiuni, cu accelerator
|
|
pe fiecare literal:
|
|
```
|
|
lnOptiune = xmenu('Verifica codurile fiscale la fiecare \<data a facturilor;Verifica doar la \<inceputul lunii;Verifica doar la \<sfarsitul lunii')
|
|
IF EMPTY(m.lnOptiune)
|
|
RETURN
|
|
ENDIF
|
|
```
|
|
|
|
3. **Meniul de borderouri** (`ofacturare_comun.vc2:5006-5029`) — meniu **construit dinamic**, cu
|
|
optiuni suplimentare adaugate conditionat si un separator vizual `\-`:
|
|
```
|
|
lcMeniuPlus = ''
|
|
IF !(EMPTY(m.lnOptiuniPlus) OR ... )
|
|
FOR lnOptiunePlus = 1 TO m.lnOptiuniPlus
|
|
lcTitlu = ALLTRIM(GETWORDNUM(m.lcListaMeniu, m.lnOptiunePlus, '|'))
|
|
lcMeniuPlus = m.lcMeniuPlus + ';' + m.lcTitlu
|
|
ENDFOR
|
|
ENDIF
|
|
lcMeniu = m.lcMeniu + IIF(!EMPTY(m.lcMeniuPlus), ';\-' + m.lcMeniuPlus, '')
|
|
lnOptiune = xmenu(m.lcMeniu)
|
|
If Empty(m.lnOptiune)
|
|
Return
|
|
Endif
|
|
DO CASE
|
|
CASE m.lnOptiune = 1
|
|
...
|
|
```
|
|
Acesta e tiparul direct aplicabil la S4b: `lcMeniu` se construieste cu `Do Case poDate.tip` (vezi
|
|
sectiunea 3), apoi un singur `xmenu(lcMeniu)` si un `Do Case lnOptiune = N` care ramifica pe
|
|
pozitia in lista construita — **nu** pe numar fix, ca la exemplele 1-2, pentru ca lista variaza pe
|
|
tip. Trebuie tinut sincron `lcMeniu` (textul optiunii) cu ordinea in care se evalueaza `lnOptiune`
|
|
in `Do Case`, altfel un `Case lnOptiune = 3` nimereste alta optiune decat cea afisata — riscul
|
|
concret al unui meniu dinamic, absent la cele statice.
|
|
|
|
**Ce NU ofera `xmenu()`**: niciun mecanism de dezactivare a unei optiuni individuale (doar prezenta/
|
|
absenta din lista construita), nicio pictograma pe item, niciun submeniu. Pentru meniul din decizia 13
|
|
(4-5 optiuni pe sursa, variabile) e suficient — nu e nevoie de mai mult.
|
|
|
|
---
|
|
|
|
## 3. Conditiile de vizibilitate ale meniului, pe tip de document
|
|
|
|
Sursa: `frm_facturare_articole.Init`, `Do Case poDate.eProforma / poDate.lCopiere / poDate.tip`,
|
|
`ofacturare.vc2:15109-15248` (citit integral, nu esantion).
|
|
|
|
| Ramura (`Case`) | `tip`(uri) | Titlu | `but_urmator_tot1.Visible` | `but_retur.Visible` | `fisier:linie` |
|
|
|---|---|---|---|---|---|
|
|
| `eProforma = 1` | proforma (orice tip) | "PROFORMA" | **.T.** | — | `:15110-15113` |
|
|
| `lCopiere` | copiere factura/aviz | "COPIERE FACTURA/AVIZ ..." | **.T.** | — | `:15115-15120` |
|
|
| `Inlist(tip,1,5,7,10)` | lista de preturi (lei/valuta/credit note/fiscala valuta) | — | — | **.T.** | `:15122-15127` |
|
|
| `Inlist(tip,2,6)` | **contract** (lei/valuta) | "FACTURA PE CTR. ..." | — (nesetat, ramane `.F.`) | — | `:15129-15143` |
|
|
| `tip = 3` | comanda | "FACTURA LA COMANDA ..." | **.T.** | — | `:15144-15150` |
|
|
| `tip = 4` | din avize | "FACTURA DIN AVIZE" | **.T.** | — | `:15151-15167` |
|
|
| `Inlist(tip,21,28,42,47)` | aviz catre clienti din comanda | "AVIZ DE EXPEDITIE DIN COMANDA" | **.T.** | — | `:15168-15177` |
|
|
| `Inlist(tip,22,29)` | aviz din lista de preturi | "AVIZ DE EXPEDITIE DIN LISTA DE PRETURI" | — | — | `:15178-15186` |
|
|
| `tip = 23` | transfer subunitati | "TRANSFER INTRE SUBUNITATI" | — | — | `:15187-15195` |
|
|
| `tip = 41` | retur transfer | "RETUR TRANSFER" | — | — | `:15196-15205` |
|
|
| `tip = 25` | transfer din comanda | "TRANSFER INTRE SUBUNITATI PE BAZA DE COMANDA" | **.T.** | — | `:15206-15215` |
|
|
| `tip = 26` | **aviz din contract** | "AVIZ DE EXPEDITIE DIN CONTRACTUL ..." | — (nesetat) | — | `:15216-15234` |
|
|
| `Inlist(tip,8,9)` | factura retur lei/valuta | — | **.T.** | — | `:15236-15241` |
|
|
| `tip = 24` | aviz retur | "RETUR AVIZ DE EXPEDITIE" | **.T.** | — | `:15242-15248` |
|
|
| *(niciun Case)* | **`tip = 52`** | **nesetat — ramane titlul implicit al formularului** | **nesetat** | — | — |
|
|
|
|
**Corectie fata de plan** (`plan_13...md:924-926`, `:1882-1883`): planul spune "tipurile de contract
|
|
(2, 6, 26, 52) nu sunt in lista [de vizibilitate a `but_urmator_tot1`]". E adevarat pentru 2/6/26, dar
|
|
**incomplet pentru 52**: `poDate.tip = 52` nu apare in **niciun** `Case` al acestui `Do Case` — nu
|
|
doar ca nu primeste `but_urmator_tot1.Visible = .T.`, ci **nu primeste nimic**: nu i se seteaza
|
|
titlul (`lb_titlu_alb_b121.Caption` ramane cel implicit al formularului, probabil gol sau invechit),
|
|
nu i se scoate coloana `cSerie` din grid (ramane vizibila, desi contractul in valuta n-are serie de
|
|
lot relevanta aici), nu i se schimba eticheta coloanei de cantitate. Pe cod, tip 52 se comporta azi ca
|
|
un tip necunoscut care a ajuns totusi sa deschida formularul (posibil pentru ca fluxul Oracle il
|
|
recunoaste — `Inlist(tnTip,2,26,6,52)` la `cursor_contract`, `ofacturare.prg:283` — dar formularul de
|
|
articole nu l-a "prins" niciodata in `Do Case`-ul lui local). **Consecinta pentru S4b**: reparatia
|
|
corecta nu e "adauga 52 la linia lui 2/6" (ar ramane fara titlu/fara eliminare `cSerie`), ci
|
|
**adauga-l explicit ca al treilea membru al ramurii `Inlist(poDate.tip, 2, 6)`** de la `:15129`,
|
|
identic cu cum a fost tratat deja in `frm_date_factura.Init` (`ofacturare.vc2:9530`:
|
|
`Case Inlist(poDate.tip, 2, 6, 52)`, si inca o data la `:9632`, `:9670`) — **acolo tip 52 e deja
|
|
grupat corect cu 2/6**, doar in acest formular de articole a fost omis.
|
|
|
|
**Ce inseamna gruparea 2/6/26/52 pentru continutul meniului**: toate patru sunt "contract" — 2/6 =
|
|
factura pe contract (lei/valuta), 26 = aviz pe contract, 52 = factura fiscala in valuta pe contract
|
|
(`COMUN\docs\tipuri_documente_facturare.md:23,27,38,50`). Optiunile din tabelul J raman aceleasi
|
|
pentru toate patru (schimba doar cuvantul "Adauga"/"Alege" vs. eventual "Avizeaza" pe 26, daca se
|
|
pastreaza conventia de limbaj factura/aviz existenta in restul formularului — `lcTipDoc` calculeaza
|
|
deja acest cuvant in alte ramuri ale aceluiasi `Do Case`, e.g. `:15175,15185,15194`, dar **nu e setat
|
|
deloc pe ramura contract** — inca o mica omisiune, `lcTipDoc` ramane la valoarea implicita "factura"
|
|
si pe aviz de contract).
|
|
|
|
**Meniul propus, per sursa** (reluat din tabelul J, cu corectiile de mai sus):
|
|
|
|
| Sursa (`tip`) | Optiunile din `xmenu()` |
|
|
|---|---|
|
|
| lista de preturi (1,5,7,10) | Cauta in lista de preturi… · Alege din nomenclator… · Retur de articole… |
|
|
| **contract, `OPT_FACTURARE=3`** (2,6,26,52) | Adauga tot din contract · Alege articolele din contract… · Cauta in lista de preturi… · Alege din nomenclator… |
|
|
| **contract, `OPT_FACTURARE IN (1,2)`** (2,6,26,52) | Adauga toate ratele · **Alege ratele de facturat…** · Cauta in lista de preturi… · Alege din nomenclator… |
|
|
| comanda (3) | Adauga tot din comanda · Alege din comanda… · Cauta in lista de preturi… · Alege din nomenclator… |
|
|
| avize (4) / avize din comanda (21,28,42,47) / transfer din comanda (25) | Adauga tot din avize · Alege avizele… · Alege liniile din avize… · Cauta in lista de preturi… · Alege din nomenclator… |
|
|
| retur (8,9,24) | Adauga tot din facturile alese · Alege liniile de returnat… · Cauta in lista de preturi… · Alege din nomenclator… |
|
|
|
|
Diferenta fata de tabelul din plan e explicata in sectiunea 4 (contractul are doua meniuri posibile,
|
|
nu unul) si in sectiunea 9 (retur nu are azi un pas separat "alege facturile" la nivelul acestui
|
|
formular — vezi mai jos).
|
|
|
|
---
|
|
|
|
## 4. Dialogul de alegere selectiva
|
|
|
|
### 4.1 Nu porni de la `frm_tranzit` (RORIS) — porneste de la `cauta_alfa`
|
|
|
|
Raportul de referinta (`COMUN\docs\cercetare\import_roris_roaacnpro.md`) descrie corect **arhitectura
|
|
generala** (buton conditionat -> metoda unica -> dialog cu bifare si criterii -> populare aditiva prin
|
|
`INSERT`, fara scriere Oracle pana la salvare) — dar `frm_tranzit` insusi e un formular **specific
|
|
ROAACNPRO**, care nu exista in ROAFACTURARE si n-ar trebui portat ca formular.
|
|
|
|
**ROAFACTURARE are deja, in productie, in acelasi `frm_facturare_articole` care e subiectul acestei
|
|
povesti, mecanismul cerut** — `cauta_alfa()` (`COMUN\programe\cauta_alfa.prg:16-260`), functia de
|
|
cautare generica folosita de zeci de `do_cauta_*` din toata suita. Are deja tot ce cere decizia 13:
|
|
|
|
- **coloana de bifat**: cand `tnTipReturn=1`, `cauta_alfa` adauga singura o coloana `ales` peste
|
|
cursorul de rezultate (`cauta_alfa.prg:124`: `Select *, 0 As ales From &lcCursort ... Into Cursor
|
|
&lcCursor`) si titlul devine explicit "Alegeti ... (mouse-click pe numar sau apasati SPACE)"
|
|
(`oproceduri_facturare.prg:2104`);
|
|
- **criterii de cautare**: parametrul `tcStringCriterii` deschide `cauta_alfa_form_plus`, varianta cu
|
|
bara de criterii (`cauta_alfa.prg:22`); fara el, cautarea alfa/browse standard tot filtreaza
|
|
interactiv pe coloanele afisate;
|
|
- **populare aditiva, fara scriere in baza**: returul (`tnTipReturn=1`) e un XML cu randurile bifate,
|
|
convertit local prin `Xmltocursor(...)` (exemplu direct, `ofacturare.vc2:9196`) — nimic nu ajunge la
|
|
Oracle in acest pas;
|
|
- **e deja folosit in acest exact formular**, pentru un caz de "alege documentul sursa": vezi 4.2.
|
|
|
|
**Recomandare de proiectare**: dialoagele "Alege..." din meniul S4b se construiesc pe reteta
|
|
`cauta_alfa(..., tnTipReturn=1)`, cu `tcselect`/`tcfiltru` diferite pe sursa (comanda/contract/avize/
|
|
retur), **nu** pe un formular nou stilizat dupa `frm_tranzit`. Ramane de portat din RORIS doar
|
|
**ideea**, nu codul: buton unic condiționat, metoda de intrare unica, populare aditiva — toate trei
|
|
deja adevarate si pentru `cauta_alfa`.
|
|
|
|
### 4.2 Precedentul direct: retur multi-factura
|
|
|
|
`frm_date_factura.do_cauta_facturi` (`ofacturare.vc2:9173-9212`) foloseste deja exact acest tipar,
|
|
pentru cazul "alege mai multe facturi sursa de retur":
|
|
|
|
```
|
|
lcXMLFacturi = caut_facturi_multiple_client(poDate.id_client, poDate.in_valuta, poDate.id_valuta, .T.)
|
|
If !Empty(lcXMLFacturi) and gnButon = 1
|
|
Xmltocursor(lcXMLFacturi, "crsFacturiTemp")
|
|
...
|
|
poDate.listaid = cursor2lista("crsFacturiTemp", "id_vanzare", ",")
|
|
```
|
|
|
|
si `caut_facturi_multiple_client` (`oproceduri_facturare.prg:2091-2121`) cheama direct
|
|
`cauta_alfa(..., lnTipReturn = Iif(tlFacturiMultiple, 1, 0))`. **Important pentru sectiunea 9**: acest
|
|
pas ruleaza azi la **antet** (`frm_date_factura`), inainte ca formularul de articole (si deci bara de
|
|
butoane S4b) sa existe — `poDate.listaid` e fixat o singura data, cursorul `crsarticole` se incarca
|
|
o singura data din el (`cursor_retur_document`, cu `V_LISTAID`). Optiunea "Adauga tot din facturile
|
|
alese" din meniul S4b **poate** refolosi direct `do_adauga_tot`/`crsarticole` asa cum e azi (sursa e
|
|
deja bounded). O optiune noua "Alege facturile de returnat…" **la nivelul barei de butoane** ar insemna
|
|
insa a permite schimbarea setului de facturi sursa **dupa** ce formularul de articole s-a deschis —
|
|
azi nu exista acest flux (odata setat, `poDate.listaid` nu se rescrie din articole). E o decizie de
|
|
proiectare noua, nu o simpla mutare a codului existent (vezi 9.3).
|
|
|
|
### 4.3 Ce cursor-sursa pe fiecare tip, si ce inseamna "linie" acolo
|
|
|
|
| Sursa | Cursor(oare) populat(e) la intrarea in `factureaza`/`factureaza2` | Ce e o "linie" pentru dialogul de alegere | `fisier:linie` |
|
|
|---|---|---|---|
|
|
| **comanda** (3, 21, 25, 28, 42, 47) | `crsarticole` <- `pack_facturare.cursor_comanda` | un articol de pe `COMENZI_ELEMENTE`, cu `id_pol` mostenit direct de pe linia comenzii | `ofacturare.prg:292-293` |
|
|
| **contract, `OPT_FACTURARE=3`** (2,6,26,52) | `crsarticole1` <- `pack_facturare.cursor_contract`, ramura `CTR_ARTICOLE` | un articol al contractului, `id_pol` derivat prin `CTR_ARTICOLE.ID_POL_ART -> CRM_POLITICI_PRET_ART` | `ff_...COMUN_PACK_FACTURARE.sql:2752-2836` |
|
|
| **contract, `OPT_FACTURARE IN (1,2)`** (2,6,26,52) | `crsarticole1` <- acelasi cursor, ramura `CTR_SCADENTAR` (`UNION ALL`) | o **rata** de scadentar (`ID_RATA`, `NR_RATA`, `DATA_RATA`, `DATA_SCADENTA`, `DEN_RATA`); `id_articol` e **NULL**, `cantitate` e mereu 1, `gestionabil=0` | `ff_...COMUN_PACK_FACTURARE.sql:2836-2924` |
|
|
| **contract, oricare din cele doua** — cautare libera | `crsarticole` <- acelasi apel, dar cu `pack_facturare.cursor_preturi` legat in interior | lista de preturi normala a operatorului (nu e "libera de politica", vezi `idpol_comanda_contract.md` E.3) | `ff_...COMUN_PACK_FACTURARE.sql:2940-2948` |
|
|
| **avize** (4) | `crsarticole` <- `pack_facturare.cursor_avize` | un rand de pe avizul sursa | `ofacturare.prg:294-295` |
|
|
| **retur** (8, 9, 24) | `crsarticole` <- `pack_facturare.cursor_retur_document`, filtrat pe `V_LISTAID` (facturile alese la antet, 4.2) | un articol al facturii/facturilor deja alese; **nicio coloana `id_vanzare`/`id_vanzare_det` in cursor** — legatura cu factura sursa se pierde inainte sa ajunga in VFP (`docs\cercetare\legatura_linie_retur.md:8-20`) | `ff_...COMUN_PACK_FACTURARE.sql:3949-4062` |
|
|
|
|
**Pe contract, `crsarticole1` e populat printr-un singur `UNION ALL`, dar cele doua ramuri sunt
|
|
disjuncte pe `OPT_FACTURARE`**: pentru un contract cu `OPT_FACTURARE=3`, `WHERE A.OPT_FACTURARE = 3`
|
|
elimina ramura de rate; pentru `OPT_FACTURARE IN (1,2)`, `WHERE ... IN (1,2)` elimina ramura de
|
|
articole. **Un contract nu produce niciodata ambele tipuri de rand in acelasi `crsarticole1`.** Deci
|
|
eticheta din meniu ("Adauga tot din contract" vs. "Adauga toate ratele") **trebuie sa depinda de
|
|
`crsarticole1.opt_facturare`** (coloana exista in cursor, `:2751,2893` — poate fi citita din primul
|
|
rand dupa incarcare), nu poate fi un text static ca in tabelul din plan.
|
|
|
|
**Daca `crsarticole1` iese gol** (contract fara articole/rate configurate), formularul de azi
|
|
**elimina complet** `grd_contracte`/`But_urmator2` si redistribuie inaltimea catre `grd_articole`
|
|
(`ofacturare.vc2:15294-15324`, `If !Used('crsarticole1') ... Thisform.RemoveObject('grd_contracte')`)
|
|
— documentul se comporta ca o factura "libera" din lista de preturi. Meniul S4b trebuie sa verifice
|
|
aceeasi conditie inainte sa ofere "Adauga tot din contract"/"Alege ratele…": daca cursorul nu exista
|
|
sau e gol, optiunea nu apare deloc (nu apare goala).
|
|
|
|
### 4.4 Populare aditiva si "nicio scriere pana la salvare"
|
|
|
|
Deja adevarat prin constructie, pentru toata familia `do_adauga_articol`: fiecare rand ales (fie prin
|
|
`do_adauga_tot`, fie prin rezultatul unui `cauta_alfa`) trece prin **`Thisform.do_adauga_articol(...)`**,
|
|
care termina cu `Insert Into crsfactura(...)` (cursor local, `.T. Buffering`) — niciun apel Oracle in
|
|
acest pas (Oracle e atins abia la salvarea documentului, `finalizeaza_factura`/`scrie_factura2`, in
|
|
afara acestei povesti). Un dialog nou de alegere trebuie doar sa **produca lista de randuri bifate**
|
|
(cursor XML din `cauta_alfa`) si sa **cheme aceeasi rutina** rand cu rand — vezi sectiunea 5, e
|
|
punctul care garanteaza si echivalenta cu "tot".
|
|
|
|
### 4.5 Zero rezultate — mesaj, nu tacere
|
|
|
|
RORIS nu spune nimic la zero rezultate (`import_roris_roaacnpro.md`, punctul 5: butonul "pare ca nu
|
|
face nimic"). `cauta_alfa` insasi nu are un mesaj dedicat de "zero rezultate" (e un browse generic —
|
|
daca cursorul de rezultate e gol, grila apare goala, fara alt semnal, cf. structurii ei standard).
|
|
**Reteta pentru S4b**: verificarea "zero rezultate" se face **inainte** de a deschide `cauta_alfa`
|
|
(similar cu `do_cauta_facturi`, care verifica intai `Empty(poDate.id_client)` inainte de a cauta),
|
|
printr-un `SELECT COUNT(*)` (sau verificare pe cursorul deja incarcat, `Reccount(...)=0`) urmat de
|
|
`AMESSAGEBOX` care spune **de ce**: "Contractul nu are rate de facturat neincasate" / "Comanda nu are
|
|
articole ramase de facturat" / etc., in loc sa lase dialogul sa se deschida gol. Exact tiparul deja
|
|
folosit de `do_adauga_tot` insusi pe ramura fara date (`:13195-13197`,
|
|
`"Nu exista articole de adaugat!"`) — se extinde acelasi obicei la dialogul de alegere.
|
|
|
|
---
|
|
|
|
## 5. Echivalenta „tot" vs. „alege"
|
|
|
|
**Garantia structurala exista, dar e incompleta azi.** Toate cele trei cai de populare a
|
|
`crsfactura` — `do_adauga_tot` (SCAN + apel), un viitor dialog de alegere (bifare + apel pe fiecare
|
|
rand bifat), si adaugarea manuala rand cu rand — converg spre **aceeasi rutina**,
|
|
`Thisform.do_adauga_articol(tlImplicit, tlContract, tlRetur)` (`ofacturare.vc2:12813-...`). Cata vreme
|
|
toate trei cheama exact aceasta rutina, cu acelasi cursor sursa pozitionat pe randul corect, rezultatul
|
|
per linie in `crsfactura` e identic prin constructie — nu exista o a doua cale de `INSERT` in
|
|
`crsfactura` in afara acestei rutine (confirmat prin cautarea `Insert Into crsfactura` — singurul alt
|
|
loc e ramura specifica `tip=30`/aviz din NIR, `ofacturare.prg:357-376`, care nu intra in perimetrul
|
|
S4b).
|
|
|
|
**Ce lipseste, concret, ca sa fie adevarat si pe contract**: `do_adauga_tot` (`:13169-13198`) parcurge
|
|
**doar `crsarticole`**. Pentru ca "Adauga tot din contract" / "Adauga toate ratele" sa functioneze,
|
|
`do_adauga_tot` are nevoie de o ramura noua (sau un al doilea parametru `tlContract`, simetric cu
|
|
`do_adauga_articol`) care sa faca `SCAN` peste `crsarticole1` si sa cheme
|
|
`Thisform.do_adauga_articol(.T., .T.)`. Fara aceasta completare, "tot" pe contract fie nu exista, fie
|
|
(daca cineva ar face butonul vizibil fara sa atinga metoda) ar aduce tacut liniile gresite din
|
|
`crsarticole` (lista de preturi) in loc de `crsarticole1` (articolele/ratele contractului) — o eroare
|
|
mai grava decat lipsa vizibilitatii, pentru ca n-ar da nicio eroare, doar rezultat gresit.
|
|
|
|
**Alegerea selectiva** trebuie sa respecte aceeasi regula: dupa ce `cauta_alfa` intoarce XML-ul cu
|
|
randurile bifate, bucla care le proceseaza trebuie sa pozitioneze cursorul sursa (`crsarticole` sau
|
|
`crsarticole1`, dupa caz) pe `id_c`-ul corespunzator inainte de fiecare apel `do_adauga_articol`, **nu**
|
|
sa reconstruiasca linia din campurile XML direct — altfel cele doua cai ("tot" vs. "alege") ar avea
|
|
doua implementari diferite ale "ce inseamna sa adaug randul X", exact riscul pe care criteriul de gata
|
|
din plan il exclude explicit ("rezultatul in `crsfactura` e identic pe cele doua cai cand selectia e
|
|
totala").
|
|
|
|
**Pe comanda/avize/retur, criteriul e deja adevarat prin constructie** — `do_adauga_tot` foloseste azi
|
|
`crsarticole`, care e cursorul lor unic; singurul de completat e contractul (cele doua cazuri de mai
|
|
sus).
|
|
|
|
---
|
|
|
|
## 6. Interactiunea cu S4 (cautarea articolelor pe server)
|
|
|
|
Decizia din S4 (`plan_13...md:1879-1888`) e explicita: `crsarticole` **nu se mai incarca in masa**
|
|
pentru facturarea libera (lista de preturi/nomenclator), inlocuita cu `combosql` pe cod/denumire care
|
|
completeaza randul pe loc — **dar** "se pastreaza adauga tot pentru tipurile care au document sursa
|
|
(comanda, aviz, contract) — acolo setul e marginit si incarcarea lui e legitima". Consecinta directa
|
|
pentru meniul S4b:
|
|
|
|
- **Optiunile "Cauta in lista de preturi…" si "Alege din nomenclator…"** (constante peste tot, cf.
|
|
deciziilor 16/18/20) **nu deschid un dialog de tip `cauta_alfa`** — ele sunt fatada meniului pentru
|
|
mecanismul S4: `combosql` pe o singura linie, populata pe loc, fara incarcare in masa. In termeni de
|
|
UI, alegerea uneia din aceste doua optiuni echivaleaza cu ce face azi `But_nou1.do_adauga` din
|
|
prototip (`APPEND BLANK` + focus pe celula de cod/denumire) — deci **"linie noua" (sectiunea 1) si
|
|
aceste doua optiuni de meniu ajung la acelasi gest UI**, doar ca "linie noua" il porneste direct
|
|
(fara meniu), iar cele doua optiuni de meniu il pornesc din context (dupa ce operatorul a vazut si
|
|
restul optiunilor sursei). Nu sunt cai de cod diferite — sunt doua puncte de intrare in acelasi
|
|
`APPEND BLANK` + editare inline.
|
|
- **Toate optiunile "Adauga tot din X…" / "Alege X…"** (comanda, contract, avize, retur) opereaza pe
|
|
cursoarele bounded (`crsarticole`/`crsarticole1`) pe care **S4 le pastreaza neschimbate** — pentru
|
|
aceste tipuri, nimic din mecanismul de cautare pe server nu se aplica; secțiunile 3-5 de mai sus
|
|
raman valabile ca atare.
|
|
- **Punct de atingere real intre cele doua povesti**: campul `id_pol` pe randul adaugat prin
|
|
`combosql` (S4, cautare din nomenclator liber) — subiectul blocajului `FACT-024` documentat pe larg
|
|
in plan (J-ter/J-quater) si in `idpol_comanda_contract.md`. S4b **nu rezolva** acest blocaj (e
|
|
decizia de produs deschisa la J-quater, intre reteta in 4 pasi / nota pe antet / nota pe antet ca
|
|
fallback) — doar il mosteneste: optiunea "Alege din nomenclator…" din meniul S4b va ajunge la aceeasi
|
|
eroare `FACT-024` la salvare, indiferent de cum arata butonul, pana cand acea decizie separata se ia.
|
|
De mentionat explicit in criteriul de gata al S4b, ca sa nu se creada ca butonul rezolva problema.
|
|
|
|
---
|
|
|
|
## 7. Ordinea de executie in pasi
|
|
|
|
1. **Bara de linie (`but_nou`, `but_sterge`, "detalii linie")**, mutata deasupra gridului, cu
|
|
`Caption` explicit pe fiecare instanta (clasele `but_nou`/`but_sterge` au deja `ToolTipText`, nu au
|
|
niciodata `Caption` — de setat pe instanta, nu de asteptat de la clasa).
|
|
*Verificabil*: cele trei butoane sunt vizibile deasupra gridului de linii, fiecare cu text vizibil
|
|
(nu doar iconita), pe orice tip de document deschis.
|
|
2. **Corectarea `Do Case` din `Init`** (`ofacturare.vc2:15109-15248`): adauga `52` la ramura
|
|
`Inlist(poDate.tip, 2, 6)` (linia 15129) astfel incat sa primeasca titlu, eliminare `cSerie`, si sa
|
|
fie tratat identic cu 2/6 in tot restul metodei — corecteaza golul mai mare decat cel semnalat in
|
|
plan (sectiunea 3 de mai sus). Adauga `26` la lista tipurilor care primesc `but_urmator_tot1.Visible
|
|
= .T.` candva in pasul 3, nu aici (26 ramane azi cu titlu corect, doar fara butonul "tot").
|
|
*Verificabil*: un document nou de tip 52 arata acelasi titlu si acelasi grid (fara `cSerie`) ca un
|
|
document de tip 2/6.
|
|
3. **Extinderea `do_adauga_tot`** cu ramura pe `crsarticole1` (parametru sau ramura separata dupa
|
|
`poDate.tip`/`crsarticole1.opt_facturare`), plus vizibilitatea butonului/optiunii pe 2/6/26/52 —
|
|
**cei doi pasi impreuna**, nu separat (vizibilitate fara continut ar aduce un buton mut; continut
|
|
fara vizibilitate nu s-ar vedea niciodata).
|
|
*Verificabil*: pe un contract cu `OPT_FACTURARE=3` si articole configurate, "adauga tot" produce in
|
|
`crsfactura` exact liniile din `crsarticole1`; pe un contract cu `OPT_FACTURARE IN (1,2)`, produce
|
|
cate o linie per rata neincasata.
|
|
4. **Butonul unic "Adauga articole" cu `xmenu()`**, inlocuind `But_urmator_tot1` (fara caption) si
|
|
orice buton separat de alegere — construit dinamic dupa tabelul din sectiunea 3, cu eticheta pe
|
|
ramura de contract aleasa in functie de `crsarticole1.opt_facturare` (sectiunea 4.3).
|
|
*Verificabil*: pe fiecare sursa, meniul deschis contine exact optiunile din tabelul sectiunii 3, in
|
|
ordinea specificata, iar alegerea `ESC` (`xmenu()` intoarce 0) nu declanseaza nimic.
|
|
5. **Dialogul de alegere selectiva**, pe reteta `cauta_alfa(..., tnTipReturn=1)` (sectiunea 4),
|
|
cu mesaj explicit la zero rezultate (4.5) si populare prin `do_adauga_articol` rand cu rand (5) —
|
|
cate o instantiere per sursa (comanda/contract-articole/contract-rate/avize/retur-linii), cu
|
|
`tcselect`/`tcfiltru` proprii.
|
|
*Verificabil*: pe fiecare sursa, bifarea a N randuri din M disponibile adauga exact acele N randuri
|
|
in `crsfactura`, cu aceleasi valori ca daca ar fi fost adaugate individual; bifarea tuturor produce
|
|
acelasi rezultat ca "adauga tot" (criteriul de gata al plan-ului, rescris verificabil).
|
|
*Depinde de*: pasul 3 (aceeasi rutina `do_adauga_articol` trebuie sa functioneze deja pe
|
|
`crsarticole1` inainte ca dialogul de alegere sa se poata baza pe ea).
|
|
6. **Reconcilierea cu selectia de facturi la antet** (sectiunea 4.2, 9.3) — decizie separata,
|
|
nu blocanta pentru pasii 1-5: daca "Alege facturile de returnat…" ramane doar la antet (cum e azi)
|
|
sau devine posibila si din bara de butoane.
|
|
|
|
*Gata cand (rescris)*: pe fiecare din cele sase surse (lista de preturi, contract-articole,
|
|
contract-rate, comanda, avize, retur), meniul "Adauga articole" ofera exact optiunile tabelate in
|
|
sectiunea 3; pentru fiecare sursa cu "tot"/"alege" ambele prezente, o selectie totala prin dialogul de
|
|
alegere produce in `crsfactura` acelasi set de randuri (aceleasi valori, nu doar acelasi numar) ca
|
|
"adauga tot"; zero rezultate in orice dialog de alegere produce un mesaj care spune sursa si motivul,
|
|
nu un dialog gol; tip 52 se comporta identic cu tip 2/6 in titlu si structura de grid.
|
|
|
|
---
|
|
|
|
## 8. Ce NU se poate testa headless
|
|
|
|
- **Continutul si comportamentul meniului `xmenu()`** — `Activate Screen` + `Define Popup ... Bar` e
|
|
UI nativa Windows/VFP (shortcut popup la pozitia mouse-ului); nu exista API de citire a itemilor unui
|
|
popup activ prin automatizare headless. Verificarea "meniul contine optiunile N" se poate face doar
|
|
**indirect**, citind stringul `lcMeniu` construit inainte de apelul `xmenu()` (verificabil headless,
|
|
ca text), nu popup-ul afisat efectiv.
|
|
- **Coloanele griduri (`grd_articole`, `grd_contracte`, `grd_factura`, si viitorul grid al dialogului
|
|
de alegere)** — capcana deja cunoscuta si confirmata pe acest proiect: sub `-A -T`
|
|
(rulare headless) `ColumnCount=0` si `RecordSource` raman artefacte, coloanele nu se materializeaza.
|
|
Exista un harness UI **vizibil** (nu headless) care le citeste corect — orice verificare vizuala a
|
|
meniului/dialogului de alegere trebuie sa treaca prin acel harness, nu prin rulare `-A -T`.
|
|
- **`cauta_alfa`/`cauta_alfa_form_plus`** — dialog modal cu `.Show(1)`, blocheaza thread-ul UI pana la
|
|
interactiune; testarea automata ar necesita fie injectare de input (interzisa pe aceasta masina,
|
|
partajata cu Marius — vezi memoria `masina-partajata-fara-input-real`), fie apelarea directa a
|
|
functiilor Oracle/cursor din spatele dialogului, ocolind UI-ul (verifica *datele*, nu *dialogul*).
|
|
- **`AMESSAGEBOX` la zero rezultate** — verificabil ca text al mesajului in cod (string literal), nu ca
|
|
aparitie reala pe ecran, din acelasi motiv.
|
|
- **Pozitionarea vizuala "deasupra gridului"** (`Top`/`Height` relative) — se poate verifica numeric
|
|
(comparand `Top`-ul butoanelor cu `Top`-ul gridului in `.vc2`), dar nu si "arata bine"/aliniere
|
|
vizuala — necesita captura de ecran prin harness-ul UI vizibil.
|
|
|
|
Ce **se poate** verifica headless, direct: continutul cursoarelor (`crsarticole`, `crsarticole1`,
|
|
`crsfactura`) dupa apelul rutinelor de adaugare, apelate direct (nu prin click) cu parametri de test;
|
|
stringul `lcMeniu` construit inainte de `xmenu()`; valorile `Visible`/`Caption`/`ToolTipText` setate pe
|
|
obiectele din `.vc2` (proprietati statice, nu comportament de runtime).
|
|
|
|
---
|
|
|
|
## 9. Riscuri, capcane de UX, si ce ramane de decis de Marius
|
|
|
|
### 9.1 Regulile de formulare/griduri (`COMUN\docs\reguli_lucru.md`, punctul 7)
|
|
|
|
Aplicabile direct aici (citite, respectate in proiectarea de mai sus):
|
|
- **`GO` pe `Recno()`** — orice bucla de tip `do_adauga_tot`/dialog de alegere care itereaza cursorul
|
|
sursa (`crsarticole`/`crsarticole1`) trebuie sa retina si sa refaca pozitia (`Recno()`) dupa fiecare
|
|
apel `do_adauga_articol`, exact cum face deja `do_adauga_tot` azi (`lnNrInregistrare = Recno()` ...
|
|
`Go lnNrInregistrare`, `:13175,13185,13193`) — pastrat si in ramura noua pe `crsarticole1`.
|
|
- **UX formulare/griduri** — butoanele fara `Caption` sunt azi conforme cu restul suitei (toate
|
|
butoanele suita sunt icon-only); a le adauga `Caption` e o schimbare vizibila la nivelul intregii
|
|
bare, nu doar a celor trei butoane noi — de discutat daca `But_renunt1`/`But_reset1` raman mute langa
|
|
butoane cu text (inconsistenta vizuala posibila, nu doar tehnica).
|
|
|
|
### 9.2 Contractul are doua meniuri, nu unul (sectiunea 4.3)
|
|
|
|
Tabelul din plan (J) trateaza "contract" ca o singura sursa cu un singur set de optiuni. Pe cod, un
|
|
contract e **fie** OPT_FACTURARE=3 (articole), **fie** 1/2 (rate) — niciodata ambele. Eticheta
|
|
"Alege ratele de facturat…" din decizia explicita a lui Marius e corecta doar pe ramura a doua; pe
|
|
prima, echivalentul e "Alege articolele din contract…". **De decis**: se pastreaza o singura eticheta
|
|
generica ("Alege din contract…") care acopera ambele cazuri fara sa distinga in text, sau se
|
|
diferentiaza explicit (mai clar pentru operator, dar mai mult cod de verificare a lui
|
|
`crsarticole1.opt_facturare` inainte de a construi meniul)?
|
|
|
|
### 9.3 "Alege facturile de returnat…" — la antet sau la bara de butoane?
|
|
|
|
Azi (sectiunea 4.2), selectia facturilor sursa pentru retur se face **o singura data**, la deschiderea
|
|
formularului de antet (`frm_date_factura.do_cauta_facturi`), inainte ca formularul de articole sa
|
|
existe. Meniul S4b, asa cum e cerut de decizia 13, ar pune "Alege facturile de returnat…" **in bara de
|
|
butoane a formularului de articole** — adica dupa ce `poDate.listaid` a fost deja fixat. Doua optiuni,
|
|
de decis de Marius:
|
|
1. Optiunea din meniul S4b **nu schimba** setul de facturi sursa — e doar un rascolitor spre inapoi,
|
|
catre acelasi dialog de la antet, dar utilizatorul trebuie sa iasa din pasul de articole ca sa-l
|
|
foloseasca (comportament posibil confuz: optiunea apare in meniul de articole, dar actioneaza pe alt
|
|
ecran).
|
|
2. Se adauga un mecanism nou: alegerea de facturi suplimentare **din formularul de articole**, care
|
|
extinde `poDate.listaid` si reincarca aditiv `crsarticole` (`cursor_retur_document` apelat a doua
|
|
oara, cu filtru pe facturile noi, `INSERT INTO crsarticole` in loc de `SELECT INTO`) — cere cod nou
|
|
in VFP, dar nu in `pack_facturare` (procedura Oracle ramane aceeasi, doar apelata de mai multe ori).
|
|
|
|
"Alege liniile de returnat…" (per articol, din facturile deja alese) e diferita si **nu are conflict**
|
|
cu fluxul de azi — e un dialog de alegere clasic peste `crsarticole`, ca pe comanda/avize.
|
|
|
|
### 9.4 `id_pol` pe rata de contract — `NULL` prin constructie, dar validat corect
|
|
|
|
Rata de scadentar (`crsarticole1`, ramura `OPT_FACTURARE IN (1,2)`) are **`id_pol` NULL** prin
|
|
constructia SQL insasi (`NULL AS ID_POL`, `:2840`) — dar asta nu ajunge niciodata la `FACT-024`,
|
|
pentru ca ratele nu trec prin `contabilizeaza_articol`, ci prin `contabilizeaza_rata` (functie separata
|
|
in `pack_facturare`, `idpol_comanda_contract.md` §0c), care citeste nota din `CONTRACTE.ID_NOTA`. **De
|
|
verificat inainte de implementare**: `do_adauga_articol`/`do_scrie_articole` scriu randul de rata in
|
|
`crsfactura` cu ce anume in coloana `id_pol` (probabil `NULL`, mostenit din `poArticol`) — daca
|
|
salvarea foloseste ramura corecta (`contabilizeaza_rata`, nu `contabilizeaza_articol`) pe baza altui
|
|
semnal decat `id_pol` (probabil `id_ctr`/`opt_facturare` pe linie), nu pe baza lui `id_pol` fiind gol.
|
|
Nu s-a verificat cine alege intre cele doua functii la salvare — e in afara perimetrului S4b (tine de
|
|
scriere, nu de bara de butoane), dar merita un pointer explicit ca sa nu se presupuna gresit ca "rata
|
|
fara `id_pol`" e acelasi caz cu "articol din nomenclator fara `id_pol`" (J-quater) — sunt cai de cod
|
|
diferite, cu tratament diferit.
|
|
|
|
### 9.5 Ce ramane strict de decis de Marius
|
|
|
|
1. Eticheta pe contract (9.2) — generica sau diferentiata pe `OPT_FACTURARE`.
|
|
2. Fluxul "Alege facturile de returnat…" (9.3) — raman la antet sau se adauga incarcare aditiva.
|
|
3. Daca `But_renunt1`/`But_reset1` primesc si ele `Caption`, pentru consistenta vizuala cu bara nou-
|
|
etichetata, sau raman icon-only (9.1).
|
|
4. Ordinea si formularea exacta a optiunilor in `xmenu()` per sursa (tabelul din sectiunea 3 e o
|
|
propunere, nu o decizie finala de text).
|
|
|
|
---
|
|
|
|
## Handoff
|
|
|
|
Cercetare incheiata, fara nicio problema de context intalnita in aceasta runda — nu a fost necesara
|
|
predarea. Toate cele noua sectiuni cerute de brief sunt completate mai sus, cu `fisier:linie` verificat
|
|
direct pe fisierele text reale (nu `.bak`), plus SQL-ul din `PACK_FACTURARE` exportat curent
|
|
(`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql`). Nicio editare de
|
|
cod, niciun `git_sync.ps1`/`txt2vcx.ps1`, niciun commit.
|