Files
comun/docs/cercetare/rec_view_articole_vanzare.md
Marius Mutu 09ddeabb1c docs: cercetarile trans-proiect din ROAFACTURARE trec in COMUN
Paisprezece rapoarte care nu erau ale ROAFACTURARE traiau in docs\cercetare\ al
acelui proiect: valuta si curs in ofacturare, TVA calculat vs salvat plus
denormalizarea VANZARI, inventarul consumatorilor VANZARI din toata suita ROA,
integrarile de contracte/politici/nomenclator (#10, #11, #12), watchdog-ul VFP
de testare, proiectarea Oracle a scrierii din S5 si view-ul VVANZARI_ARTICOLE.

Motivul mutarii, nu doar al pastrarii: planurile #10, #11 si #12 sunt amanate,
iar indexul lor spune explicit ca se reiau din aceste rapoarte - deci sunt punct
de plecare, nu istoric. Iar tinta lor e COMUN plus ROAPRETURI/ROACONTRACTE.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
2026-08-11 22:31:53 +03:00

165 lines
10 KiB
Markdown

# Proiectare view Oracle pentru liniile de articole ale unei vanzari (VVANZARI_ARTICOLE)
Cercetare + proiectare, read-only pe baza. Decizia lui Marius (08.08.2026): view dedicat, varianta B
din `rec_review_ancorare_s4.md` (respinsa atunci doar pentru ca insemna migrare de schema - acum
aprobata). Inlocuieste lista de 20 coloane + join pe 4 tabele din `IncarcaArticoleFactura`
(`COMUN\programe\ofacturare_editare.prg:201-208`).
## A. Precoditia VERSIUNE
`MARIUSM_AUTO` e la zi **pentru schema firmei (`ff_`)** pe orice ar putea atinge `VANZARI_DETALII`/
facturare: toate scripturile `ff_` din 2015 incoace apar in `VERSIUNE`, inclusiv cele mai recente
patru (`ff_2026_08_06_09/10/11/12`, comanda/contract, `PACK_FACTURARE`, `FACT_VFACTURI`,
`VANZARI_BACKFILL`). Diferenta gasita fata de `SCRIPTURI_CLAR` (452 de fisiere, din care 14 `ff_`)
e integral din 2009-2014 (dinainte de generalizarea `UpdateVersiune`) plus scripturi de diagnostic
fara prefix de tracking (`DIAG_SPATIU_*`, ad-hoc-uri fara nume standard) - niciunul din ele nu
atinge `VANZARI`/`VANZARI_DETALII`/facturare. Verdict: **precoditia trece**, sursa `MARIUSM_AUTO` e
de incredere pentru acest DDL.
## B. Ce exista deja - niciun candidat direct refolosibil, dar un precedent util
Cautat in `all_views` (MARIUSM_AUTO) orice view pe `VANZARI_DETALII`/liniile unei vanzari:
`VVANZARI_DETALII`, `VVANZARI_DETALII_TOT`, `FACT_VFACTURI_DETALII` sunt cele relevante.
- **`FACT_VFACTURI_DETALII`** (exportat integral) e cel mai apropiat candidat structural - selecteaza
direct din `vanzari_detalii`, cu join-uri catre `nom_articole`/`nom_gestiuni`/`nom_valute` ca in
proiectarea de mai jos. **Nu e reutilizabil ca atare**: `pret` si `discount_unitar` sunt
RECALCULATE la cursul valutar curent (`ROUND(NVL(g.curs,1)*NVL(a.pret,0)/NVL(g.multiplicator,1),
pack_sesiune.getoptiunefirma('PPRETV'))`, apel de functie PL/SQL per coloana per rand), construit
pentru **afisare/tiparire** facturi, nu pentru editare. Pagina de editare (#6) trebuie sa lucreze
pe valorile RAW stocate, ca la salvare (S5) sa scrie inapoi exact ce a citit - un `pret` deja
convertit ar strica exact acest contract. Confirma insa tiparul de join corect (articol/gestiune/
valuta) si ca genul asta de view exista deja in familia `FACT_*` pentru alt scop.
- **`VVANZARI_DETALII`/`VVANZARI_DETALII_TOT`**: alt scop (afisare generica vanzari + utilizatori +
politici de pret), nu au `pret_cu_tva`, `cont`, `id_valuta`, `id_gestiune`, `taxcode`, `lot` -
nepotrivite.
Niciunul nu inlocuieste nevoia unui view nou - se continua cu proiectarea.
## C. Numele: `VVANZARI_ARTICOLE`
Verificat liber in `all_objects` (MARIUSM_AUTO). 17 caractere, sub limita de 30 (Oracle 10.2).
**Criteriul lui Marius (08.08.2026)**: numele trebuie sa pastreze prefixul familiei de vanzari,
`vvanzari_*`, pentru ca el se uita la view-uri **alfabetic** si vrea sa vada dintr-o privire ca tine
de vanzari. La o listare alfabetica: `VVANZARI_ARTICOLE`, `VVANZARI_DETALII`,
`VVANZARI_DETALII_TOT`, `VVANZARI_TOT`.
Numele analog conventiei surorilor de pe acelasi formular (`vact_tot`, `vrul_tot`,
`vrul_obinv_tot`) ar fi fost `vvanzari_detalii_tot`, dar e **deja ocupat** (alt view, B mai sus).
Numele de lucru din prima varianta a fost `VVD_TOT` (`v` + abreviere + `_tot`, aliniat cu aliasul
VFP `tvd`), respins de Marius pe criteriul de mai sus: nu se citea ca facand parte din familie si
cadea in alta parte a listei alfabetice.
## D. Coloanele - RAW, fara filtru STERS in view
Cele 20 de coloane consumate azi + **`id_vanzare` adaugat**: lista din
`ofacturare_editare.prg:201-203` filtreaza pe `vd.id_vanzare` dar nu-l intoarce niciodata ca si
coloana - omisiune reala, semnalata in misiune, acum corectata in view.
- **Fara conversie valutara, fara valori calculate** (spre deosebire de `FACT_VFACTURI_DETALII`) -
editarea scrie inapoi exact ce citeste.
- **`STERS` ramane in view ca si coloana, dar FARA filtru `WHERE sters=0` in definitie** - acelasi
tipar ca `VACT_TOT`/`VRUL_TOT`/`VRUL_OBINV_TOT` (niciunul nu filtreaza `sters` in view, apelantul
o face explicit). Apelantul de azi (`IncarcaArticoleFactura`) deja are `WHERE ... vd.sters = 0` -
ramane neschimbat, doar `FROM vanzari_detalii vd ... WHERE vd.id_vanzare=... AND vd.sters=0` devine
`FROM vvanzari_articole vd WHERE vd.id_vanzare=... AND vd.sters=0`.
## E. Ce s-a respins: valorile calculate `CALCULEAZA_TOTAL_FARA_TVA_FACT`/`_TVA_FACT`
Ambele sunt functii **in `PACK_FACTURARE`**, semnatura `(V_PRET, V_DIFERENTA, V_CURS,
V_DISCOUNT_UNITAR, V_DISCOUNT_EVIDENTIAT, V_CANTITATE, V_PRET_CU_TVA, V_PROC_TVAV) RETURN NUMBER` -
strict `NUMBER`, deci **apelabile din SQL** (confirmat prin `all_arguments`, fara tip PL/SQL-only).
Exista precedent local pentru functii de pachet apelate per-rand intr-un view din aceeasi familie
(`VRUL_TOT` cheama `PACK_SESIUNE.SUMA_RON` pe aproape fiecare coloana numerica), deci performanta nu
e un argument respingator prin ea insasi pe un view filtrat pe `id_vanzare` (cateva linii/factura).
**Respins totusi, pentru acum**:
1. `V_DISCOUNT_EVIDENTIAT` **nu e coloana pe `VANZARI_DETALII`** - e pe antet (`VANZARI.
DISCOUNT_EVIDENTIAT`, confirmat in `all_tab_columns`). A include totalul calculat per linie ar
cere fie un join suplimentar la `VANZARI` (umfla view-ul cu o dependenta noua doar pentru un
parametru), fie parametrul trimis din VFP - oricum, in afara scopului Rundei 1 (doar afisare).
2. Runda 1 (deja implementata si testata, `docs\progres.md`) **nu consuma** aceste valori - grid-ul
e readonly, fara subtotal calculat.
3. Nevoia reala apare la S4b/Runda 4 (`plan_06_s4_proiectare.md`, C.1-C.3) - dar acolo e vorba de
**totalul pe DOCUMENT** (suma peste toate liniile), comparat cu `ACT`/`RUL`, nu de o coloana pe
fiecare rand din grid. O interogare de agregare separata (sau o functie Oracle dedicata) e o
potrivire mai buna pentru "totalul de control" decat 2 coloane calculate in view-ul de grid.
4. **Costul amanarii e mic**: extinderea unui VIEW (`CREATE OR REPLACE`) nu e o migrare de schema in
sensul de risc/coordonare al unei modificari de tabela - se poate adauga oricand printr-un script
nou, fara sa afecteze datele sau consumatorii existenti ai coloanelor deja definite. Deci nu e
nevoie sa se "prevada" acum ca sa se evite un al doilea script peste o saptamana.
**Recomandare pentru Runda 4**: cand S4b ajunge la implementare, se adauga fie doua coloane noi in
`VVANZARI_ARTICOLE` (dupa un join la `VANZARI` pentru `DISCOUNT_EVIDENTIAT`), fie - preferabil - o interogare
de agregare separata in Oracle care calculeaza direct SUMA pe document, fara sa treaca prin grid.
Decizia ramane a lui Marius/sesiunii care implementeaza S4b, pe baza planului deja scris in
`plan_06_s4_proiectare.md` C.1.
## F. Validare pe cele doua cazuri de regresie
Rulat direct ca `SELECT` (fara `CREATE VIEW`), corpul propus vs. interogarea de azi din
`IncarcaArticoleFactura`, pe `MARIUSM_AUTO`:
- **`id_vanzare = 1050`** (`cod=1140888`, `tip=1`): **4 randuri**, valori identice rand-cu-rand intre
interogarea veche si corpul noului view (`id_vanzare_det` 1584-1587). Coincide cu baza de regresie
din `docs\progres.md`.
- **`id_vanzare = 1047`** (`cod=1140885`, `tip=-12`): **2 randuri** (1578, 1579), identice intre cele
doua interogari.
Ambele cazuri: zero divergenta, inclusiv pe coloanele cu `NULL` (ex. `id_gestiune`/`nume_gestiune`
pe liniile nestocate din `id_vanzare=1047`).
## G. Numele coloanelor la iesire
Fara alias-uri noi - toate coloanele pastreaza numele lor de baza din tabelele sursa (Oracle
foloseste automat numele coloanei cand nu exista `AS`):
```
ID_VANZARE, ID_VANZARE_DET, ID_ARTICOL, CANTITATE, PRET, PRET_CU_TVA, PROC_TVAV, DISCOUNT_UNITAR,
ID_GESTIUNE, CONT, ID_VALUTA, ID_JTVA_COLOANA, SERIE, EXPLICATIE, TAXCODE, LOT, STERS,
DENUMIRE, CODMAT, NUME_GESTIUNE, NUME_VAL
```
**Zero schimbari fata de azi** pentru `ControlSource`-urile existente ale `grdArticoleFactura`
(`tvd.denumire`, `tvd.codmat`, etc.) - toate numele coincid cu ce se foloseste azi. Singura
schimbare vizibila e coloana noua `tvd.id_vanzare`, disponibila dar neconsumata inca de grid.
## H. Numerotare script
`SCRIPTURI_CLAR\2026\08\` exista deja, ultimul numar folosit azi (08.08.2026, la momentul
verificarii) e **niciunul** - nu exista fisiere `_2026_08_08_` in director (ultimele sunt din
06.08.2026, `NN` pana la 12). **`NN=01` e liber pentru 08.08.2026**, comun tuturor prefixelor -
de reverificat la momentul aplicarii, pentru ca sesiunea are mai multi agenti activi in paralel azi
care ar putea consuma acelasi numar inaintea acestui script.
Nume final propus: **`ff_2026_08_08_01_COMUN_VVANZARI_ARTICOLE.sql`** - scriptul livrat foloseste deja acest
nume in `exec pack_migrare.UpdateVersiune(...)`; daca sesiunea principala aloca alt `NN`, fisierul
**si** acel apel trebuie schimbate impreuna (altfel `VERSIUNE` inregistreaza un nume care nu exista
pe disc).
## I. Format script
`CREATE OR REPLACE VIEW` (fara `FORCE`) - verificat pe modelul cel mai recent din `SCRIPTURI_CLAR`
(`ff_2026_08_06_11_COMUN_FACT_VFACTURI.sql`, care creeaza doua view-uri fara `FORCE`); `FORCE` nu e
necesar oricum, toate tabelele sursa (`VANZARI_DETALII`, `NOM_ARTICOLE`, `NOM_GESTIUNI`,
`NOM_VALUTE`) exista deja. CRLF verificat byte-safe dupa scriere (44 CRLF, 0 LF singur). Fara `;` in
comentarii inaintea instructiunii. Se incheie cu `UpdateVersiune` + `commit`.
## Livrabil
`D:\ROA\ROAFACTURARE\docs\cercetare\ff_view_articole_vanzare.sql` - scriptul complet, **neaplicat**.
## Ce trebuie schimbat in VFP ca urmare (doar cand se aplica scriptul)
1. `COMUN\programe\ofacturare_editare.prg:201-208` (`IncarcaArticoleFactura`): inlocuieste
`FROM vanzari_detalii vd LEFT JOIN nom_articole na ... LEFT JOIN nom_gestiuni ng ... LEFT JOIN
nom_valute nv ...` cu `FROM vvanzari_articole vd`, pastrand neschimbat `WHERE vd.id_vanzare = ... AND
vd.sters = 0` si toata lista de coloane din `SELECT` (numele raman identice).
2. Fallback-ul `CREATE CURSOR tvd (...)` (`:214-216`) si duplicatul din `omodificari.vc2` (~14076,
semnalate deja ca duplicare in `rec_review_ancorare_s4.md`) **nu se ating** de aceasta schimbare -
raman neschimbate structural, doar sursa `SELECT`-ului se simplifica.
3. **Opional**, daca se doreste sa se profite de coloana noua `id_vanzare`: nu e necesar niciun
consum imediat in VFP - grid-ul nu are nevoie de ea (id-ul e deja cunoscut din parametrul functiei).