603 lines
42 KiB
Markdown
603 lines
42 KiB
Markdown
# S3b — Proiectare: sectiunea pliata "alte date + analitice"
|
|
|
|
Livrabilul povestii **S3b** din `docs\plan_13_unificare_formular_facturare.md:1838-1854` (deciziile 7,
|
|
8, 25, 26). Proiectare pe cod, fara nicio modificare — zero editari, zero
|
|
`git_sync.ps1`/`txt2vcx.ps1`, zero commit. `COMUN\clase\ofacturare_comun.vc2` si
|
|
`COMUN\programe\ofacturare_editare.prg` (perimetrul #6) doar citite, neatinse.
|
|
|
|
## Verdict (rezumat)
|
|
|
|
S3b nu e o simpla "mutare de controale" cum sugereaza textul din plan. **Descoperirea centrala,
|
|
negasita in materialele existente**: mecanismul de alocare a numarului de chitanta nu porneste doar
|
|
din clicul utilizatorului pe `opt_incasat` — porneste din **orice** atribuire programatica a
|
|
proprietatii `.Value`, pentru ca `opt_incasat.ProgrammaticChange` (`ferestre_cere_date.vc2:3351-3352`)
|
|
cheama exact acelasi `actualizeaza_tipincasare()` ca si `.Click` (`:3250-3251`). `Init`-ul de azi
|
|
(`:3150`) seteaza chiar el `Thisform.opt_incasat.Value = 2` cand documentul soseste cu
|
|
`poDate.incasat<>0` (caz real: copiere, confirmat la `ofacturare_stoc.prg:535`,
|
|
`oproceduri_facturare.prg:1186`, `ofacturare_comun.vc2:4066,4260`) — deci **azi, deschiderea
|
|
dialogului aloca deja un numar de chitanta fara ca userul sa atinga nimic**, de fiecare data cand
|
|
documentul soseste cu o incasare presetata. In formularul unificat, unde zona nu se mai deschide o
|
|
singura data modal ci se pliaza/depliaza repetat pe acelasi obiect `poDate` persistent, acelasi cod
|
|
rulat la fiecare depliere ar realoca/dealoca la fiecare toggle — exact opusul criteriului cerut de
|
|
decizia 25. Sectiunea 4 trateaza asta ca risc central, cu recomandare concreta.
|
|
|
|
A doua descoperire: **niciun mecanism de pliere reutilizabil nu exista** in prototipul
|
|
`frm_facturare_articole2` (cautare completa, zero potriviri pe "plia/colaps/accordion/expand" in
|
|
`ofacturare.vc2`) — cel mai apropiat tipar din suita e `frm_modific2024.afiseaza_rulaje`
|
|
(`omodificari.vc2:13169-13199`, perimetrul #6, citit dar neatins), care refoloseste **acelasi idiom
|
|
sus/jos** deja validat pentru `but_modifica`/`but_salveaza` (decizia 9), dar aplicat unui show/hide,
|
|
nu unei blocari. Sectiunea 6 detaliaza.
|
|
|
|
A treia: pentru analiticele read-only (decizia 26), mecanismul existent `ct_clb_cautare.do_dezactiveaza()`
|
|
(`caut_ora.vc2:800-806`) **ascunde doar lupa de cautare**, nu blocheaza si textbox-ul de afisare —
|
|
cineva tot poate scrie liber in camp. Sectiunea 2 detaliaza gap-ul si completarea minima necesara.
|
|
|
|
---
|
|
|
|
## 1. Inventarul exact al celor patru grupuri din `frm_alte_date`
|
|
|
|
Sursa primara a controalelor: `docs\cercetare\inventar_controale_formulare.md` §4 si
|
|
`docs\S1_inventar_campuri_formular_unificat.md` (randurile "Pliat — alte date"), reconfirmate aici
|
|
direct pe `COMUN\clase\ferestre_cere_date.vc2` (clasa `frm_alte_date`, `2219-3353`; garda de validare
|
|
`inainte_de_do_termin` la `3044-3103`, `Init` la `3105-3208`).
|
|
|
|
### 1.1 Delegat / transport
|
|
|
|
| Control | Caption real | `fisier:linie` (ADD OBJECT) | Vizibilitate | Ruta de scriere (din rute_scriere_antet.md / S1) |
|
|
|---|---|---|---|---|
|
|
| `Ct_clb_delegat` | "Delegat" | `ferestre_cere_date.vc2:2553` (container `ct_clb_cautare`-like, `caution=do_cauta_delegat`) | pliat, mereu editabil pe document nou; **eliminat cu totul** cand `poDate.eProforma=1` (`:3192`) | pe loc, `modifica_date_factura` (`V_ID_DELEGAT`), neconditionat — `modifica_date_factura_parametri.md:17` |
|
|
| `Ct_clb_masina` | "Masina" | `:2569` | idem, eliminat pe proforma (`:3193`) | `V_ID_MASINA`, neconditionat — `:18` |
|
|
| `Ct_clb_agent` | "Agent" | `:2537` | idem, **nu e eliminat pe proforma** (nu apare in cascada `RemoveObject` `:3192-3201`) | `V_ID_AGENT`, neconditionat — `:19` |
|
|
| `Clb_dataora_exp` | "Data si ora expedierii" | `:2443` | idem, nu eliminat pe proforma; **validat obligatoriu** in `inainte_de_do_termin` (`:3062-3067`, `Case Empty(Nvl(poDate.dataora_exp,{})) And poDate.eProforma = 0`) | `V_DATAORA_EXP`, neconditionat — `:20` |
|
|
| `But_modifica1` | (icon, `caction` implicit -> `do_modifica`) | `:2343` | actiune, nu camp — deschide `nom_parteneri_modifica` pe delegatul curent (`ferestre_cere_date.vc2:2925-2935`) | — |
|
|
|
|
**Validarea de grup** (`inainte_de_do_termin`, `:3055-3060`): delegatul e obligatoriu doar cand
|
|
`gcNumeProgram = [ROAFACTURARE]` **si** documentul nu e proforma sau bon fiscal
|
|
(`!(poDate.eProforma = 1 OR poDate.eBonFiscal = 1)`) — nuanta care trebuie pastrata identic in
|
|
formularul unificat, nu doar copiata "delegat obligatoriu".
|
|
|
|
### 1.2 Incasare (grupul cel mai mare, vezi si sectiunile 3-4)
|
|
|
|
| Control | Caption real / eticheta dinamica | `fisier:linie` | Vizibil cand |
|
|
|---|---|---|---|
|
|
| `opt_incasat` (radiogrup 4 optiuni) | "Fara incasare" / "Chitanta" / "Bon fiscal" / "POS Card" | `:2638-2685` (default `Value=1`) | mereu, dar **intreg containerul incasare** dispare pe proforma (`:3140-3143`, `Thisform.opt_incasat.Visible = .F.`, doar pe ramura non-proforma exista oricum) si pe `gcNumeProgram=[ROAGEST]` sau `!Between(poDate.tip,1,4)` |
|
|
| `Cb_casa` | "Casa" -> "Banca POS" pe POS (`:2967` `_lbbase1.Caption='Banca POS'`) | `:2362` | ascuns doar la `opt_incasat=1` |
|
|
| `Clb_serie_chit` | "Serie chitanta" | `:2503` | vizibil **doar** la Chitanta (`Value=2`) |
|
|
| `Clb_nrchit` | "Nr. chitanta" -> "Nr. bon" pe Bon fiscal/POS | `:2480` | ascuns doar la `Value=1` |
|
|
| `Clb_incasat` | "Incasat" | `:2461` | ascuns doar la `Value=1` |
|
|
| `cmdModificaBon` | icon, `caction=do_modifica_bon` | `:2526` | vizibil **doar** la Bon fiscal (`Value=3`) |
|
|
| `chkPOS` | "POS" | `:2409` | vizibil la Bon fiscal (`Value=3`, bifabil) **si** la POS (`Value=4`, fortat `.T.` si ascuns — `:2845` `thisform.chkPOS.Value=1` apoi `.Visible=.F.`) |
|
|
| `chkDetaliat` | "Detaliat" | `:2396` | vizibil doar la Bon fiscal |
|
|
| `cboTipFactura` | combo, langa "Tip factura" | `:2378` | mereu (langa incasare), scrie `poDate.tip_saft` |
|
|
|
|
Masina de stari completa e la sectiunea 3-4. **Eticheta "Casa"/"Banca POS" si vizibilitatea lui
|
|
`chkPOS`/`chkDetaliat` fac parte din aceeasi metoda unica** (`actualizeaza_tipincasare`) — nu sunt
|
|
conditii separate de refacut, sunt randuri din acelasi `Do Case`.
|
|
|
|
### 1.3 Adresa de facturare
|
|
|
|
| Control | Caption | `fisier:linie` | Vizibilitate |
|
|
|---|---|---|---|
|
|
| `clb_adresa_facturare` | "Adresa facturare" | `:2422` | pliat, mereu editabil; **nu** eliminat pe proforma (absent din cascada `:3192-3201`) |
|
|
| `do_cauta_adresa` (metoda, nu control separat) | — | `:2911-2926` | cauta pe `poDate.id_client`, seteaza `poDate.adresa_facturare`/`poDate.id_facturare` |
|
|
|
|
Ruta de scriere: `V_ID_FACTURARE`, neconditionat — `modifica_date_factura_parametri.md:21`.
|
|
|
|
### 1.4 Text aditional
|
|
|
|
| Control | Caption | `fisier:linie` | Vizibilitate |
|
|
|---|---|---|---|
|
|
| `Ed_tx_simplu1` | "Text aditional (max. 1000 caractere)" | `:2585` | pliat, mereu editabil; nu eliminat pe proforma — dimpotriva, **pe proforma ramane singurul grup activ**, formularul se redimensioneaza in jurul lui (`:3184-3207`) |
|
|
| `_checkbox1` ("Listare detaliata") | "Listare detaliata" | `:3002-3011` | ADD OBJECT separat, `ControlSource=poDate.nListareDetaliata` — **nu e in cascada celor patru grupuri din B**, e propriul lui control, langa text aditional in layout, dar conceptual apartine grupului de raportare (I-bis) alaturi de `tip_saft`/`efactura`, nu grupului "text aditional" |
|
|
|
|
Ruta: `V_TEXT_ADITIONAL`, neconditionat, **fara** `NVL` — `modifica_date_factura_parametri.md:23`.
|
|
|
|
**Observatie structurala pentru mockup**: `_checkbox1` (listare detaliata) e cablat separat de
|
|
`chkDetaliat` din grupul incasare (control diferit, aceeasi semantica probabila — ambiguitate deja
|
|
semnalata in S1, randul 57, neinchisa aici). Formularul unificat trebuie sa aleaga **unul singur**
|
|
dintre cele doua controale existente, nu sa le porteze pe amandoua.
|
|
|
|
---
|
|
|
|
## 2. Analiticele coborate din antet (decizia 8, nuantata de decizia 26)
|
|
|
|
Controale: `Ct_clb_venchelt` ("Venit / cheltuiala"), `Ct_clb_sectie` ("Sectie"), `Ct_clb_responsabil`
|
|
("Responsabil"), `Ct_clb_lucrare` ("Lucrare") — toate patru container `ct_clb_cautare` (subclasa
|
|
`caut_ora.vcx`), azi pe `frm_date_factura`/`frm_date_aviz`, **nu** pe `frm_alte_date`
|
|
(`inventar_controale_formulare.md` §3; S1 randurile 39-42). Live in sectiunea I a planului ca grup
|
|
"Pliat — analitice", distinct de cele patru grupuri ale lui `frm_alte_date` — dar aceeasi sectiune
|
|
pliata a formularului unificat, conform textului S3b ("peste ele coboara analiticele din antet").
|
|
|
|
### 2.1 Ce inseamna "afisare read-only" mecanic
|
|
|
|
Sursa: `docs\cercetare\rute_scriere_antet.md` §1 — verdict deja stabilit, **DA** pentru
|
|
`ID_SECTIE`/`ID_RESPONSABIL`/`ID_LUCRARE` printr-o cale noua (`frm_facturi.do_editare_factura` ->
|
|
`frm_modific2024`, perimetrul #6), **neconfirmat** pentru `ID_VENCHELT`. Pentru #13, indiferent de
|
|
raspunsul acelei rezerve, decizia 26 e explicita: **zero editare din formularul unificat**, oricare ar
|
|
fi ruta reala din Oracle.
|
|
|
|
**Mecanismul de blocare vizuala, verificat pe cod, cu un gap real**:
|
|
`ct_clb_cautare.do_dezactiveaza()` (`caut_ora.vc2:800-806`):
|
|
```
|
|
PROCEDURE do_dezactiveaza
|
|
This.lactiv = .F.
|
|
This.img_cautare.Visible = .F.
|
|
This.ctooltip = This.clb_tx_cautare.text_simplu1.ToolTipText
|
|
This.clb_tx_cautare.text_simplu1.ToolTipText = []
|
|
This.clb_tx_cautare.text_simplu1.Refresh()
|
|
ENDPROC
|
|
```
|
|
`This.lactiv` gateaza **doar** deschiderea dialogului de cautare — `DblClick` (`:822-826`),
|
|
`KeyPress` pe Enter/Tab/F7 (`:829-836`), `img_cautare.Click` (`:840-843`) — toate testeaza
|
|
`This.Parent(.Parent).lactiv` inainte sa cheme `do_apeleaza()`. **Nu seteaza `ReadOnly` pe
|
|
`clb_tx_cautare.text_simplu1`** — textbox-ul bindat (`ControlSource=This.cvar_afisata`, setat in
|
|
`Init`, `caut_ora.vc2:814-817`) ramane direct tastabil. Pentru un camp cu adevarat read-only (decizia
|
|
26 cere explicit "nu se editeaza"), `do_dezactiveaza()` trebuie **completat**, nu doar apelat: se
|
|
adauga `This.clb_tx_cautare.text_simplu1.ReadOnly = .T.` (si eventual `.TabStop = .F.`, ca sa nu
|
|
primeasca focus deloc) langa apelul existent — o linie noua, in tiparul deja recomandat de plan
|
|
(sectiunea I: "singura reteta completa e `clb_tx_data.dezactiveaza()`... se generalizeaza de la ea").
|
|
|
|
**Consecinta pentru "un singur buton deschide tot" (decizia 9)**: `do_dezactiveaza()` se apeleaza **o
|
|
singura data**, la constructia sectiunii, **si nu se mai cheama niciodata `do_activeaza()`** pentru
|
|
aceste patru controale — nici cand `but_modifica` deblocheaza restul antetului. E o exceptie
|
|
deliberata de la "un singur control comanda toata protectia antetului" (plan I:843-853), simetrica cu
|
|
exceptia deja acceptata pentru grupurile B/C la decizia 25 (sectiunea 5 de mai jos).
|
|
|
|
### 2.2 Eticheta / tooltip
|
|
|
|
Nicio propunere de text nu exista inca in materialele citite — de scris la implementare. Recomandare
|
|
minima, in stilul deja folosit in codebase (ex. `Ct_clb_gestiune_init.ToolTipText`, un citat complet
|
|
la `inventar_controale_formulare.md:93-95`, deci precedent de lungime/ton acceptat): eticheta ramane
|
|
neschimbata ("Venit / cheltuiala"/"Sectie"/"Responsabil"/"Lucrare"), `ToolTipText` nou de tipul
|
|
*"Se editeaza din Editare factura (articole, cantitati, preturi) — buton disponibil pe fiecare linie
|
|
a notei contabile"*, ca sa nu para camp stricat. Text exact — **de decis de Marius**, vezi sectiunea 9.
|
|
|
|
### 2.3 Nivel antet vs. nivel linie — de retinut la afisare
|
|
|
|
`rute_scriere_antet.md` §1.4: editarea reala prin #6 e **pe linie de nota**, nu pe antet — un
|
|
document poate ajunge cu sectii diferite pe linii diferite dupa editare (imposibil la emitere). Cand
|
|
formularul unificat afiseaza analiticele "cu valoarea de antet" (cum spune decizia 26), afiseaza de
|
|
fapt **o singura valoare reprezentativa** (probabil prima linie sau variabila de sesiune retinuta la
|
|
emitere), nu o agregare a liniilor — daca liniile diverg dupa o editare #6, afisarea din #13 devine
|
|
"aproximativa, nu autoritara". Nu e o contradictie de rezolvat aici (decizia 26 exista tocmai ca sa
|
|
evite ca #13 sa scrie peste diferentierea de linie), dar merita un rand explicit in criteriul de
|
|
"gata" (sectiunea 10): afisarea trebuie sa spuna clar ce valoare arata, nu sa pretinda ca e valoarea
|
|
unica a documentului daca liniile difera.
|
|
|
|
---
|
|
|
|
## 3. `actualizeaza_tipincasare`
|
|
|
|
Definita la `COMUN\clase\ferestre_cere_date.vc2:2698-2856`, metoda proprie a clasei `frm_alte_date`.
|
|
Comuta vizibilitatea intregului subgrup de incasare pe `This.opt_incasat.Value` (patru ramuri, tabel
|
|
complet la sectiunea 1.2 si in `inventar_controale_formulare.md:130-135`) **si**, in aceeasi metoda,
|
|
aloca/dezaloca numerele — cele doua responsabilitati (UI si alocare) sunt **impletite in acelasi
|
|
`Do Case`**, nu separate. Fiecare ramura incepe prin a dezaloca defensiv celelalte trei tipuri de
|
|
numar, apoi aloca pe cel curent daca e cazul:
|
|
|
|
| `opt_incasat.Value` | Dezaloca la intrare | Aloca | Alte efecte |
|
|
|---|---|---|---|
|
|
| 1 (Fara incasare) | 16, 3, 26 | — | `poDate.incasat=0`, `poDate.nr_incasare=0` |
|
|
| 2 (Chitanta) | 3, 16, 26 | `creeaza_cursor_serii(16)` + `clb_serie_chit.genereazaNumar()` (`:2783`) — doar daca `nRezultatSerii=0` (nu realoca daca seria era deja creata) | `poDate.incasat=poDate.totalctva` |
|
|
| 3 (Bon fiscal) | 3, 16, 26 | `do_aloca_nr_bon([CLICK])` (`:2807`) -> cod 3 | idem, plus `tip_saft` poate deveni 751 daca `gnEFactura_tip_saft_bf` e setat |
|
|
| 4 (POS/Card) | 3, 16, 26 | `do_aloca_nr_pos([CLICK])` (`:2844`) -> cod 26 | idem, `chkPOS.Value` fortat 1 si ascuns |
|
|
|
|
**Ce depinde de ea**: `opt_incasat.Click` (`:3250-3251`) **si** `opt_incasat.ProgrammaticChange`
|
|
(`:3351-3352`) — vezi sectiunea 4, e disjunctia care conteaza. Nu are alti apelanti directi in
|
|
`ferestre_cere_date.vc2` (cautare `vfp_symbols.ps1 -Grep actualizeaza_tipincasare -CodeOnly`
|
|
recomandata la implementare pentru confirmare exhaustiva pe tot proiectul — nu rulata aici din motive
|
|
de buget, dar apelantul extern deja cunoscut e citat mai jos, la 3.1).
|
|
|
|
### 3.1 Apel extern, cu context important
|
|
|
|
`COMUN\clase\ofacturare.vc2:14919-14926` (`frm_facturare_articole(2).inainte_de_do_termin`, inainte
|
|
de `ofrmdatesupl.Show(1)`):
|
|
```
|
|
ofrmdatesupl = Createobject("frm_alte_date")
|
|
ofrmdatesupl.nnrbon = poDate.nract
|
|
If (poDate.eBonFiscal = 1)
|
|
With ofrmdatesupl
|
|
.opt_incasat.Value = 3 && INCASARE CU BON FISCAL
|
|
.actualizeaza_tipincasare() && apel EXPLICIT, dupa .Value=
|
|
.opt_incasat.option1.TabStop = .F.
|
|
...
|
|
```
|
|
Apelantul seteaza `.Value=3` **si** cheama explicit `actualizeaza_tipincasare()` imediat dupa — ceea
|
|
ce, coroborat cu descoperirea de la sectiunea 4 (`.Value=` deja declanseaza `ProgrammaticChange` ->
|
|
aceeasi metoda), inseamna ca metoda ruleaza de doua ori la acest apel. Nu produce o eroare vizibila
|
|
(fiecare ramura e idempotenta: dezaloca ce era alocat, realoca acelasi tip), dar confirma ca autorul
|
|
codului nu s-a bazat exclusiv pe evenimentul `ProgrammaticChange` — semn ca mecanismul lui exact
|
|
(cand se declanseaza, cand nu) n-a fost niciodata documentat explicit, doar "acoperit din ambele
|
|
parti". **Portarea "ca atare" trebuie sa pastreze acest apel dublu identic**, nu sa-l "curete" ca
|
|
redundant — eliminarea unuia dintre cele doua declansatoare ar putea rupe o presupunere neverificata
|
|
in alta parte a codului.
|
|
|
|
### 3.2 "Se muta ca atare" — ce inseamna concret
|
|
|
|
Corpul metodei (`:2698-2856`) nu are nicio dependenta de fereastra-container (`Thisform.*` peste
|
|
tot, nu `This.Parent.*`) — se poate muta **byte-cu-byte** pe formularul unificat, cu conditia ca
|
|
toate cele noua controale referite (`opt_incasat`, `cb_casa`, `clb_serie_chit`, `clb_nrchit`,
|
|
`clb_incasat`, `_shape3`, `lb_simplu1`, `cmdModificaBon`, `chkPOS`, `chkDetaliat`, `cboTipFactura`)
|
|
sa existe cu **exact aceleasi nume** pe noul formular, in acelasi container logic (`Thisform`, nu un
|
|
subpanou cu alt scope) — altfel referintele nekvalificate `Thisform.xxx` pica silentios pe obiect
|
|
inexistent. Aceasta e o constrangere de implementare directa: **sectiunea pliata trebuie sa fie
|
|
container-transparenta** pentru aceasta metoda (fie pusa direct pe `Thisform`, fie metoda insasi
|
|
adaptata sa foloseasca `This.Parent`-ul corect) — nu poate fi mutata intr-un obiect-container separat
|
|
fara o trecere explicita de `Thisform.xxx -> This.Parent.xxx` pe toate liniile.
|
|
|
|
---
|
|
|
|
## 4. Alocarea si dezalocarea numerelor — evenimentele exacte
|
|
|
|
### 4.1 Evenimente de alocare (azi)
|
|
|
|
1. **`opt_incasat.Click`** (`:3250-3251`) — interactiune reala a utilizatorului pe radiogrup.
|
|
2. **`opt_incasat.ProgrammaticChange`** (`:3351-3352`) — **descoperire centrala a acestui raport**,
|
|
negasita in materialul de plan sau in cele patru rapoarte de referinta: in VFP, orice atribuire
|
|
`.Value = n` facuta din cod (nu de utilizator) declanseaza `ProgrammaticChange`, nu `Click`. Clasa
|
|
are ambele metode cablate pe **acelasi** apel (`actualizeaza_tipincasare()`), deci **orice loc din
|
|
cod care scrie `opt_incasat.Value = ...` aloca/dealoca numere**, indiferent de intentie.
|
|
3. **Chiar `Init`-ul clasei** foloseste acest canal: `:3150`, `Thisform.opt_incasat.Value = 2` — ruleaza
|
|
**doar daca** `poDate.incasat <> 0` la momentul deschiderii. Verificat pe cod (nu presupus) ca
|
|
`poDate.incasat` poate fi nenul **inainte** ca `frm_alte_date` sa se deschida, prin cel putin patru
|
|
cai reale: `ofacturare_stoc.prg:535`, `oproceduri_facturare.prg:1186`,
|
|
`ofacturare_comun.vc2:4066`, `ofacturare_comun.vc2:4260` (toate patru scriu `poDate.incasat =
|
|
incasat`, parametru primit de la apelant — flux de copiere/reluare a unui document cu incasare deja
|
|
stabilita). **Concluzie verificata**: azi, deschiderea dialogului `frm_alte_date` pe un astfel de
|
|
document **aloca deja un numar de chitanta la Init, inainte ca userul sa apese orice**. Nu e o
|
|
ipoteza — e mecanismul descris la sectiunea 3, declansat de linia 3150.
|
|
4. `do_modifica_bon`/`do_modifica_pos` (`:3001-3022`) — dezaloca explicit + realoca, la apasarea
|
|
butonului "Modifica bon"/echivalent POS.
|
|
5. `do_aloca_nr_bon`/`do_aloca_nr_pos` (`:2864-2907`) — chemate din interiorul lui
|
|
`actualizeaza_tipincasare` (ramurile 3 si 4), nu independent.
|
|
|
|
### 4.2 Evenimente de dezalocare (azi)
|
|
|
|
1. **In interiorul `actualizeaza_tipincasare`** — fiecare ramura dezaloca defensiv celelalte trei
|
|
tipuri **inainte** de a (re)aloca pe cel ales (tabelul de la sectiunea 3). Efect: comutarea intre
|
|
optiuni, in cadrul aceleiasi sesiuni de dialog, e curata — nu ramane niciun numar orfan din
|
|
optiunea anterioara.
|
|
2. **`inainte_de_do_renunt`** (`:3023-3043`) — la anulare (buton Renunt / ESC pe dialogul modal):
|
|
```
|
|
inainte_de_do_renunt (ferestre_cere_date.vc2:3025-3030)
|
|
If Type('poGeneratorNumere') = 'O'
|
|
poGeneratorNumere.dezaloca_numar(16) && chitanta
|
|
poGeneratorNumere.dezaloca_numar(3) && bon fiscal
|
|
...
|
|
```
|
|
**Gap real, preexistent, verificat pe cod**: acest bloc dezaloca 16 (chitanta) si 3 (bon fiscal),
|
|
dar **nu 26 (POS)** — nici direct, nici in blocul urmator (`:3033-3035`, care dezaloca doar 16 din
|
|
nou, conditionat). Daca utilizatorul alege POS/Card si apoi anuleaza dialogul, numarul POS alocat
|
|
**ramane alocat**, nedezalocat. Nu e introdus de S3b — exista deja in codul de azi — dar merita
|
|
semnalat explicit ca risc mostenit (sectiunea 9), pentru ca S3b il "muta ca atare" (plan, textul
|
|
povestii), deci il si multiplica pe orice cale noua prin care sectiunea pliata s-ar putea
|
|
"renunta" fara sa fie un dialog modal cu propriul buton Renunt.
|
|
3. **`Init` pe eroare Oracle** (`:3159`) — `poGeneratorNumere.dezaloca_numar(5)` (factura) daca
|
|
interogarea `v_nom_casa` esueaza, cu `Return` imediat dupa (linie explicita, spre deosebire de
|
|
bug-ul #16 din `s3_portare_antet.md` §6, unde nu exista `Return` echivalent). Semnalat, neurmarit
|
|
mai departe aici — acelasi risc de arhitectura ca #16, dar pe alt fisier.
|
|
|
|
### 4.3 Riscul central pentru formularul unificat, si recomandarea
|
|
|
|
**Problema mecanica exacta**: in fluxul de azi, `frm_alte_date` e un dialog modal, instantiat **o
|
|
singura data** per emitere (`ofacturare.vc2:14921`), asa ca `Init`-ul lui (si declansarea eventuala de
|
|
la linia 3150) ruleaza **o singura data**. In formularul unificat, grupul de incasare devine o
|
|
sub-sectiune a unui panou pliabil, pe **acelasi obiect de formular persistent** — daca implementarea
|
|
naiva re-populeaza `opt_incasat.Value` din `poDate` de fiecare data cand sectiunea se depliaza (ex.
|
|
"la fiecare `Show`/`Visible=.T.` al panoului, resincronizeaza controalele cu starea curenta a lui
|
|
`poDate`"), **fiecare depliere ar re-declansa `ProgrammaticChange` -> `actualizeaza_tipincasare()` ->
|
|
dezaloca tot + realoca pe optiunea curenta** — incalcand direct criteriul din S3b ("deschiderea si
|
|
inchiderea formularului fara a atinge zona de incasare nu aloca si nu dezaloca niciun numar").
|
|
|
|
**Recomandare concreta**: populeaza `opt_incasat.Value` din `poDate` **o singura data**, la
|
|
constructia sectiunii de antet a documentului (echivalentul lui `Init` de azi, care ruleaza o data per
|
|
sesiune de emitere/editare) — nu la fiecare toggle de pliere/depliere. Plierea/deplierea trebuie sa
|
|
fie **strict** un toggle de `Visible`/`Height` pe containerul vizual, fara nicio atingere a
|
|
proprietatii `.Value` a lui `opt_incasat` sau a oricarui alt control cu `ProgrammaticChange` cablat pe
|
|
alocare. Aceasta e exact genul de regula care trebuie verificata explicit la implementare (criteriu de
|
|
"gata" concret la sectiunea 10), nu presupusa.
|
|
|
|
---
|
|
|
|
## 5. Grupul de incasare pe document deja emis (decizia 25)
|
|
|
|
**Ce spune decizia**: orice camp schimbat din grupul C (incasare) pe un document deja emis
|
|
"marcheaza documentul pentru regenerare" — dar regenerarea nu exista in etapa I, deci **planul tine
|
|
campurile blocate**, cu explicatie la hover, pana la etapa II (plan `:192-201`, `:1847-1848`).
|
|
`rute_scriere_antet.md` §3 confirma independent ca nu exista nicio cale directa de scriere pentru
|
|
grupul C dupa emitere (verdict "NU" pentru toate controalele, "PARTIAL neconfirmat" doar pentru o
|
|
cale indirecta prin editarea notei — vezi §3.2 acolo, ramane deschisa).
|
|
|
|
### 5.1 Mecanic: pe ce proprietate, pe ce conditie
|
|
|
|
Decizia 9 stabileste ca `but_modifica` deblocheaza **tot** antetul, fara exceptie de camp — dar
|
|
decizia 25 taie o exceptie explicita peste asta pentru grupurile B si C. Nu exista inca (verificat,
|
|
`rute_scriere_antet.md` §2-3) un mecanism de blocare per-grup separat de `but_modifica`; trebuie
|
|
construit nou, dar dupa un tipar deja folosit in codebase pentru exact intrebarea "acest document are
|
|
deja un numar, sau e nou": `chkSerieAct.Enabled = !EMPTY(NVL(poRec.numar_act,0))`
|
|
(`ofacturare_comun.vc2:5736-5750`, citat deja in plan I:839 si S1 randul 60). Decizia 9 **abandoneaza**
|
|
acest test ca poarta pe cele patru bife de identitate (serie/numar/data/scadenta) — dar testul insusi
|
|
ramane exact instrumentul potrivit pentru o alta intrebare: "documentul e nou sau deja emis?", care e
|
|
tocmai conditia ceruta de decizia 25 pentru grupurile B/C.
|
|
|
|
**Recomandare mecanica**: la construirea antetului, se calculeaza o singura data un flag (ex.
|
|
`lDocumentExistent = !EMPTY(NVL(poRec.numar_act,0))` sau echivalentul lui pe obiectul `poDate`/`poRec`
|
|
folosit de formularul unificat — de confirmat la implementare care obiect poarta `numar_act` in noua
|
|
arhitectura, pentru ca `poRec` era specific lui `frm_modifica_factura`, perimetrul #6). Controalele
|
|
grupului C (`opt_incasat` si tot ce atarna de el din tabelul sectiunii 1.2) primesc `Enabled = .F.`
|
|
**neconditionat de starea lui `but_modifica`** cand `lDocumentExistent = .T.`, in etapa I. Cand
|
|
`but_modifica` deblocheaza restul antetului, acest grup **ramane** dezactivat — e o exceptie fixa, nu
|
|
una care se recalculeaza la fiecare click pe `but_modifica`.
|
|
|
|
**Grupul B** (tip document, valuta, zi curs, client, sursa, gestiune sursa, politica de preturi) are
|
|
aceeasi tratare — dar acele controale traiesc azi in `frm_date_factura`/`frm_date_aviz`
|
|
(sectiunea I a planului, nu sectiunea B de aici), deci blocarea lor nu e in perimetrul S3b propriu-zis;
|
|
se semnaleaza aici doar pentru consecventa mecanismului (acelasi flag, acelasi tipar de `Enabled=.F.`
|
|
peste orice stare a lui `but_modifica`).
|
|
|
|
### 5.2 La emitere, se comporta ca azi
|
|
|
|
Pentru un document **nou** (nu inca emis), `lDocumentExistent = .F.`, grupul C e activ normal — se
|
|
comporta identic cu `frm_alte_date` de azi, cu masina de stari intreaga din sectiunile 3-4. Nimic nu
|
|
se schimba pe calea de emitere initiala; blocarea se aplica **doar** cand formularul unificat deschide
|
|
un document deja scris in `VANZARI` (calea de editare, nu de creare).
|
|
|
|
### 5.3 Tooltip / explicatie la hover
|
|
|
|
Ca la sectiunea 2.2, textul exact nu exista inca — de propus la implementare, in tonul deja folosit in
|
|
codebase. Continut minim necesar: sa spuna ca modificarea incasarii pe un document emis nu e inca
|
|
posibila din acest formular ("disponibil dupa ce regenerarea documentului e implementata" sau
|
|
echivalent), nu doar "camp dezactivat" fara explicatie — plan `:198-200` cere explicit "cu explicatie
|
|
la hover".
|
|
|
|
---
|
|
|
|
## 6. Mecanismul de pliere — nu exista, se construieste nou dupa un tipar existent
|
|
|
|
**Cautare directa in prototip**: `vfp_symbols.ps1 -Grep` (si grep text simplu) pe "plia|colaps|
|
|
collapse|expand|acordeon|accordion" in `COMUN\clase\ofacturare.vc2` (unde traieste
|
|
`frm_facturare_articole2`, `:15741-19355`) — **zero potriviri**. Prototipul are controalele de antet
|
|
montate direct pe formular (confirmat deja de `s3_portare_antet.md` §3 si de
|
|
`inventar_controale_formulare.md` §2), dar **niciun mecanism de show/hide de sectiune** — nu exista
|
|
nici macar un buton candidat.
|
|
|
|
**Cel mai apropiat tipar real din suita**: `frm_modific2024.afiseaza_rulaje`
|
|
(`COMUN\clase\omodificari.vc2:13169-13199`, perimetrul #6, doar citit aici). Cod complet:
|
|
```
|
|
PROCEDURE afiseaza_rulaje
|
|
* COLAPSEAZA SAU MARESTE PAGEFRAME-UL RULAJE
|
|
lcPicture = this.but_afiseaza_rulaje.Picture
|
|
...
|
|
llAfiseazaRulaje = 'sus'$m.lcPicture
|
|
IF m.llAfiseazaRulaje
|
|
lcPicture2 = STRTRAN(m.lcPicture,'sus','jos') ...
|
|
ELSE
|
|
lcPicture2 = STRTRAN(m.lcPicture,'jos','sus') ...
|
|
ENDIF
|
|
this.but_afiseaza_rulaje.Picture = m.lcPicture2
|
|
...
|
|
this.pgfArticole.Visible = m.llAfiseazaRulaje
|
|
this.but_copiazaR.Visible = m.llAfiseazaRulaje
|
|
this.but_modificaR.Visible = m.llAfiseazaRulaje
|
|
this.but_stergeR.Visible = m.llAfiseazaRulaje
|
|
thisform.resize_grid1()
|
|
ENDPROC
|
|
```
|
|
Trei observatii directe:
|
|
1. **Foloseste exact acelasi idiom sus/jos** deja validat si documentat pentru `but_modifica`/
|
|
`but_salveaza` (decizia 9, `docs\cercetare\buton_comutator_picture.md`, citat in plan `:63-75`):
|
|
citeste starea curenta din numele fisierului `Picture` (contine "sus" sau "jos"), calculeaza
|
|
perechea opusa prin `STRTRAN`, rescrie **`Picture` + `cPictureDown` + `cPictureUp` impreuna** —
|
|
aceeasi precautie semnalata in plan ("numai `.Picture` nu ajunge: hover-ul standard din
|
|
`buton.MouseEnter`/`MouseLeave` rescrie `Picture` din `cPictureUp`/`cPictureDown`").
|
|
2. **Nu e o clasa reutilizabila, e cod ad-hoc per caz** — toggle direct pe `.Visible` al unei liste
|
|
fixe de controale, plus un apel manual de reflow (`resize_grid1()`, metoda proprie a formularului,
|
|
nu un mecanism generic). Nu exista in nicio biblioteca de clase din `COMUN` (`_baza.vcx`, etc.,
|
|
cautare separata, zero potriviri pentru o clasa "panou pliabil"/"expander"/"accordion") un
|
|
container gata facut de pliere. **S3b trebuie sa scrie cod nou**, dupa acest tipar, nu sa
|
|
instantieze o clasa existenta.
|
|
3. **E in perimetrul #6, doar citire** — poate fi copiat ca *idee*/tipar la implementare, dar
|
|
`omodificari.vc2` insusi nu se atinge cat timp #6 e in lucru (decizia 30).
|
|
|
|
### 6.1 Ce trebuie sa scrie S3b, concret
|
|
|
|
- **Un buton comutator per sectiune pliata** (sau unul singur pentru toata zona "alte date +
|
|
analitice", de decis la implementare — plan I nu specifica granularitatea), cu imaginile
|
|
sus/jos deja existente in `COMUN\grafice` (aceleasi perechi folosite pentru `but_afiseaza_rulaje`,
|
|
de identificat exact numele fisierelor la implementare — nu verificate aici, doar tiparul de
|
|
mecanism).
|
|
- **Toggle de `.Visible`/`.Height`** pe grupul de controale al sectiunii (delegat/transport, incasare,
|
|
adresa, text aditional, analitice), plus un apel de reflow echivalent lui `resize_grid1()` — pentru
|
|
ca restul formularului (butoane, alte sectiuni de mai jos) sa nu ramana cu goluri sau suprapuneri
|
|
cand sectiunea se pliaza/depliaza. VFP nu reflow-eaza automat un layout absolut-pozitionat (`Left`/
|
|
`Top` fixe pe fiecare control) — de asta si tiparul din `frm_date_factura.Init` (citat in
|
|
`s3_portare_antet.md` §5, "masoara inaltimile containerelor de antet intr-un array `laPozitii`") cat
|
|
si `afiseaza_rulaje` fac manual acest calcul; nu exista un layout manager automat de reutilizat.
|
|
- **Populare o singura data** a starii initiale (sectiunea 4.3) — separat de toggle-ul de vizibilitate,
|
|
ca sa nu retrigger-eze `ProgrammaticChange`.
|
|
- **Intrebare deschisa, semnalata deja in `s3_portare_antet.md` §5** (nu redusa aici): daca lookup-urile
|
|
Oracle ale lui `frm_alte_date.Init` (delegat/masina ultima factura, cursorul `v_nom_casa`) raman
|
|
**eager** (rulate la construirea formularului, ca azi) sau devin **lazy** (amanate pana la prima
|
|
depliere a sectiunii, ca sa nu incarce round-trip-uri Oracle inutile cand userul nu ajunge niciodata
|
|
acolo). Ambele optiuni sunt compatibile cu criteriul "deschiderea/inchiderea nu aloca numere" **doar
|
|
daca** populate keeping in mind sectiunea 4.3 (populare o singura data, indiferent de varianta
|
|
aleasa) — **de decis de Marius**, vezi sectiunea 9.
|
|
|
|
---
|
|
|
|
## 7. Ordinea de executie
|
|
|
|
Pasi care lasa suita functionala dupa fiecare — calea veche (`frm_alte_date` ca dialog separat) **nu
|
|
se sterge** in etapa I, cf. textul povestii ("`frm_alte_date` nu se sterge cat timp calea veche mai e
|
|
in uz").
|
|
|
|
1. **Construieste sectiunea vizuala pliata** (patru grupuri din sectiunea 1 + analiticele din
|
|
sectiunea 2), fara nicio logica de alocare/validare inca — doar controale + toggle de
|
|
Visible/Height (sectiunea 6). *Criteriu:* fiecare control existent in `frm_alte_date`/antetul de
|
|
analitice apare o data, cu aceeasi eticheta, in sectiunea corecta a formularului unificat —
|
|
verificare camp-cu-camp fata de tabelele din sectiunile 1-2 de aici.
|
|
2. **Porteaza `actualizeaza_tipincasare` ca atare** (sectiunea 3), cu toate cele noua referinte
|
|
`Thisform.xxx` rezolvate corect in noul container (sectiunea 3.2). *Criteriu:* alegerea fiecarei
|
|
optiuni din `opt_incasat` produce exact aceleasi `Visible`/etichete pe controalele dependente ca pe
|
|
`frm_alte_date` de azi, verificabil headless (sectiunea 8).
|
|
3. **Rezolva explicit riscul de la sectiunea 4.3** — populare unica a starii, toggle de pliere fara
|
|
atingere de `.Value`. *Criteriu, verificabil headless:* pe un document de test cu `poDate.incasat<>0`
|
|
la construirea formularului, se depliaza si se plie
|
|
aza sectiunea de trei ori consecutiv fara a atinge
|
|
niciun control din grup — `poGeneratorNumere` (cursorul lui de numere alocate) arata **acelasi**
|
|
numar de chitanta la finalul celor trei toggle-uri ca la inceput, nu unul nou de fiecare data.
|
|
4. **Porteaza delegat/transport si adresa de facturare** (`do_cauta_delegat`/`do_cauta_masina`/
|
|
`do_cauta_agent`/`do_cauta_adresa`/`do_modifica`), cu validarea din `inainte_de_do_termin`
|
|
(sectiunea 1.1). *Criteriu:* fiecare cautare deschide acelasi dialog si scrie aceleasi proprietati
|
|
pe `poDate` ca azi (comparatie directa, cod identic mutat).
|
|
5. **Adauga analiticele read-only** (sectiunea 2), inclusiv completarea `do_dezactiveaza()` cu
|
|
`ReadOnly=.T.` explicit. *Criteriu:* tastarea directa in oricare din cele patru campuri nu modifica
|
|
valoarea afisata (verificare pe proprietate, headless).
|
|
6. **Implementeaza blocarea grupului C pe document deja emis** (decizia 25, sectiunea 5), cu flag-ul
|
|
de "document existent" si exceptia peste `but_modifica`. *Criteriu:* pe un document nou,
|
|
`but_modifica` (cand exista, dupa S3/decizia 9) nu afecteaza grupul C (mereu activ); pe un document
|
|
deja emis, grupul C ramane `Enabled=.F.` inainte **si** dupa apasarea lui `but_modifica`.
|
|
7. **Verificare de regresie end-to-end**: emite acelasi document (numerar, chitanta, bon fiscal, POS —
|
|
toate patru, nu doar unul) o data pe calea veche (`frm_alte_date` dialog) si o data pe formularul
|
|
unificat, compara `poDate`-ul rezultat inainte de scriere in Oracle (aceleasi campuri de incasare,
|
|
acelasi numar alocat) — tipar deja folosit in `s3_portare_antet.md` §7 pentru S3, reutilizat aici
|
|
pe grupul mai mic al lui S3b.
|
|
|
|
*Depinde de S3* (planul o spune explicit) — pasii 4 si 6 presupun ca `but_modifica`/blocarea antetului
|
|
(proiectata in S3, sectiunea I a planului) exista deja ca mecanism, nu doar ca design pe hartie.
|
|
|
|
---
|
|
|
|
## 8. Ce nu se poate testa headless
|
|
|
|
Precedent direct: `s3_portare_antet.md` §8, si memoria de proiect
|
|
(`grid-coloane-nu-se-materializeaza-headless` — coloanele de grid nu se materializeaza sub `-A -T`,
|
|
exista harness UI vizibil separat care le citeste corect).
|
|
|
|
**Se POATE testa headless** (contrar primei intuitii, pentru ca e logica pe proprietati, nu pictura pe
|
|
ecran):
|
|
- Toata masina de stari `actualizeaza_tipincasare` — `Createobject()` fara `.Show()` tot ruleaza
|
|
`Init` si tot cabl eaza evenimentele; `thisform.opt_incasat.Value = n` declanseaza
|
|
`ProgrammaticChange` identic cu UI vizibil sau nu. Verificarile de alocare/dezalocare de la pasul 3
|
|
al sectiunii 7 sunt testabile 100% headless, pe proprietatile lui `poGeneratorNumere`.
|
|
- Vizibilitatea controalelor dupa toggle (`.Visible`, `.Height`, existenta obiectului via `Type(...)`)
|
|
— acelasi motiv, confirmat deja de `s3_portare_antet.md` §8 pentru mecanismul similar din `Init`-urile
|
|
de antet.
|
|
|
|
**NU se poate testa headless**:
|
|
- **Aspectul vizual real dupa pliere/depliere** (suprapuneri, goluri, pozitionarea corecta a
|
|
controalelor de sub sectiune dupa reflow-ul manual, sectiunea 6.1) — layout absolut-pozitionat, fara
|
|
reflow automat; verificarea ceruta e "arata bine pe ecran", nu o proprietate booleana — necesita
|
|
harness UI vizibil (memoria de proiect citata mai sus) sau verificare manuala de Marius.
|
|
- **Cele patru dialoguri modale** (`do_cauta_delegat`/`do_cauta_masina`/`do_cauta_agent`/
|
|
`do_cauta_adresa`) — interactiunea reala de alegere dintr-o lista nu se simuleaza headless; se poate
|
|
testa doar efectul **dupa** ce rezultatul cautarii e construit manual (tiparul deja folosit in
|
|
proiect, citat in `s3_portare_antet.md` §8, pct. 1).
|
|
- **Lookup-urile Oracle din `Init` (delegat/masina ultima factura, `v_nom_casa`)** — necesita conexiune
|
|
Oracle reala (harnessul suporta asta prin `MARIUSM_AUTO`, dar tot nu e "headless" in sensul de
|
|
"fara dependinte externe") si date de test care sa existe pentru clientul folosit.
|
|
- **Butonul `cmdModificaBon`/`do_modifica_bon`** — deschide `viz_config_serii_complet WITH 3`
|
|
(`oserii_numere.prg`), alt formular modal, aceeasi limitare ca dialogurile de cautare.
|
|
|
|
---
|
|
|
|
## 9. Riscuri si capcane
|
|
|
|
1. **Riscul central** (sectiunea 4.3): re-populare a starii `opt_incasat` la fiecare toggle de pliere
|
|
ar re-declansa alocare/dezalocare, incalcand direct criteriul cerut de decizia 25/S3b. Tratat
|
|
explicit ca pas 3 in ordinea de executie — **nu** de lasat "se rezolva de la sine prin arhitectura",
|
|
pentru ca mecanismul de declansare (`ProgrammaticChange`) e usor de lovit accidental de orice cod
|
|
ulterior care "resincronizeaza UI-ul cu modelul" intr-un loc gresit.
|
|
2. **Gap preexistent, nu introdus de S3b, dar mostenit prin "muta ca atare"**: `inainte_de_do_renunt`
|
|
(`:3025-3030`) nu dezaloca numarul POS (26) la anulare — doar chitanta (16) si bon fiscal (3). Daca
|
|
formularul unificat introduce vreo cale noua de "renunta la document" care nu mapeaza exact pe acest
|
|
cod, riscul se poate agrava (numar POS ramas alocat orfan, de fiecare data cand utilizatorul incepe
|
|
un document cu POS si renunta). Recomandare: fie se corecteaza in trecere (nu e in perimetrul strict
|
|
al portarii "ca atare", dar e o linie), fie se semnaleaza explicit ca bug cunoscut de preluat separat.
|
|
3. **`_checkbox1`/"Listare detaliata" vs. `chkDetaliat`** (sectiunea 1.4) — doua controale cu semantica
|
|
probabil identica, ambiguitate deja semnalata in S1 (randul 57), neinchisa aici. Formularul unificat
|
|
trebuie sa aleaga unul singur; alegerea gresita (portarea amandurora ca doua campuri distincte)
|
|
ar introduce un camp duplicat fara sens pentru utilizator.
|
|
4. **`do_dezactiveaza()` insuficient pentru read-only real** (sectiunea 2.1) — daca implementarea
|
|
apeleaza doar metoda existenta fara completarea de `ReadOnly`, decizia 26 nu e respectata mecanic:
|
|
campul arata blocat (fara lupa) dar tot accepta taste.
|
|
5. **Referinte `Thisform.xxx` nekvalificate** in `actualizeaza_tipincasare` (sectiunea 3.2) — orice
|
|
decizie de a pune sectiunea pliata intr-un container/obiect separat (nu direct pe `Thisform`) rupe
|
|
tacit aceste referinte, cu eroare de "obiect inexistent" la runtime, nu la compilare.
|
|
6. **Dependinta pe S3**: `but_modifica` si testul "document existent" (sectiunea 5.1) nu exista inca
|
|
nicaieri in cod — proiectate doar pe hartie in plan (sectiunea I). Pasii 4 si 6 din sectiunea 7 nu
|
|
pot fi *implementati* complet inainte ca S3 sa livreze acel mecanism, doar proiectati.
|
|
7. **Bug-ul de `sectie`** (`omodificari.vc2:13941`, semnalat deja in `rute_scriere_antet.md` §1.3 si
|
|
in plan `:761-764`) — nu afecteaza direct S3b (analiticele sunt read-only aici, deci S3b nu scrie
|
|
niciodata `id_sectie`), dar afecteaza increderea in ce se **afiseaza**: daca bug-ul e real, coloana
|
|
`id_sectie` din Oracle poate sa nu reflecte eticheta aratata dupa o editare din #6. In afara
|
|
perimetrului S3b de reparat (e in #6), dar relevant pentru cine citeste afisarea din #13 dupa o
|
|
editare de la #6.
|
|
|
|
---
|
|
|
|
## 10. Criteriul de "gata", rescris verificabil
|
|
|
|
Textul din plan (`:1849-1852`) spune: *"un document cu incasare prin bon fiscal emis din formularul
|
|
unificat produce aceleasi randuri si acelasi numar de bon ca pe calea veche; deschiderea si inchiderea
|
|
formularului fara a atinge zona de incasare nu aloca si nu dezaloca niciun numar; iar pe un document
|
|
emis analiticele se vad dar nu se pot edita."* Precizat mai jos, pe fiecare bucata:
|
|
|
|
1. **Paritate de emitere, pe toate patru tipurile de incasare, nu doar bon fiscal**: se emite acelasi
|
|
document de test (client, articole, cantitati, preturi identice) o data pe calea veche
|
|
(`frm_date_factura`/`frm_date_aviz` -> `frm_facturare_articole(2)` -> `frm_alte_date`) si o data pe
|
|
formularul unificat, pentru fiecare din **Fara incasare / Chitanta / Bon fiscal / POS-Card**. Se
|
|
compara `lcListaIncasare` (stringul asamblat inainte de `scrie_factura2`, sectiunea 3.1 al
|
|
`rute_scriere_antet.md`) si numarul alocat (`poDate.nr_incasare`) — trebuie sa fie identice pe
|
|
fiecare din cele patru cazuri, nu doar pe bon fiscal.
|
|
2. **Non-alocare la toggle de pliere, testabila headless** (sectiunea 7, pasul 3, deja formulat ca
|
|
assert concret pe `poGeneratorNumere`) — pe **doua** scenarii de start, nu unul: document nou
|
|
(`poDate.incasat=0` la construire) **si** document venit din copiere cu incasare presetata
|
|
(`poDate.incasat<>0`, sectiunea 4.1 punctul 3) — al doilea caz e cel care azi *deja* aloca la
|
|
deschidere, exact scenariul pe care criteriul trebuie sa-l acopere explicit.
|
|
3. **Blocarea grupului C, pe ambele stari ale antetului**: pe un document deja emis, campurile din
|
|
grupul de incasare raman `Enabled=.F.` atat inainte cat si dupa apasarea lui `but_modifica` — nu
|
|
doar "la deschidere" (ce ar lasa loc unei regresii daca `but_modifica` le-ar debloca din greseala
|
|
odata cu restul).
|
|
4. **Analiticele, pe ambele stari**: pe un document emis, cele patru campuri (venit/cheltuiala, sectie,
|
|
responsabil, lucrare) afiseaza valoarea curenta din sursa lor (sectiunea 2.3 — de precizat exact
|
|
care sursa la implementare) si resping orice tentativa de tastare directa sau de deschidere a
|
|
dialogului de cautare — verificat pe proprietatea `ReadOnly`/`lactiv`, nu doar vizual.
|
|
5. **Delegat/transport/adresa/text aditional** — paritate camp-cu-camp cu `frm_alte_date` de azi, pe
|
|
cel putin un document proforma (grup delegat/incasare eliminat, sectiunea 1.4) si unul non-proforma
|
|
(grup complet), ca sa acopere ambele ramuri ale `Init`-ului de azi (`:3109-3207`).
|
|
|
|
*Depinde de:* S3 (but_modifica, mecanismul de blocare a antetului). *Nu depinde de:* etapa II
|
|
(regenerarea) — grupurile B/C raman blocate prin design in etapa I, nu prin absenta temporara a unei
|
|
functionalitati care ar trebui testata aici.
|
|
|
|
---
|
|
|
|
## Ce ramane de decis de Marius
|
|
|
|
1. **Textul exact al tooltip-urilor** pentru analiticele read-only (sectiunea 2.2) si pentru grupul de
|
|
incasare blocat pe document emis (sectiunea 5.3) — doar continutul minim necesar e propus aici, nu
|
|
formularea finala.
|
|
2. **Granularitatea butonului/butoanelor de pliere**: un singur comutator pentru toata zona "alte date
|
|
+ analitice", sau unul separat per subgrup (delegat/transport, incasare, adresa, text, analitice)?
|
|
Plan sectiunea I nu specifica, iar tiparul gasit (`afiseaza_rulaje`) e per-sectiune unica, nu
|
|
per-formular-intreg — precedentul nu decide singur granularitatea (sectiunea 6.1).
|
|
3. **Eager vs. lazy pentru lookup-urile Oracle din `Init`** (delegat/masina ultima factura, casa) —
|
|
semnalat si in `s3_portare_antet.md` §5 ca discutie deschisa, reconfirmat aici pentru acelasi cod
|
|
(sectiunea 6.1, ultimul punct).
|
|
4. **Corectarea gap-ului de dezalocare POS la anulare** (sectiunea 9, punctul 2) — se repara in trecere
|
|
ca parte a S3b, sau se lasa exact ca azi si se semnaleaza separat ca bug de preluat ulterior?
|
|
5. **`_checkbox1` vs. `chkDetaliat`** (sectiunea 1.4, sectiunea 9 punctul 3) — care dintre cele doua
|
|
controale de "listare detaliata" devine campul unic in formularul unificat; ambiguitatea ramane
|
|
deschisa din S1 si nu s-a inchis aici.
|
|
|
|
## Handoff
|
|
|
|
Cercetare incheiata, nu intrerupta la mijloc — toate cele zece sectiuni cerute in briefing sunt
|
|
complete, cu citate `fisier:linie` verificate direct pe fisierele reale (nu `.bak`). Niciun cod
|
|
atins, nicio interogare Oracle rulata (nu a fost nevoie — tot ce trebuia era in codul VFP deja citit
|
|
sau in cele patru rapoarte de referinta). Fisierul e complet la aceasta versiune; nu e nevoie de o
|
|
sesiune de continuare pentru S3b ca atare. Urmatorul pas natural (nu al acestei sarcini) ar fi S3
|
|
insusi (blocarea antetului, `but_modifica`) — S3b depinde de el pentru pasii 4 si 6 din sectiunea 7,
|
|
dar proiectarea de aici nu asteapta acel livrabil, doar implementarea o va astepta.
|