sync SVN r18077
This commit is contained in:
482
docs/cercetare/s4_cautare_articole_server.md
Normal file
482
docs/cercetare/s4_cautare_articole_server.md
Normal file
@@ -0,0 +1,482 @@
|
||||
# Cercetare — proiectare S4: cautarea articolelor pe server, in linie
|
||||
|
||||
Investigatie READ-ONLY pentru povestea **S4** din `docs\plan_13_unificare_formular_facturare.md:1865-1874`,
|
||||
plus sectiunea `### C. Incarcarea articolelor — de ce dureaza si ce inlocuieste` (`:589-614`).
|
||||
Fara editari de cod, fara `git_sync.ps1`/`txt2vcx.ps1`, fara commit. `COMUN\clase\ofacturare_comun.vc2`
|
||||
si `COMUN\programe\ofacturare_editare.prg` (perimetrul #6) doar citite, nu atinse. Pe Oracle doar
|
||||
`SELECT`, prin exportul `PACK_FACTURARE` de pe disc — nu s-a rulat nimic pe server.
|
||||
|
||||
## Verdict (rezumat)
|
||||
|
||||
Mecanismul de inlocuire propus in plan **exista deja, dar e un prototip la jumatate**:
|
||||
`grd_factura.cCodMat.cboCodmat` / `cCboDenumire` (`ofacturare.vc2:16751-16797`, wiring la
|
||||
`:19288-19334`) cauta pe server prin `combosql` si scriu `codmat`/`denumire`/`id_articol` in
|
||||
`crsfactura` — dar **nu scriu nimic altceva**, pentru ca sursa lor (`vnom_articole`) nu are pret,
|
||||
TVA, valuta, `id_pol`, `gestionabil`. Asta confirma exact ce zice planul la punctul C: partea Oracle
|
||||
de facut e o **varianta filtrata pe articol a celor cinci cursoare de facturare**, nu o cautare noua.
|
||||
|
||||
Descoperirea care schimba proiectarea fata de textul din plan: **`crsarticole` nu e doar sursa de
|
||||
populare a gridului — e un registru al cantitatii ramase de facturat**, citit si scris de
|
||||
`do_adauga_tot`, `do_sterge` si `do_scrie_factura` pentru toate tipurile cu document sursa (comanda,
|
||||
aviz, contract-lista-de-preturi). Stergerea unei linii **reface** cantitatea in `crsarticole`
|
||||
(`:14640-14669`), iar la scriere se face `Calculate Sum(cantitate) To lnCantitateRamasa` peste
|
||||
`crsarticole` ca sa se decida daca se inchide automat comanda/avizul (`:14303-14311`, `:14334-14338`).
|
||||
Asta inseamna ca **incarcarea in masa nu poate disparea pentru aceste tipuri**, indiferent de S4 —
|
||||
nu doar pentru ca planul a decis sa pastreze "adauga tot", ci pentru ca bookkeeping-ul de cantitate
|
||||
ramasa e cablat direct pe cursorul incarcat. S4 se aplica deci curat doar pe ramurile de **lista de
|
||||
preturi** (`cursor_preturi`, plus jumatate din `cursor_contract` si `cursor_gestiune`) — vezi punctul 7.
|
||||
|
||||
A doua descoperire: calea de scriere a pretului la nivel de linie (`adauga_articol_factura`,
|
||||
verificata separat in S10, `docs\cercetare\s10_pret_rederivat.md`) **primeste deja pretul ca
|
||||
parametru** in loc sa-l re-deriveze — exact precedentul pe care trebuie sa-l urmeze si varianta
|
||||
filtrata: cauta pretul o singura data, la alegerea liniei, si il transmite mai departe neschimbat.
|
||||
|
||||
## 1. Inventarul celor cinci cursoare Oracle
|
||||
|
||||
Sursa: `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql` (corpul
|
||||
pachetului; liniile de mai jos sunt pe corp, `:2138+`, nu pe spec `:335+` — offset **+17** fata de
|
||||
citatele vechi din plan, confirmat si in S10).
|
||||
|
||||
### 1.1 `cursor_preturi` — lista de preturi, ramura principala (`:2138-2644`)
|
||||
|
||||
```
|
||||
PROCEDURE cursor_preturi(V_DATA_CURS IN DATE, V_TIP IN NUMBER, V_ID_VALUTA IN NUMBER,
|
||||
V_ID_GESTIUNE_INIT IN NUMBER, V_LUNA IN NUMBER, V_AN IN NUMBER,
|
||||
V_ID_UTIL IN NUMBER, V_ID_SUCURSALA IN NUMBER,
|
||||
V_CURSOR OUT cursor_facturare)
|
||||
```
|
||||
|
||||
**Fara filtru pe articol** — semnatura n-are niciun parametru de cod/denumire. Ramuri pe `V_TIP`
|
||||
(`CASE`, `:2159-2643`):
|
||||
|
||||
| Ramura | Cand | Sursa randurilor | Observatie |
|
||||
|---|---|---|---|
|
||||
| `V_TIP = 45` | restaurant | `utilizatori_rol_intern` -> `politici_grupuri` -> `crm_politici_preturi` -> `crm_politici_pret_art` -> `nom_articole`, plus `curs`/`nom_valute` | fara filtru de stoc, `cantitate` fixa la 1 (`:2193`) |
|
||||
| `V_TIP IN (1,2)` | factura in lei | acelasi lant de politici, plus `LEFT JOIN` pe `STOC` agregat pe gestiunile utilizatorului | `WHERE` final filtreaza pe stoc > 0 sau `RF_FACTURARE_FARA_STOC` (`:2387-2388`) |
|
||||
| `V_TIP IN (5,6,10,52)` | factura in valuta | `FACT_VPRETURI_UTILIZATOR` (view precalculat, nu politici brute) + `STOC` + `CURS` | `WHERE A.ID_UTIL = V_ID_UTIL AND ((A.ID_VALUTA = V_ID_VALUTA AND A.IN_VALUTA=1) OR A.ID_POL = politica_stoc)` (`:2461-2462`) |
|
||||
| `V_TIP = 7` | credit note | `FACT_VPRETURI_UTILIZATOR`, filtrat suplimentar `NVL(A.nota_discount,0)=1` (`:2538`) | doar articole de discount |
|
||||
| `ELSE` (aviz, tip implicit) | orice alt tip | `FACT_VPRETURI_UTILIZATOR`, fara filtrul de valuta din ramura 5/6/10/52 | ramura cea mai generala |
|
||||
|
||||
Coloane comune returnate (uniforme pe toate ramurile, ceea ce conteaza pentru mapare — punctul 6):
|
||||
`id_c, id_articol, lot, serie, id_pol, id_valuta, nume_lista_preturi, discount_unitar,
|
||||
discount_unitar_val, codmat, codbare, denumire, um, gestionabil, cantitate, proc_tvav,
|
||||
preturi_cu_tva, curs, multiplicator, pret, pret_val, tip_valuta, nume_val` (+ `modificabil`,
|
||||
`id_gestiune`, `cont` doar pe ramura restaurant).
|
||||
|
||||
Apeleaza intai `initializeaza_facturare`, `completare_politica_stoc` si
|
||||
**`verifica_cursuri_valute(V_DATA_CURS, V_ID_UTIL)`** (`:2149-2153`) — validare **neconditionata**
|
||||
a cursurilor pentru toate valutele din listele de preturi ale utilizatorului, indiferent de articolul
|
||||
cautat. Relevant pentru S4d (`-20005`).
|
||||
|
||||
### 1.2 `cursor_contract` — factura/aviz pe contract (`:2646-2950`)
|
||||
|
||||
```
|
||||
PROCEDURE cursor_contract(V_DATA_CURS, V_TIP, V_ID_VALUTA, V_LISTAID, V_ID_GESTIUNE_INIT,
|
||||
V_LUNA, V_AN, V_ID_UTIL, V_ID_SUCURSALA,
|
||||
V_ID_AGENT OUT, V_NUME_AGENT OUT,
|
||||
V_CURSOR OUT cursor_facturare, V_CURSOR2 OUT cursor_facturare)
|
||||
```
|
||||
|
||||
**Doua cursoare de iesire.** `V_CURSOR2` (`:2718-2938`) e specific contractului: `UNION ALL` intre
|
||||
(a) articole cu `OPT_FACTURARE = 3` din `CTR_ARTICOLE` si (b) rate din `CTR_SCADENTAR` pentru
|
||||
`OPT_FACTURARE IN (1,2)`, cu `id_articol = NULL` pe randurile de rata — filtrate pe
|
||||
`V_LISTAID` (lista de `id_ctr`) prin `charn2collection`. La final (`:2940-2948`) **cheama
|
||||
`cursor_preturi` cu aceiasi parametri** si scrie rezultatul in `V_CURSOR` — deci jumatate din
|
||||
`cursor_contract` e literalmente `cursor_preturi`.
|
||||
|
||||
In VFP, cele doua cursoare de iesire ajung (observat pe cod, nu documentat explicit in `goExecutor`)
|
||||
in `crsarticole` (=`V_CURSOR`, lista de preturi) si `crsarticole1` (=`V_CURSOR2`, liniile contract +
|
||||
rate) — vezi `ofacturare.vc2:13778` (`lcCursorStoc = Iif(poArticol.opt_facturare = 0, [crsarticole],
|
||||
[crsarticole1])`) si `Destroy` (`:12804-12811`) care inchide ambele.
|
||||
|
||||
**Randurile de rata nu au `id_articol`** — nu pot fi gasite printr-o cautare cod/denumire; raman
|
||||
legate de gridul `crsarticole1` existent (`grd_contracte`), bounded de numarul de rate ale
|
||||
contractului, nu de catalog. Vezi punctul 7.
|
||||
|
||||
Valideaza cursurile valutare **doar** pentru valutele prezente in `CTR_SCADENTAR`/`CTR_ARTICOLE` ale
|
||||
contractelor din `V_LISTAID` (`:2679-2716`) — spre deosebire de `cursor_preturi`, care valideaza tot
|
||||
ce are utilizatorul in politici. Filtru deja ingust pe sursa, dar tot pe tot contractul, nu pe
|
||||
articol.
|
||||
|
||||
### 1.3 `cursor_comanda` — factura/aviz pe comanda (`:2952-3171`)
|
||||
|
||||
```
|
||||
PROCEDURE cursor_comanda(V_DATA_CURS, V_TIP, V_LISTAID, V_ID_UTIL, V_CURSOR OUT cursor_facturare)
|
||||
```
|
||||
|
||||
`V_LISTAID` e **un singur `id_comanda`** (`TO_NUMBER(V_LISTAID)`, `:2963` — nu o lista, desi
|
||||
parametrul se numeste la fel ca la contract/avize). Doua ramuri identice ca forma (`V_TIP <= 20` =
|
||||
factura, altfel aviz, `:2994-3170`), ambele pe `COMENZI_ELEMENTE` filtrat `WHERE A.ID_COMANDA =
|
||||
V_ID_COMANDA` (`:3078`, `:3166`) — **deja filtrat pe un singur document sursa**, nu pe tot catalogul.
|
||||
`LEFT JOIN` cu suma cantitatilor deja facturate din `VANZARI_DETALII` pe acelasi `ID_COMANDA`
|
||||
(`:3060-3068`) calculeaza `cantitate` ca **ramas de facturat**, nu cantitatea comandata bruta —
|
||||
exact sursa pentru bookkeeping-ul de "adauga tot" / stergere de la punctul urmator.
|
||||
|
||||
### 1.4 `cursor_avize` — factura din avize (`:3703-3874`)
|
||||
|
||||
```
|
||||
PROCEDURE cursor_avize(V_LISTAID, V_ID_UTIL, V_DISCOUNT OUT NUMBER, V_CURSOR OUT cursor_facturare)
|
||||
```
|
||||
|
||||
`V_LISTAID` = lista de `id_vanzare` (avize sursa), separate prin virgula. O singura interogare,
|
||||
fara `CASE` pe tip — agrega `VANZARI_DETALII` pe cheie compusa (articol, pol, lot, serie, discount,
|
||||
TVA, gestiune, cont, pret...) si scade ce a fost deja facturat din `VANZARI_CANTITATI`
|
||||
(`WHERE A.CANTITATE <> NVL(B.CANTITATE, 0)`, `:3871`) — acelasi tipar "ramas de facturat" ca la
|
||||
comanda. **Nu are ramuri pe `V_TIP`** — planul o citeaza ca exemplu de "aceleasi ramuri pe tip", dar
|
||||
real e cea mai simpla dintre cele cinci: un singur `SELECT`.
|
||||
|
||||
### 1.5 `cursor_gestiune` — transfer intre subunitati pe lista de preturi (`:4158-4310+`)
|
||||
|
||||
```
|
||||
PROCEDURE cursor_gestiune(V_DATA_CURS, V_ID_POL, V_ID_GESTIUNE, V_LUNA, V_AN,
|
||||
V_ID_UTIL, V_ID_SUCURSALA, V_CURSOR OUT cursor_facturare)
|
||||
```
|
||||
|
||||
Foloseste `V_ID_POL` **fix** (nu politica derivata din utilizator ca la `cursor_preturi`), pe
|
||||
`STOC` filtrat `ID_GESTIUNE = V_ID_GESTIUNE` `JOIN` `CRM_POLITICI_PRET_ART WHERE ID_POL = V_ID_POL`
|
||||
(`:4266-4280`) — deja restrans la o singura gestiune si o singura politica, dar tot fara filtru pe
|
||||
articol; `GROUP BY` pe articol agrega stocul.
|
||||
|
||||
## 2. De unde sunt executate; cine consuma `crsarticole`
|
||||
|
||||
**Executia:** un singur loc, `ofacturare.prg:266-311` (`factureaza`), rutare pe `tnTip` (punct de
|
||||
plecare confirmat, `Do Case` la `:266-308`) -> `goExecutor.oExecute(lcSqlCursor, [crsarticole])`
|
||||
(`:310-311`). Acelasi tipar apare a doua oara in `factureaza2` (`ofacturare.prg:824+`, ramura
|
||||
`frm_facturare_articole2`, prototipul).
|
||||
|
||||
**Consumatorii `crsarticole` in perimetrul S4** (`frm_facturare_articole`, `ofacturare.vc2:11xxx-15300`;
|
||||
lista completa via `vfp_symbols -Grep 'crsarticole\b' -CodeOnly`):
|
||||
|
||||
| Metoda | Linii | Ce face cu `crsarticole` | Ramane dupa S4? |
|
||||
|---|---|---|---|
|
||||
| `Destroy` | `12804-12811` | inchide cursorul | da, neschimbat |
|
||||
| `do_adauga_articol` | `12813-13167` | citeste **un rand ales** (`Scatter Name poArticol`), il scrie in `crsfactura` | **inlocuit** de randul intors de cautarea pe server, pe ramurile de lista de preturi — vezi punctul 7 |
|
||||
| `do_adauga_tot` | `13169-13198` | `Scan` peste tot cursorul, cheama `do_adauga_articol` pe fiecare rand | **pastrat neschimbat**, dar numai pe tipurile cu document sursa |
|
||||
| `do_cauta` | `13566-13593` | filtru client-side (`Set Filter`) peste cursorul deja incarcat, dupa text tastat in `txtArticole`/`txtCodmat` si politica aleasa | **dispare** pe ramurile de lista de preturi — inlocuit de `combosql` |
|
||||
| `do_scrie_factura` | `14301-14338` | `Calculate Sum(cantitate) To lnCantitateRamasa` peste `crsarticole`, decide daca se inchide comanda/avizul sursa (`pnParametruAditional`) | **pastrat neschimbat** — vezi verdictul |
|
||||
| `do_sterge` | `14608-14669` | la stergerea unei linii din `crsfactura`, **reface** cantitatea in `crsarticole`/`crsarticole1` (`Replace cantitate With cantitate + poArticol.cantitate`) | **pastrat neschimbat** pe tipurile cu bookkeeping; pe lista de preturi nu exista azi replace-back real (cantitatea nu scade la adaugare pe acele tipuri — stocul se verifica separat, prin `cursor_gestiuni_articol*`) |
|
||||
| `do_modifica` | `13778` | alege `crsarticole` sau `crsarticole1` dupa `opt_facturare` pentru verificare stoc | pastrat, tine de gestiunea aleasa la editarea unei linii deja adaugate |
|
||||
| `cb_politici_preturi.InteractiveChange` | `15647-15658` | cheama `do_cauta()` (filtru client-side) | **dispare** — pe varianta noua, schimbarea politicii devine parametru al cautarii pe server (`id_pol` in `WHERE`), nu filtru local |
|
||||
| `KeyPress` (navigare grid) | `15463-15486` | navigare in cursor la taste sageata | **dispare** pe ramurile fara grid de sus |
|
||||
|
||||
`frm_facturare_articole2` (prototipul, `:17xxx-18xxx`) are exact aceeasi structura pe
|
||||
`do_adauga_articol` / `do_adauga_tot` / `do_scrie_factura` / `do_sterge` — nu difera in aceasta
|
||||
privinta.
|
||||
|
||||
**Concluzie pentru cat se poate scoate:** `do_cauta` si filtrul din `cb_politici_preturi` dispar
|
||||
integral (inlocuite de cautarea pe server). `do_adauga_articol` isi schimba sursa randului (de la
|
||||
`Scan` in cursorul local la randul ales de `combosql`), dar restul lui (verificare stoc, alegere
|
||||
gestiune via `cursor_gestiuni_articol*`, scriere in `crsfactura`) **nu se schimba** — vezi punctul 6.
|
||||
`do_adauga_tot`, `do_sterge` (partea de bookkeeping) si `do_scrie_factura` (`lnCantitateRamasa`)
|
||||
**nu pot fi scoase** cat timp `crsarticole` ramane sursa lor de adevar pentru "cat a mai ramas" —
|
||||
motiv suplimentar, nu doar UX, pentru care "adauga tot" ramane cablat pe incarcare in masa acolo
|
||||
unde exista document sursa.
|
||||
|
||||
## 3. Cat costa azi incarcarea, pe forma interogarii (nu pe timpi masurati — decizia 31)
|
||||
|
||||
**`cursor_preturi` (ramurile 1/2 si generala) nu are niciun filtru pe articol** — semnatura n-are
|
||||
parametru de cod/denumire (`:2138-2146`). Rezultatul e **intreg catalogul accesibil utilizatorului**:
|
||||
`utilizatori_rol_intern` -> `politici_grupuri` -> `crm_politici_preturi` (toate politicile active la
|
||||
data cursului) -> `crm_politici_pret_art` (toate liniile de pret ale acelor politici) -> `nom_articole`.
|
||||
Numarul de randuri creste cu produsul dintre "cate politici de pret vede utilizatorul" si "cate
|
||||
articole are fiecare politica" — nu cu numarul de articole cautate, care e de regula 1.
|
||||
|
||||
Trei surse structurale de cost, vizibile direct in forma interogarii, nu masurate:
|
||||
|
||||
1. **`LEFT JOIN` pe `STOC` agregat** (`:2359-2378`, ramura 1/2) — subquery cu `GROUP BY ID_ARTICOL`
|
||||
peste tot stocul lunii curente, pe toate gestiunile la care utilizatorul are drept, recalculat la
|
||||
fiecare deschidere de formular, indiferent daca utilizatorul cauta un singur articol.
|
||||
2. **`FACT_VPRETURI_UTILIZATOR`** (ramurile 5/6/10/52 si 7 si aviz) e un view, nu un tabel — planul
|
||||
nu detaliaza corpul lui aici (ar fi o cercetare separata), dar fiind sursa pentru "toate preturile
|
||||
vizibile utilizatorului", are aceeasi forma: cost proportional cu marimea catalogului, nu cu
|
||||
cautarea.
|
||||
3. **`verifica_cursuri_valute`** (`:2153`, chemata necondiționat la fiecare apel) valideaza cursul
|
||||
pentru **toate** valutele din politicile utilizatorului, nu doar valuta articolului cautat —
|
||||
cost fix per deschidere, independent de ce se cauta.
|
||||
|
||||
Concluzia structurala: interogarea de azi calculeaza raspunsul pentru "orice articol ar putea alege
|
||||
utilizatorul", cand formularul are nevoie doar de "articolul pe care tocmai l-a tastat". Filtrarea pe
|
||||
`id_articol`/`codmat`/`denumire` reduce fiecare din cele trei surse la un numar de randuri marginit
|
||||
de cate politici de pret contin acel articol (de regula 1, rar cateva), nu de marimea catalogului.
|
||||
|
||||
## 4. Proiectarea variantei filtrate, cursor cu cursor
|
||||
|
||||
Toate cinci sunt proceduri PL/SQL in `PACK_FACTURARE`, apelate direct din VFP prin
|
||||
`{call pack.proc(...)}` + `goExecutor.oExecute`, fara view intermediar si fara strat ORM — deci
|
||||
minimul de schimbare e **acelasi tipar**: o procedura noua (sau o supraincarcare cu parametru
|
||||
suplimentar) in acelasi pachet, apelata din acelasi loc (`ofacturare.vc2`, metoda nou-introdusa pe
|
||||
`combosql`, nu din `ofacturare.prg`, care ramane neschimbat — el tot incarca varianta "in masa"
|
||||
acolo unde ramane necesara).
|
||||
|
||||
**Alegere de proiectare, nu fapt verificat:** supraincarcare (aceeasi denumire, parametru nou
|
||||
opțional `V_FILTRU_COD IN VARCHAR2 DEFAULT NULL` / `V_FILTRU_DEN IN VARCHAR2 DEFAULT NULL`) e mai
|
||||
sigura decat o procedura noua, pentru ca **garanteaza** aceleasi ramuri de `CASE`, acelasi `JOIN`,
|
||||
aceeasi logica de rotunjire — orice divergenta viitoare intre "cursor complet" si "cursor filtrat" ar
|
||||
fi un bug de sincronizare greu de prins. Cu supraincarcare, filtrul se adauga o singura data, in
|
||||
`WHERE`-ul final al fiecarei ramuri, nu in logica de business.
|
||||
|
||||
| Cursor | Ce se adauga | Unde (linia `WHERE`/`CASE` care primeste filtrul) |
|
||||
|---|---|---|
|
||||
| `cursor_preturi` | `AND (V_FILTRU_COD IS NULL OR C.CODMAT LIKE V_FILTRU_COD) AND (V_FILTRU_DEN IS NULL OR UPPER(C.DENUMIRE) LIKE UPPER(V_FILTRU_DEN))` — pe alias-ul articolului, `C` pe patru din cinci ramuri, `A` pe ramurile cu `FACT_VPRETURI_UTILIZATOR` | dupa `WHERE` existent, pe fiecare din cele 5 ramuri (`:2264`, `:2387-2388`, `:2464-2465`, `:2540-2541`, `:2640-2641`) — 5 locuri, nu unul |
|
||||
| `cursor_contract` | acelasi filtru pe `V_CURSOR` (delegat catre `cursor_preturi`, gratuit); pe `V_CURSOR2` filtrul se adauga in `UNION ALL`-ul de la `:2752` (partea cu `id_articol`), **nu** pe partea de rate (`id_articol IS NULL` — nu se pot filtra pe cod, raman needitate de filtru) | `:2825` (join articol) + propagare in `WHERE`-ul de la `:2819` |
|
||||
| `cursor_comanda` | filtru pe `C.CODMAT`/`C.DENUMIRE` in `WHERE A.ID_COMANDA = V_ID_COMANDA` (`:3078`, `:3166`) — **dar nu are sens sa se filtreze**: cf. punctul 7, comanda ramane pe calea "adauga tot" | de proiectat doar daca decizia de la punctul 7 se schimba |
|
||||
| `cursor_avize` | idem — nu are sens, acelasi motiv | idem |
|
||||
| `cursor_gestiune` | filtru pe `C.CODMAT`/`C.DENUMIRE` in interogarea de la `:4234-4237`, inainte de `GROUP BY` | `:4266-4293` |
|
||||
|
||||
**Parametrii care raman identici** pe varianta filtrata: `V_DATA_CURS`, `V_TIP`, `V_ID_VALUTA`,
|
||||
`V_ID_GESTIUNE_INIT`, `V_LUNA`, `V_AN`, `V_ID_UTIL`, `V_ID_SUCURSALA` — tot ce vine din `poDate` /
|
||||
sesiune la deschiderea formularului, nu se recalculeaza per cautare. Doar filtrul de text e nou, plus
|
||||
(pentru `cursor_preturi` in noua utilizare) eventual `V_ID_POL` daca utilizatorul a ales explicit o
|
||||
lista de preturi in combo-ul `cb_politici_preturi` — azi acel combo doar filtreaza local
|
||||
(`ofacturare.vc2:15647-15658`, comentat inlocuit cu `do_cauta()`); pe varianta noua devine parametru
|
||||
real al interogarii.
|
||||
|
||||
**Ce nu se poate verifica din cod, ramane de decis de Marius:** daca filtrul pe `codmat` foloseste
|
||||
`LIKE` "incepe cu" (ca `combosql` de azi, `nCharCountBegin`/cautare incrementala) sau match exact la
|
||||
alegerea din lista — combosql de azi face amandoua (tastare = "incepe cu" pe server, alegere din
|
||||
lista = valoare exacta), deci varianta cea mai apropiata de comportamentul actual e sa pastreze
|
||||
acelasi tipar: interogarea filtrata se cheama la fiecare tastare (ca azi, `RefreshData`), iar
|
||||
valoarea finala aleasa vine din randul deja adus, nu dintr-o interogare separata "exact match".
|
||||
|
||||
## 5. `combosql` — contract si exemple reale
|
||||
|
||||
**Clasa:** `combosql AS combobox`, `COMUN\clase\_cb_base.vc2:519-843`. Nu e specifica facturarii —
|
||||
traieste in biblioteca comuna a suitei, dar cautarea nu a gasit nicio alta utilizare, nici in
|
||||
`ROAFACTURARE`, nici in `COMUNROA`/`ROAGEST` (`grep -rn "AS combosql WITH"` — zero potriviri in afara
|
||||
`ofacturare.vc2:16751/16785/16861`, cele trei coloane ale gridului prototip). **Singurul exemplu real
|
||||
de folosire e chiar prototipul din plan** — nu exista alt loc in suita de copiat.
|
||||
|
||||
**Proprietati relevante** (`_memberdata`, `:560-575`):
|
||||
|
||||
| Proprietate | Rol |
|
||||
|---|---|
|
||||
| `csourcesql` | `SELECT` fara `WHERE`/`ORDER BY` — baza interogarii |
|
||||
| `csourcewhere` | conditia `WHERE` fixa (ex. `inactiv = 0`) |
|
||||
| `csourceorder` | `ORDER BY`, implicit `pfieldactiv` |
|
||||
| `pcursorname` | numele cursorului cu rezultatele |
|
||||
| `pfieldactiv` | campul dupa care se cauta si se afiseaza |
|
||||
| `psecondfield` | al doilea camp de cautare (optional) |
|
||||
| `ncharcountbegin` | cate caractere minim inainte sa porneasca interogarea pe server |
|
||||
| `llimittolist` | daca valoarea trebuie sa existe in lista |
|
||||
|
||||
**Mecanismul** (`refreshdata`, `:796-830`): construieste
|
||||
`SELECT ... FROM (cSourceSql) WHERE (cSourceWhere) AND (pFieldActiv LIKE ?pcValue [OR psecondfield
|
||||
LIKE ?pcValue]) ORDER BY ...`, cu `?pcValue` = `cSearchString + '%'` (incepe cu) sau
|
||||
`'%'+cSearchString+'%'` (contine, la Ctrl+Enter) si il executa prin
|
||||
**`goExecutor.oExecuta`** (`selectdata`, `:832-840`) — acelasi executor folosit peste tot in suita
|
||||
pentru apeluri Oracle, deci **niciun mecanism nou de transport**, doar un SQL nou de trimis.
|
||||
`KeyPress` (`:610-776`) gestioneaza incremental tastarea: la fiecare caracter tastat re-executa
|
||||
`RefreshData(1)` daca lungimea depaseste `nCharCountBegin`.
|
||||
|
||||
**Contractul de legare la o coloana de grid**, dedus din prototip (`ofacturare.vc2:16751-16762` +
|
||||
`:19288-19306`):
|
||||
|
||||
1. se adauga ca `CurrentControl` al coloanei (`Column1.CurrentControl = "cCboDenumire"`, `:16621`);
|
||||
2. `ControlSource` leaga afisarea de campul din cursorul de linii (`crsFactura.codmat`, `:16754`);
|
||||
3. **evenimentul de reactie e `LostFocus`, nu `Valid` sau `InteractiveChange`** — abia la parasirea
|
||||
celulei se scriu campurile in cursorul de linii, cu paza `If this.Value <> thisform.cOldValue`
|
||||
(setat in `When`, `:19308-19310`) ca sa nu se rescrie fara motiv;
|
||||
4. `LostFocus` de azi scrie **doar** campurile pe care le are `vnom_articole`: `codmat`, `denumire`,
|
||||
`id_articol` (`:19293`) — nimic despre pret, TVA, valuta. **Aici se opreste prototipul azi**; tot
|
||||
ce trebuie adaugat pentru S4 e sa inlocuiasca `crsCodmat`/`crsDenumire` (rezultatul din
|
||||
`vnom_articole`) cu rezultatul cursorului Oracle filtrat de la punctul 4, care are toate coloanele,
|
||||
si sa extinda `REPLACE`-ul de la `:19293`/`:19317` cu restul campurilor din tabelul de la punctul 6.
|
||||
|
||||
**Ce nu ofera azi `combosql` si trebuie adaugat, nu doar copiat:** `csourcesql` e un `SELECT`
|
||||
static definit in `.vcx` la design-time, nu poate primi parametrii dinamici ai documentului curent
|
||||
(`poDate.zi_curs`, `poDate.tip`, `poDate.id_valuta`...) direct in proprietate. Pentru cursorul
|
||||
Oracle cu 8 parametri, populate din `poDate`/sesiune, `csourcesql`/`csourcewhere` trebuie construite
|
||||
dinamic in `Init` sau la schimbarea documentului (nu sunt string-uri fixe ca azi), sau — alternativa
|
||||
mai simpla — `refreshdata`/`selectdata` se suprascriu punctual pe instanta din grid, ca sa apeleze
|
||||
`{call pack_facturare.cursor_preturi_filtrat(...)}` in loc de `SELECT ... FROM (cSourceSql)`. A doua
|
||||
varianta pastreaza restul mecanismului (`KeyPress`, incremental, `LostFocus`) neschimbat si e
|
||||
schimbarea minima — de confirmat cu Marius, nu o certitudine de cod.
|
||||
|
||||
## 6. Maparea camp-cu-camp
|
||||
|
||||
Sursa cea mai fiabila pentru "ce completeaza azi `crsarticole` in linie" nu e cursorul Oracle brut, ci
|
||||
`Gather Name poArticol Fields Like ...` din `do_adauga_articol` (`ofacturare.vc2:12945-12957`,
|
||||
identic pe `frm_facturare_articole2` la `:17226+`) — acolo se vede exact ce trece din randul scanat
|
||||
in `crsfactura`.
|
||||
|
||||
| Camp in `crsfactura` | Vine din `crsarticole` (coloana cursorului Oracle) | Pe varianta filtrata |
|
||||
|---|---|---|
|
||||
| `id_articol`, `codmat`, `codbare`, `denumire`, `um` | direct din cursor | identic — filtrul e chiar pe aceste coloane |
|
||||
| `pret_achizitie` | **nu** din `crsarticole` — vine din `poArtLista`/`crsartselectate` (rezultatul lui `cursor_gestiuni_articol*`, ales dupa `crsarticole`), nu din cursorul de lista de preturi | **neschimbat** — pasul e deja separat azi, ramane separat |
|
||||
| `id_pol` | direct (`crsarticole.id_pol`) | identic |
|
||||
| `Cont` | direct (`crsarticole.cont`, doar ramura restaurant o are explicit; pe restul vine `'371'` implicit sau din `cursor_gestiuni_articol*`) | identic pe ramurile care il au; **de verificat** pe ramurile 1/2/5/6/7/10/52/aviz — cursorul nu are `CONT` explicit in `SELECT` (`:2268-2329` etc.), deci provine din `do_alege_stoc`, nu din `crsarticole` |
|
||||
| `id_gestiune` | direct doar pe ramura restaurant (`A.ID_GESTIUNE`, `:2220`); pe rest vine din alegerea de gestiune (`cursor_gestiuni_articol*`) | identic — pasul de alegere gestiune ramane neschimbat |
|
||||
| `Proc_Tvav`, `pretftva`, `Pretctva`, `discountftva`(`discount_unitar`), `discountctva` | direct din cursor, plus `do_initializeaza_articol` (`:13618-13659`) care deriva `pretftva`/`pretctva`/`tva` reciproc dupa `preturi_cu_tva` | identic — logica de derivare e in VFP, nu se schimba |
|
||||
| `id_valuta`, `tip_valuta`, `nume_val`, `Curs`, `multiplicator` | direct din cursor | identic |
|
||||
| `gestionabil` | direct din cursor | identic (inclusiv regula de proforma, `ofacturare.prg:333-336`, care suprascrie `gestionabil=0` — ramane in `ofacturare.prg`, neschimbata) |
|
||||
| `id_jtva_coloana` | direct doar pe ramurile care il au explicit in `SELECT` (aviz/contract/retur); pe `cursor_preturi` (1/2/5/6/7/10/52) **nu apare in lista de coloane** returnate (`:2264-2329`) | **de verificat cu Marius** — daca lipseste azi, `Gather ... id_jtva_coloana` scrie `NULL`/valoare implicita; filtrarea nu schimba nimic aici, dar merita clarificat inainte de implementare, nu presupus |
|
||||
| `pretv_orig`, `pretd`, `id_valuta_d` | nu apar in `cursor_preturi`; vin din `poArtLista`/`crsartselectate` (alegerea de gestiune) | neschimbat |
|
||||
| `taxcode`, `explicatie`, `id_lucrare_rez`, `id_part_rez`, `id_ctr`, `opt_facturare` | nu din `crsarticole` — din `poArticol`/context (`do_initializeaza_articol`, `do_alege_stoc`) | neschimbat |
|
||||
| `pret_cu_tva` (flag `preturi_cu_tva`) | direct din cursor (`A.PRETURI_CU_TVA` / `D.PRETURI_CU_TVA`) | identic |
|
||||
|
||||
**Concluzie pentru punctul 6 al cerintei:** nicio coloana din cele cerute explicit (pret, cota TVA,
|
||||
valuta, `id_pol`, `gestionabil`, `pret_cu_tva`) nu ridica probleme — toate vin direct din cursorul
|
||||
Oracle si filtrarea pe articol nu le atinge. Singurul semnal de atentie e `id_jtva_coloana`, absent
|
||||
din `cursor_preturi` insusi (posibil completat in alt pas, neverificat aici — iese din perimetrul
|
||||
"cele cinci cursoare", ar cere citirea intregului `do_adauga_articol`/`calculeaza_totaluri`).
|
||||
|
||||
## 7. „Adauga tot" — ce ramane si de ce (nu doar decizia din plan)
|
||||
|
||||
Planul spune "se pastreaza adauga tot pentru tipurile cu document sursa (comanda, aviz, contract) —
|
||||
acolo setul e marginit". Cercetarea (punctul 2) arata un motiv suplimentar, mai tare decat marimea
|
||||
setului: **bookkeeping-ul de cantitate ramasa** (`do_sterge`, `do_scrie_factura`) citeste si scrie
|
||||
direct in `crsarticole`, deci acel cursor **trebuie sa existe incarcat in memorie** cat timp
|
||||
formularul e deschis, indiferent cum alege utilizatorul liniile.
|
||||
|
||||
**Vizibilitatea de azi a butonului `but_urmator_tot1`** ("adauga tot"), confirmata pe cod
|
||||
(`ofacturare.vc2:15108-15248`, `Do Case poDate.tip`):
|
||||
|
||||
| Tip | Vizibil "adauga tot" azi | Sursa cursorului |
|
||||
|---|---|---|
|
||||
| proforma (`eProforma=1`) | da (`:15113`) | `cursor_preturi` sau alt cursor dupa tip, marcat negestionabil |
|
||||
| copiere (`lCopiere`) | da (`:15120`) | `cursor_preturi` (varianta copiere, `ofacturare.prg:464-473`) |
|
||||
| `1, 5, 7, 10` — lista de preturi | **nu** | `cursor_preturi` |
|
||||
| `2, 6` — contract | **nu** | `cursor_contract` |
|
||||
| `3` — comanda | da (`:15150`) | `cursor_comanda` |
|
||||
| `4` — avize | da (`:15166`) | `cursor_avize` |
|
||||
| `21, 28, 42, 47` — aviz din comanda | da (`:15177`) | `cursor_comanda` |
|
||||
| `22, 29` — aviz din lista de preturi | **nu** | `cursor_preturi` |
|
||||
| `23, 41` — transfer subunitati | **nu** menționat explicit vizibil | `cursor_gestiune` |
|
||||
| `25` — transfer din comanda | da (`:15215`) | `cursor_comanda` |
|
||||
| `26` — aviz din contract | **nu** | `cursor_contract` |
|
||||
| `8, 9` — retur | da (`:15240`) | `cursor_retur` (nu e in cele 5, iese din perimetru) |
|
||||
| `24` — aviz retur | da (`:15245`) | `cursor_retur` |
|
||||
|
||||
**Coincide exact** cu impartirea utila pentru S4: butonul e vizibil azi pe tipurile unde
|
||||
`do_adauga_tot` are sens pentru ca setul e mic **si** bookkeeping-ul de ramas il cere
|
||||
(comanda/aviz-din-comanda/retur), si e ascuns pe tipurile de lista de preturi (1/5/7/10, 22/29) si pe
|
||||
contract-lista-de-preturi (2/6/26) — exact ramurile pe care cautarea filtrata inlocuieste incarcarea
|
||||
in masa. **Contractul insa nu are azi "adauga tot" vizibil deloc** (nici pe partea de rate, nici pe
|
||||
partea de articole) — planul semnaleaza asta separat, la S4b, ca gol de acoperit (tipurile 2, 6, 26,
|
||||
52 lipsesc din conditiile de vizibilitate), nu ca ceva de pastrat.
|
||||
|
||||
**Concret, ce se schimba per tip:**
|
||||
- **Lista de preturi (1,5,7,10,22,29) si transfer pe lista (23,41,45,48,49):** `crsarticole` nu se
|
||||
mai incarca la deschidere; `combosql` cauta filtrat; "adauga tot" ramane ascuns (ca azi — n-are
|
||||
sens pe catalog intreg).
|
||||
- **Comanda (3,21,25,28,42,47) si avize (4):** `crsarticole` **ramane incarcat in masa**, neschimbat;
|
||||
`combosql` **nu se activeaza** pe aceste tipuri (sau, daca se activeaza pentru UX, cauta *in*
|
||||
cursorul deja incarcat, nu pe server — cautare locala, nu Oracle) pentru ca bookkeeping-ul de
|
||||
cantitate ramasa il cere oricum incarcat.
|
||||
- **Contract (2,6,26,52):** dublu — `crsarticole` (jumatatea `cursor_preturi`) trece pe cautare
|
||||
filtrata ca orice lista de preturi; `crsarticole1` (rate + articole `OPT_FACTURARE=3`) **ramane
|
||||
incarcat in masa**, bounded de contract, neschimbat de S4 (randurile de rata n-au `id_articol`,
|
||||
nu pot fi cautate).
|
||||
- **Retur (8,9,24):** in afara celor cinci cursoare cerute (`cursor_retur`/`cursor_retur_document`),
|
||||
proiectat separat la S4f — nesemnalat aici ca problema, doar exclus din perimetru.
|
||||
|
||||
## 8. Interactiunea cu S4b si S10
|
||||
|
||||
**Cu S4b (bara de butoane / meniul de adaugare):** S4b proiecteaza meniul `xmenu()` "Adauga
|
||||
articole" cu optiunile pe sursa (tot / alege), inclusiv acoperirea golului de pe contract (tipurile
|
||||
2/6/26/52). S4 ii da continutul concret pentru ramura "cauta in linie": pe tipurile de lista de
|
||||
preturi (unde S4b nu are nevoie de optiunea "tot" azi), linia de grid cu `combosql` **este** metoda
|
||||
de adaugare — nu exista un dialog separat de ales. Pe tipurile cu document sursa, S4 nu schimba
|
||||
nimic din ce proiecteaza S4b: meniul ramane cablat pe `do_adauga_tot`/alegere din `crsarticole`
|
||||
existent. Punctul de atingere real: daca S4b decide sa afiseze si pe contract un "adauga tot" (gol
|
||||
semnalat la punctul 7), acel "tot" trebuie sa opereze pe `crsarticole1` (rate+articole), nu pe
|
||||
`crsarticole` (lista de preturi) — cele doua cursoare raman distincte si dupa unificare.
|
||||
|
||||
**Cu S10 (pretul care nu trebuie re-derivat, `docs\cercetare\s10_pret_rederivat.md`):** verificarea
|
||||
S10 arata ca `adauga_articol_factura` **primeste pretul ca parametru** (`V_PRET_ACHIZITIE_TEMP` si
|
||||
restul) si nu-l recalculeaza, cu o singura exceptie tacuta: liniile de contract cu
|
||||
`OPT_FACTURARE = 3`, unde `CTR_ARTICOLE.PRET_UNITAR` **suprascrie** pretul trimis, necondiționat de
|
||||
sursa. Pentru S4, asta inseamna doua lucruri concrete:
|
||||
1. cursorul filtrat (`cursor_preturi`/`cursor_gestiune` cu filtru pe articol) se cheama **o singura
|
||||
data**, la selectarea liniei in `combosql` (`LostFocus`) — pretul obtinut atunci se scrie in
|
||||
`crsfactura` si **nu se re-interogheaza** la scriere, exact ca azi pe calea `crsarticole` completa;
|
||||
2. pe **contract**, indiferent daca linia a fost aleasa prin `crsarticole1` (needitat de S4) sau,
|
||||
ipotetic, printr-o cautare filtrata viitoare, riscul de suprascriere tacuta descris in S10 exista
|
||||
deja si S4 nu-l introduce si nu-l rezolva — il mosteneste neschimbat, pentru ca punctul de
|
||||
suprascriere e in `adauga_articol_factura` (scriere), nu in cursorul de cautare (citire).
|
||||
|
||||
## 9. Ordinea de executie in pasi
|
||||
|
||||
1. **Pas 1 — Oracle, `cursor_preturi` filtrat.** Supraincarcare cu `V_FILTRU_COD`/`V_FILTRU_DEN`
|
||||
opționale, aceleasi 5 ramuri, filtru adaugat in `WHERE`-ul fiecareia (punctul 4). *Gata cand:*
|
||||
apelat cu filtru gol, cursorul e identic randuri-cu-randuri (aceleasi coloane, aceleasi valori, pe
|
||||
fiecare din cele 5 ramuri de `V_TIP`) cu varianta actuala pe acelasi set de parametri — comparatie
|
||||
directa pe SQL, nu pe timp.
|
||||
2. **Pas 2 — Oracle, `cursor_gestiune` filtrat.** Acelasi tipar, un singur `SELECT`, mai simplu.
|
||||
*Gata cand:* idem, comparatie randuri-cu-randuri cu filtru gol.
|
||||
3. **Pas 3 — Oracle, `cursor_contract`, doar partea `V_CURSOR`.** Filtrul se propaga gratuit prin
|
||||
apelul catre `cursor_preturi` de la `:2940-2948`; nicio schimbare suplimentara necesara daca Pasul
|
||||
1 e facut corect. *Gata cand:* `cursor_contract` cu filtru gol produce acelasi `V_CURSOR` ca
|
||||
inainte de Pasul 1 (regresie, nu functie noua).
|
||||
4. **Pas 4 — VFP, `combosql` pe `cCodMat`/`cCboDenumire`.** Inlocuieste `csourcesql`/`SelectData` cu
|
||||
apelul la cursorul filtrat (punctul 5); extinde `LostFocus` (`:19288-19330`) sa scrie toate
|
||||
campurile din tabelul de la punctul 6, nu doar `codmat`/`denumire`/`id_articol`. *Gata cand:*
|
||||
alegerea unei linii in grid, pe un document de tip lista-de-preturi, produce in `crsfactura`
|
||||
aceleasi valori ca alegerea aceluiasi articol azi din `crsarticole` incarcat complet — comparatie
|
||||
pe date, punctul 10.
|
||||
5. **Pas 5 — VFP, oprirea incarcarii in masa pe tipurile vizate.** In `ofacturare.prg:266-311`, pentru
|
||||
`tnTip` din ramurile de lista de preturi (1,5,7,10,22,29,23,41,45,48,49) si jumatatea `cursor_preturi`
|
||||
a contractului, `goExecutor.oExecute` nu se mai cheama la deschidere — grid-ul porneste gol,
|
||||
`combosql` populeaza la cerere. *Gata cand:* deschiderea formularului pe aceste tipuri nu executa
|
||||
niciun apel `cursor_preturi`/`cursor_gestiune`/`cursor_contract` (verificabil in log-ul
|
||||
`goExecutor`/`WAIT WINDOW ... NOWAIT` din `combosql.selectdata`, care ramane singurul loc care
|
||||
cheama Oracle pentru articole).
|
||||
6. **Pas 6 — verificare "adauga tot" neatins.** Pe comanda/aviz/contract-rate, `do_adauga_tot`,
|
||||
`do_sterge`, `do_scrie_factura` raman neschimbate (Pasii 1-5 nu le ating codul). *Gata cand:*
|
||||
regresie manuala pe un document din comanda si unul din aviz — comportament identic cu azi.
|
||||
|
||||
*Depinde de:* S3 (planul o marcheaza asa; portarea antetului trebuie sa existe inainte, ca sa aiba
|
||||
`poDate` populat corect la deschiderea gridului).
|
||||
|
||||
## 10. Cum se verifica „aceleasi valori ca azi"
|
||||
|
||||
**Testabil pe date (nu doar pe cod), propunere concreta:** pentru fiecare tip reprezentativ (1 sau 5
|
||||
pentru lista de preturi, 2 pentru contract, 41 pentru transfer-gestiune), se alege un articol prezent
|
||||
in cursorul complet de azi si se compara randul din `crsarticole` (deschidere veche, neschimbata) cu
|
||||
randul intors de cursorul filtrat pe acelasi articol, aceiasi parametri (`zi_curs`, `id_valuta`,
|
||||
`id_gestiune_init`, utilizator) — comparatie coloana cu coloana, in Oracle direct (doua `SELECT`-uri,
|
||||
`MINUS` intre ele pe coloanele comune) sau in VFP prin doua cursoare deschise simultan. Se repeta pe
|
||||
un articol cu politica de discount, unul in valuta si unul fara stoc (`RF_FACTURARE_FARA_STOC`), ca
|
||||
sa acopere ramurile de `CASE` din punctul 1.
|
||||
|
||||
**Ce nu se poate testa headless — capcana cunoscuta** (`grid-coloane-nu-se-materializeaza-headless`,
|
||||
memorie de proiect): sub `-A -T`, `ColumnCount`/`RecordSource` ale gridului sunt artefacte, nu
|
||||
reflecta ce vede operatorul. Deci **partea VFP** (alegerea din `combosql`, `LostFocus`-ul care scrie
|
||||
in `crsfactura`) nu se poate verifica prin harnessul headless obisnuit — cere fie harnessul UI
|
||||
vizibil existent, fie verificare directa pe cursorul `crsfactura` dupa un apel programatic la metoda
|
||||
`LostFocus` (posibil, pentru ca metoda insasi nu depinde de randare, doar de `This.Value` — de
|
||||
confirmat la implementare). Partea Oracle (comparatia de cursoare de mai sus) **e** testabila
|
||||
headless, prin `SELECT`, fara nicio dependenta de VFP.
|
||||
|
||||
## 11. Riscuri si ce ramane de decis de Marius
|
||||
|
||||
- **`id_jtva_coloana` lipsa din `cursor_preturi`** (punctul 6) — de clarificat inainte de
|
||||
implementare daca e completat in alt pas (nevazut aici) sau ramane `NULL` si azi; filtrarea nu
|
||||
schimba comportamentul, dar nota trebuie inchisa ca sa nu para un bug nou introdus de S4.
|
||||
- **Mecanismul de legare `combosql` -> cursor Oracle parametrizat dinamic** (punctul 5, ultimul
|
||||
paragraf) e o alegere de implementare, nu un fapt de cod — `csourcesql` static din `.vcx` nu poate
|
||||
primi parametrii de sesiune direct; solutia propusa (suprascriere punctuala `refreshdata`) e
|
||||
rezonabila, dar nu e singura posibila si nu exista alt exemplu in suita de comparat.
|
||||
- **Contractul ramane cu doua surse de date pe acelasi grid conceptual** (`crsarticole` filtrat +
|
||||
`crsarticole1` needitat) — de confirmat ca UX-ul (doua zone: cautare + grid rate) e acceptabil, nu
|
||||
doar tehnic corect.
|
||||
- **`cursor_gestiune` (transfer subunitati) nu are azi buton "adauga tot" vizibil** (tabelul din
|
||||
punctul 7 nu-l gaseste in `Do Case`) — de verificat separat daca tipurile 23/41 au alt mecanism de
|
||||
adaugare in masa, neacoperit de cautarea in `crsarticole`/`crsarticole1` directa; nu s-a citit codul
|
||||
suplimentar necesar pentru raspuns cert aici.
|
||||
- **Validarea de curs valutar (`verifica_cursuri_valute`, punctul 1.1) ramane neconditionata** chiar
|
||||
si pe varianta filtrata, daca se pastreaza in procedura supraincarcata — poate produce `-20005` la
|
||||
prima cautare a unui articol, inainte ca utilizatorul sa fi vazut vreun rand, pe o valuta pe care
|
||||
n-o foloseste azi doar pentru ca incarcarea in masa "o gasea" oricum. De discutat cu Marius daca
|
||||
validarea trebuie restransa la valuta articolului cautat sau ramane globala (comportament
|
||||
identic cu azi, doar declansat mai des — la fiecare cautare, nu o data la deschidere).
|
||||
- **Numarul exact de apeluri Oracle pe sesiune de cautare** (un apel per tastare, cu debounce prin
|
||||
`nCharCountBegin`) nu a fost masurat si nu trebuie masurat aici (decizia 31) — dar merita setat
|
||||
explicit `nCharCountBegin` >= 2-3 la implementare, ca sa nu se piarda avantajul filtrarii intr-un
|
||||
numar mare de interogari de o litera.
|
||||
|
||||
## Handoff
|
||||
|
||||
Cercetare incheiata in aceasta sesiune, fara nevoie de predare — toate cele 11 puncte cerute sunt
|
||||
acoperite mai sus, cu citate `fisier:linie` verificate pe fisierul real (nu `.bak`). Niciun fisier de
|
||||
cod atins, niciun `git_sync.ps1`/`txt2vcx.ps1` rulat, nicio scriere pe Oracle.
|
||||
Reference in New Issue
Block a user