sync SVN r18197

ROAAUTO 2.5.6: Vizualizare comenzi unificata cu Istoric comenzi (filtre si coloane noi), coloane manopera/materiale si total fara/cu TVA in vizualizare comenzi si facturi; versiune_db 2026_09_23_01.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cfkx1QfeDv987o8x1rAtrr
This commit is contained in:
2026-09-23 22:13:59 +03:00
parent c047ff339a
commit 395e51e5bb
12 changed files with 1528 additions and 155 deletions

View File

@@ -678,11 +678,11 @@ DEFINE CLASS pg_meniu_princ AS pg_meniu OF "..\comun\clase\ofundal.vcx"
ENDPROC ENDPROC
PROCEDURE Page2.Cw4.do_actiune PROCEDURE Page2.Cw4.do_actiune
DO vizualizare_comenzi IN oproceduri_vizualizare.prg DO vizualizare_comenzi IN oproceduri_vizualizare.prg WITH .F.
ENDPROC ENDPROC
PROCEDURE Page2.Cw5.do_actiune PROCEDURE Page2.Cw5.do_actiune
DO vizualizare_ist_comenzi IN oproceduri_vizualizare.prg DO vizualizare_comenzi IN oproceduri_vizualizare.prg WITH .T.
ENDPROC ENDPROC
PROCEDURE Page2.Cw6.do_actiune PROCEDURE Page2.Cw6.do_actiune

File diff suppressed because it is too large Load Diff

View File

@@ -232,7 +232,8 @@ Procedure vizualizare_facturi
Private pcselect,pcschema,pcfiltru,pcorder,pofacturi,llAfiseaza Private pcselect,pcschema,pcfiltru,pcorder,pofacturi,llAfiseaza
Store '' To pofacturi Store '' To pofacturi
pcschema=['NRCRT n(5),ID_LUCRARE N(20),NRORD C(50),DATAI d,NUME c(50),TELEFON C(50),MANOPERA n(20,4),MATERIALE n(20,4),MANOPERA_DEVIZ n(20,4), MATERIALE_DEVIZ n(20,4),'+]+; pcschema=['NRCRT n(5),ID_LUCRARE N(20),NRORD C(50),DATAI d,NUME c(50),TELEFON C(50),MANOPERA n(20,4),MATERIALE n(20,4),MANOPERA_DEVIZ n(20,4), MATERIALE_DEVIZ n(20,4),'+]+;
['ASIGURATOR c(24),INSPECTOR c(24),NR_DOSAR c(40),NRINMAT c(35),NRACT n(14),DATAACT d,VALCTVA n(19,2), ID_PART_REF N(20), PART_REF C(100)'] ['ASIGURATOR c(24),INSPECTOR c(24),NR_DOSAR c(40),NRINMAT c(35),NRACT n(14),DATAACT d,VALCTVA n(19,2), ID_PART_REF N(20), PART_REF C(100),'+]+;
['ORE_MANOPERA n(20,4),VAL_MANOPERA n(20,4),VAL_MATERIALE_ACH n(20,4),VAL_MATERIALE_VZ n(20,4),VALFTVA n(19,2)']
pcorder=[a.dataact,a.nract,a.datai,a.nrord] pcorder=[a.dataact,a.nract,a.datai,a.nrord]
*!* modificare 27.01 *!* modificare 27.01
*!* pcselect=['select row_number() over (partition by a.nrord order by ] + pcorder + [) as nrcrt,'+]+; *!* pcselect=['select row_number() over (partition by a.nrord order by ] + pcorder + [) as nrcrt,'+]+;
@@ -241,7 +242,8 @@ pcorder=[a.dataact,a.nract,a.datai,a.nrord]
*!* ['from ] + gcS + [.dev_validare_comenzi a '+]+; *!* ['from ] + gcS + [.dev_validare_comenzi a '+]+;
*!* ['where 1=2'] *!* ['where 1=2']
pcselect=['select a.nrcrt,a.id_lucrare,a.nrord,a.datai,a.nume,a.telefon,a.manopera,a.materiale,a.manopera_deviz, a.materiale_deviz, a.asigurator,a.inspector,'+]+; pcselect=['select a.nrcrt,a.id_lucrare,a.nrord,a.datai,a.nume,a.telefon,a.manopera,a.materiale,a.manopera_deviz, a.materiale_deviz, a.asigurator,a.inspector,'+]+;
['a.nr_dosar,a.nrinmat,a.nract,a.dataact,a.valctva, a.id_part_ref, a.part_ref '+]+; ['a.nr_dosar,a.nrinmat,a.nract,a.dataact,a.valctva, a.id_part_ref, a.part_ref, '+]+;
['a.ore_manopera, a.val_manopera, a.val_materiale_ach, a.val_materiale_vz, a.manopera + a.materiale as valftva '+]+;
['from auto_facturi_emise a'+]+; ['from auto_facturi_emise a'+]+;
['where 1=2'] ['where 1=2']
@@ -647,17 +649,22 @@ Release pocomenzi
Endproc && validare_comenzi Endproc && validare_comenzi
***************************************************************************************** *****************************************************************************************
Procedure vizualizare_comenzi Procedure vizualizare_comenzi
Lparameters tlIstoric
Private pcselect,pcschema,pcfiltru,pcorder,pocomenzi,llAfiseaza Private pcselect,pcschema,pcfiltru,pcorder,pocomenzi,llAfiseaza
Store '' To pocomenzi Store '' To pocomenzi
If Used('crscomenzi') If Used('crscomenzi')
Use In crscomenzi Use In crscomenzi
Endif Endif
pcschema=['ID_ORDL n(10),ID_LUCRARE n(10),DATAI d,NUME c(50),NRORD c(50),NRINMAT c(35),VALIDAT n(1),ID_TIP N(5),TIP_COMANDA c(50),DATAORAVALID D,'+] +; pcschema=['ID_ORDL n(10),ID_LUCRARE n(10),DATAI d,NUME c(50),NRORD c(50),NRINMAT c(35),VALIDAT n(1),ID_TIP N(5),TIP_COMANDA c(50),DATAORAVALID D,'+] +;
['FACTURAT n(1),DATAFACT d,NRFACT N(14),PROC_TVAV N(10,4), ID_PART_REF N(20), PART_REF C(100), SERIES V(100), KMINT I, ORE_FUNCTIONARE I'] ['FACTURAT n(1),DATAFACT d,NRFACT N(14),PROC_TVAV N(10,4), ID_PART_REF N(20), PART_REF C(100), SERIES V(100), KMINT I, ORE_FUNCTIONARE I,'+] +;
['ORE_MANOPERA N(20,4),VAL_MANOPERA N(20,4),VAL_MANOPERA_FACTURA N(20,4),VAL_MATERIALE_VZ N(20,4),VAL_MATERIALE_ACH N(20,4),VAL_MATERIALE_FACTURA N(20,4),VALFTVA_FACTURA N(20,4),VALCTVA_FACTURA N(20,4),'+] +;
['ASIGURATOR c(40),MARCA c(24),MASINA c(20),INSPECTOR c(40),NR_DOSAR c(40),INCHIS_FORTAT n(1)']
pcselect=['select a.id_ordl,a.id_lucrare,a.datai,a.nume,a.nrord,a.nrinmat,a.validat,a.id_tip,a.tip_comanda,a.dataoravalid,a.facturat,a.datafact,a.nrfact,a.proc_tvav, a.id_part_ref, a.part_ref, '+]+; pcselect=['select a.id_ordl,a.id_lucrare,a.datai,a.nume,a.nrord,a.nrinmat,a.validat,a.id_tip,a.tip_comanda,a.dataoravalid,a.facturat,a.datafact,a.nrfact,a.proc_tvav, a.id_part_ref, a.part_ref, '+]+;
[' a.series, a.kmint, a.ore_functionare '+] + ; [' a.series, a.kmint, a.ore_functionare, '+] + ;
[' from ] + gcS + [.auto_normare_comenzi a where 1=2'] [' a.ore_manopera, a.val_manopera, a.val_manopera_factura, a.val_materiale_vz, a.val_materiale_ach, a.val_materiale_factura, a.val_manopera_factura + a.val_materiale_factura as valftva_factura, a.valctva_factura, '+] + ;
[' a.asigurator, a.marca, a.masina, a.inspector, a.nr_dosar, a.inchis_fortat '+] + ;
[' from auto_istoric_comenzi a where 1=2']
*!* [' from ] + gcS + [.dev_vvalid_comenzi a where 1=2'] *!* [' from ] + gcS + [.dev_vvalid_comenzi a where 1=2']
*!* pcfiltru=[luna=]+Alltrim(Str(gnLuna))+[ and an=]+Alltrim(Str(gnAn)) *!* pcfiltru=[luna=]+Alltrim(Str(gnLuna))+[ and an=]+Alltrim(Str(gnAn))
*!* pcfiltru=[(extract(month from datafact) =]+Alltrim(Str(gnLuna))+[ and extract(year from datafact) =]+Alltrim(Str(gnAn))+[) or (datafact is null )] *!* pcfiltru=[(extract(month from datafact) =]+Alltrim(Str(gnLuna))+[ and extract(year from datafact) =]+Alltrim(Str(gnAn))+[) or (datafact is null )]
@@ -669,7 +676,7 @@ llAfiseaza=.F.
gencursor('pocomenzi','crscomenzi',pcselect,pcfiltru,pcschema,pcorder,llAfiseaza) gencursor('pocomenzi','crscomenzi',pcselect,pcfiltru,pcschema,pcorder,llAfiseaza)
pocomenzi.ca_baza1.afisare() pocomenzi.ca_baza1.afisare()
ofrmviz=Createobject('frm_viz_comenzi') ofrmviz=Createobject('frm_viz_comenzi', m.tlIstoric)
ofrmviz.Show(1) ofrmviz.Show(1)
If Used('crscomenzi') If Used('crscomenzi')
Use In crscomenzi Use In crscomenzi

View File

@@ -1,3 +1,11 @@
<!--
23/09/2026
ROAAUTO - 2.5.6
:,modificare:
Vizualizare comenzi si Istoric comenzi folosesc acelasi ecran (filtre noi: asigurator, inspector, nr. dosar, referinta; coloane noi: asigurator, marca, masina, inspector, nr. dosar, arhivat); in Vizualizare comenzi si Vizualizare facturi s-au adaugat coloanele ore/valoare manopera, valoare materiale (achizitie/vanzare) si total fara/cu TVA, cu totaluri in subsolul gridului.
-->
<!-- <!--
07/08/2026 07/08/2026
ROAAUTO - 2.5.5 ROAAUTO - 2.5.5

View File

@@ -19,8 +19,11 @@ jos.
### Specifice ROAAUTO ### Specifice ROAAUTO
(niciunul încă — primele insight-uri de proiect au fost, până acum, toate transversale și au - [vfp_oracle_pack_sesiune.md](vfp_oracle_pack_sesiune.md) — capcană: view-urile (`AUTO_COMENZI_VALIDATE`, `AUTO_VORDL_FACTURI`) își calculează coloanele după luna de lucru din `PACK_SESIUNE`; o interogare din `sqlplus` fără `setluna/setan` întoarce tăcut alte date decât aplicația
migrat în `COMUN/docs/`) - [flux-vizualizare-comenzi.md](flux-vizualizare-comenzi.md) — lanțul ecranului „Vizualizare comenzi": filtru implicit `[1=2]` (cursor gol), filtrul real în `frm_viz_comenzi.do_cauta`; ecranul pereche facturi
- [flux-gccondluna.md](flux-gccondluna.md) — `gcCondLuna` nu e „luna calendaristică", ci luna de lucru plus coada de documente vechi neînchise; cele 6 coloane cerute și capcana de măsurare
- [vederi-auto-comenzi.md](vederi-auto-comenzi.md) — lanțul de view-uri Oracle din spatele ecranelor de comenzi/facturi: `AUTO_ISTORIC_COMENZI`, `AUTO_COMENZI_VALIDATE`, `AUTO_VORDL_FACTURI`, garzi și indexuri
- [tva-valori-manopera-materiale.md](tva-valori-manopera-materiale.md) — cu/fără TVA pe valorile din „Vizualizare comenzi” / „Vizualizare facturi” / facturarea devizelor: devizul și coloanele facturate sunt fără TVA, doar `valctva` e cu TVA
### Partajate (COMUN/docs/, valabile pe toate proiectele ROA*) ### Partajate (COMUN/docs/, valabile pe toate proiectele ROA*)

43
docs/flux-gccondluna.md Normal file
View File

@@ -0,0 +1,43 @@
# `gcCondLuna` — filtrul global „luna de lucru"
## Unde e definit
- `Programe/ovariabile_globale.prg:16` — `PUBLIC gcCondLuna` (`:1`), construită la pornire din
`gnLuna`/`gnAn`. Presupune aliasul `a` pe sursa interogată.
## Ce înseamnă (formularea de la `:16-18`)
Rândul intră dacă:
1. `a.datai` e în luna de lucru (`extract(month)+extract(year)*12 = gnLuna+gnAn*12`), **SAU**
2. `a.datai` e mai vechi **ȘI**:
- `a.inch_validare = 0` → `a.facturat = 0` sau facturat în luna de lucru (`a.datafact`);
- `a.inch_validare = 1` → `a.validat = 0` sau validat în luna de lucru (`a.dataoravalid`).
Deci **nu** e „luna calendaristică": târăște după ea coada de documente vechi încă neînchise.
- `inch_validare` vine din `DEV_TIP_DEVIZ` (per tip de document): 0 = se închide prin facturare,
1 = se închide prin validare.
## Consumatori (doar ecrane de vizualizare/validare)
- `Programe/oproceduri_vizualizare.prg` — `emitere_facturi:64`, `inchidere_regie:131`,
`inchidere_productie:198`, `vizualizare_manopera:528`, `validare_comenzi:620`, plus
`normare_salarii:394` (suprascris imediat cu `[1=2]` la `:397`, deci inert).
- `Programe/oproceduri_devize.prg` — `normare_comanda:236`, `export_comanda_xml:1633`.
- `Clase/odevize.vc2` — `do_cauta:1626`, `:5587`.
- `Clase/oviz_devize.vc2` — `do_cauta:1331`, `do_factureaza_avans:1581`, `do_factureaza_final:2318`,
`do_verifica_part:4486`, `do_cauta:7730`, `:8680`, `:14125`, `frm_viz_comenzi/do_cauta:15333`,
`:19074`.
- ~19 locuri reale.
## Capcane
- **Măsurare**: numărul de rânduri depinde de `validat`/`facturat`, coloane calculate de view-uri
după **luna de sesiune Oracle**. Fără `pack_sesiune.setluna/setan`, `validat` iese 0 peste tot și
filtrul întoarce istoricul. Măsurat AUTOMOTIVE 10/2025: 195 rânduri corect, 32 790 fără sesiune.
Vezi `vfp_oracle_pack_sesiune.md`.
- **Coloane cerute**: `gcCondLuna` referă `a.datai`, `a.inch_validare`, `a.facturat`, `a.datafact`,
`a.validat`, `a.dataoravalid`. Orice sursă nouă pusă sub `gcCondLuna` trebuie să expună toate
șase, altfel `ORA-00904` la căutare. `AUTO_ISTORIC_COMENZI` a primit `inch_validare` abia prin
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\09\ff_2026_09_22_01_AUTO.sql`.

View File

@@ -0,0 +1,65 @@
# Flux: ecranul „Vizualizare comenzi" (unificat: luna curenta + istoric)
## Lanț
- `Programe/oproceduri_vizualizare.prg:651` `Procedure vizualizare_comenzi` `Lparameters tlIstoric`
(`:652`) — **o singura procedura pentru ambele tile-uri**, nu doua separate. `pcschema`/`pcselect`
(`:658-667`) pe `auto_istoric_comenzi a`, cu **+6 campuri** fata de forma veche: `asigurator`,
`marca`, `masina`, `inspector`, `nr_dosar`, `inchis_fortat`. `pcorder = a.datai,a.nrord` (`:674`).
- **Capcană**: `pcfiltru = [1=2]` (`:672`) — cursorul `crscomenzi` se deschide **gol**; gridul se
populează abia la căutarea din formular. Neschimbat fata de forma veche.
- `gencursor('pocomenzi','crscomenzi',...)` (`:676`) → `pocomenzi.ca_baza1.afisare()` (`:677`) →
`Createobject('frm_viz_comenzi', m.tlIstoric)` (`:679`) → `.Show(1)` (`:680`).
- Tile-uri (`Clase/ofundal_dev.vc2`): `Page2.Cw4.do_actiune` (`:681`) `DO vizualizare_comenzi ...
WITH .F.` (`nid_cw=5`, luna curenta), `Page2.Cw5.do_actiune` (`:685`) `WITH .T.` (`nid_cw=6`,
istoric). Drepturile pe cele doua tile-uri raman separate (nid_cw diferit).
- Formular: `Clase/oviz_devize.vc2:14503` (`DEFINE CLASS frm_viz_comenzi`). Proprietate `lIstoric`
(`*p: listoric`, `:14590`), primita in `Init(tlIstoric)` — controleaza titlul (ISTORIC /
VIZUALIZARE COMENZI) si filtrul de mai jos.
- `frm_viz_comenzi.do_cauta` (`Clase/oviz_devize.vc2:15667`) — **aici** se bifurca cele doua moduri
si se construieste filtrul real:
- `lcFiltru = Iif(Thisform.lIstoric, [2=2], gcCondLuna)` (`:15679`) — istoricul vede tot, modul
"luna curenta" ramane limitat la `gcCondLuna`;
- + filtrele bifate: `ck_datai` (`:15681`), `ck_nrinmat` (`:15685`), `ck_nrord` (`:15689`),
`ck_nume` (`:15693`), `ck_asigurator` (`:15697`), `ck_inspector` (`:15701`), `ck_nr_dosar`
(`:15705`), `ck_series` (`:15709`), `ck_referinta` (`:15738`) — **ultimii 4 (asigurator,
inspector, nr_dosar, referinta) sunt noi**, nu existau in forma veche de "luna curenta";
- + `and a.id_tip = ...` dacă s-a ales un tip (`:15713`);
- + `and a.validat = 0/1` după `cbValidat` (`:15718-15722`);
- + `and a.inchis_fortat = 0/1` după `cbArhivat` (`:15724-15729`);
- apoi `Thisform.actualizeaza_grid1(lcFiltru)`.
- `actualizeaza_grid1` — pune `pocomenzi.ca_baza1.cfiltru`, reapelă `afisare()`, cu `save_grid` /
`restore_grid`.
- Coloane noi, adaugate **la coada** grid-ului (`Column22-27`, `:15021-15054`): `cAsigurator`,
`cMarca`, `cMasina`, `cInspector`, `cNr_dosar`, `cArhivat` (`IIF(inchis_fortat=1,'Da','Nu')`).
- `Cmd_sterge1`/`do_sterge` exista in clasa (`:14858`, `:15982`) dar `Visible = .F.` (`:14865`) —
butonul de stergere ramane ascuns, ca in fosta forma de istoric; activarea lui e o decizie
separata, netratata de unificare.
## Capcană: forma unificata e deschisa de `vizualizare_comenzi`, nu de `vizualizare_ist_comenzi`
`vizualizare_ist_comenzi` (`Programe/oproceduri_vizualizare.prg:445`) si clasa
`frm_istoric_comenzi` **raman inca in cod dar nu mai sunt apelate din niciun tile** — cautarea unei
proceduri "de istoric" dupa nume duce la codul gresit. Cod mort, de sters.
## Valorile implicite ale combo-urilor (contează la orice măsurătoare)
| combo | implicit | efect în `do_cauta` |
|---|---|---|
| `cbArhivat` | `"Active"` (`Clase/oviz_devize.vc2:14453`) | mereu `and a.inchis_fortat = 0` (`:15726`) |
| `cbValidat` | `"<Toate>"` (`:14471`) | nimic |
| `cbtip_deviz` | `"<Toate tipurile>"` (`:65`, clasa `ctip_deviz`) | nimic |
## Ecranul pereche „Vizualizare facturi"
- `Programe/oproceduri_vizualizare.prg:231` `Procedure vizualizare_facturi` — sursa
`auto_facturi_emise a` (`:247`); `pcFiltru = [1=2]` (`:253`), deci din nou cursor gol.
- Filtrul real e în `frm_viz_facturi.do_cauta` (`Clase/oviz_devize.vc2:17795`) și **nu** folosește
`gcCondLuna` (linia e comentată la `:17800`), ci `extract(month from dataact)=gnLuna` +
`extract(year from dataact)=gnAn` (`:17799`) + checkbox-uri; `actualizeaza_grid1` (`:17837`).
- Formular: `Clase/oviz_devize.vc2:16936` (`DEFINE CLASS frm_viz_facturi`).
## Editare de grid
- Coloane noi **doar la coadă** — preferințele de grid (`gridprefs.tmp` din GridExtras) se aplică
pozițional; o coloană inserată la mijloc mută toate preferințele salvate.

View File

@@ -3,23 +3,62 @@
Cercetare + plan. Data: 22.09.2026. Dovezile de plan/IO sunt luate pe schema `MARIUSM_AUTO` de pe Cercetare + plan. Data: 22.09.2026. Dovezile de plan/IO sunt luate pe schema `MARIUSM_AUTO` de pe
`ROA_CENTRAL`. `ROA_CENTRAL`.
## 0. Stare — predare către o sesiune nouă ## 0. Stare — 22.09.2026, implementat integral (pașii 1-4 + 6), în așteptare de review
**Acesta este fișierul de implementat.** Planul e la §5, aprobat de Marius pe 22.09.2026. **Acesta este fișierul de implementat.** Planul e la §5, aprobat de Marius pe 22.09.2026.
- **Nimic implementat.** Zero fișiere de cod atinse, zero scripturi rulate pe Oracle, zero commit-uri. - **Pas 1 — baza de date: SCRIS ȘI RULAT pe `MARIUSM_AUTO` de pe `ROA_CENTRAL`** (aprobat de Marius).
`git status` are doar fișiere noi în `docs/`. `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\09\ff_2026_09_22_01_AUTO.sql`, cu antet de comentarii care
- **Nimic într-o stare periculoasă**: fără editări de binar fără write-back, fără tranzacții deschise, explică ce s-a modificat față de versiunile anterioare ale celor două view-uri.
fără procese rămase vii, fără date de test consumate. ASCII, CRLF, se încheie cu `UpdateVersiune` + `commit`.
- **Primul pas într-o sesiune nouă**: `git_sync.ps1` (obligatoriu la început de sesiune), apoi §5 pas 1. Dovadă: „View created" ×2, `VERSIUNE` conține `ff_2026_09_22_01_AUTO.sql`, toate cele 5 coloane noi
- **Decizii deja luate, nu le relua**: §4 varianta 1 (ecranul de comenzi trece pe există în `USER_TAB_COLUMNS`, zero obiecte `AUTO_*` invalide.
`AUTO_ISTORIC_COMENZI`, nu se modifică `AUTO_NORMARE_COMENZI`); manopera se livrează în ambele **Nepublicat încă** la clienți (`publicare_scripturi.ps1` nu a fost rulat).
forme (deviz + facturat); costul se ia din `RUL.PRET`, nu din `VANZARI_DETALII.PRET_ACHIZITIE`. - **Pas 2 — cursoarele VFP: FĂCUT.** `Programe/oproceduri_vizualizare.prg` — `vizualizare_comenzi`
- **Interzis**: să atingi `AUTO_NORMARE_COMENZI` (§4); să inserezi coloane noi la mijlocul gridurilor trecut pe `auto_istoric_comenzi` (+6 coloane), `vizualizare_facturi` +4 coloane.
(§6.1); să rulezi scriptul de bază fără cererea explicită a lui Marius (§5 pas 1); să dai commit - **Pas 3 — gridurile: FĂCUT, cu write-back pe binar.** `Clase/oviz_devize.vc2` — `frm_viz_comenzi`
fără ca Marius să vadă întâi diff-ul complet. `ColumnCount` 13→19, `frm_viz_facturi` `ColumnCount` 12→16, coloane noi **la coadă**.
- **Rămâne de aflat de la client** (§7.1-7.3): rânduri + timp actual pe luna curentă la baza cea mai - **Pas 4 — totalurile de sub gridul de facturi: FĂCUT.** 4 containere `clb_tx_simplu` noi
mare, dimensiunile `RUL`/`ACT`/`DEV_OPER`, existența `IDX_RUL_001`. Nu blochează pașii 1-3. (`Clb_ore_manopera`, `Clb_val_manopera`, `Clb_val_mat_ach`, `Clb_val_mat_vz`) pe două rânduri sub
cele existente, `frm_viz_facturi.Height` 497→560, iar `refreshdata` însumează cele 4 coloane cu
`Nvl(...,0)` și garda `nrcrt=1`.
- **Pas 5 (raportul `rap_facturi_clienti`) — NEFĂCUT**, opțional: `.frx` se editează doar în IDE-ul VFP.
- **Pas 6 — testat pe bază: 7 PASS / 1 FAIL.** Raport: `docs/review/teste_coloane_manopera_piese_viz.md`.
Rularea efectivă a ecranelor în VFP rămâne de făcut (necesită IDE).
- **Necomis.** Diff-ul complet: `docs/review/diff_coloane_manopera_piese_viz.patch`.
### Ce au arătat testele (rezumat)
- **Riscul principal e eliminat**: mutarea sursei ecranului de comenzi **nu schimbă setul de
comenzi afișate** — `AUTO_NORMARE_COMENZI` și `AUTO_ISTORIC_COMENZI` întorc exact aceleași 375 de
`ID_LUCRARE` (0 diferențe în ambele sensuri), iar cu filtrul `gcCondLuna` aplicat, exact aceleași
179 de rânduri. `INCH_VALIDARE` coincide cu `DEV_TIP_DEVIZ` și cu `AUTO_NORMARE_COMENZI`, 0 NULL.
- Cele 4 coloane noi din `AUTO_FACTURI_EMISE` sunt **identice** cu omoloagele din
`AUTO_ISTORIC_COMENZI` pe toate cele 131 de `ID_LUCRARE` comune.
- Garda `id_lucrare > 0` este necesară și funcționează: `RUL` are 6 597 de rânduri cu
`ID_LUCRARE = 0`, iar view-urile nu întorc niciunul.
- **NULL-urile sunt frecvente** (§6.6 de mai jos) — orice sumă/afișare are nevoie de `Nvl`.
- **§3.2 se confirmă pe producție, se infirmă pe dev.** Pe schema de test (`RUL` = 10 374 rânduri)
optimizatorul dez-corelează subinterogările și face `TABLE ACCESS FULL` pe `RUL` — de aici „T8
FAIL". **Pe producția clientului AUTOMOTIVE (`RUL` = 571 508 rânduri) planul folosește
`INDEX RANGE SCAN IDX_RUL_001`**, corelat, exact cum prezicea §3.2; la fel manopera, pe
`IDX_ORDL_00001` + `IDX_OPER_01`. Deci T8 era un artefact al volumului mic.
- ~~Dar apare o problemă mai mare: ecranul întoarce 32 790 de rânduri, +28 % timp~~ — **RETRAS
23.09.2026**, măsurătoare invalidă (lipsea `pack_sesiune.setluna/setan`). Real: **164 de
rânduri, ~3.3 s, +0.4 s de la coloanele noi**. Vezi §7 și `docs/vfp_oracle_pack_sesiune.md`.
- Cost I/O pe schema de test: 642 → 1 207 `consistent gets` (**1.88×**) pentru aceleași 179 de rânduri.
### Ce e de reținut pentru sesiunile următoare
- **Capcană FoxBin2Prg**: blocurile `ADD OBJECT '<grid>.<coloana>.<control>'` trebuie scrise în
**ordine alfabetică** (case-insensitive) în `.vc2`; altfel `txt2vcx.ps1` cade la fidelity-check.
Ordinea canonică se citește din `<staging>\verify\*.vc2` — fișierul acela e chiar editarea ta
rescrisă canonic, deci se poate adopta ca sursă.
- **Decizii deja luate, nu le relua**: §4 varianta 1; manopera în ambele forme (deviz + facturat);
costul din `RUL.PRET`, nu din `VANZARI_DETALII.PRET_ACHIZITIE`.
- **Interzis**: să atingi `AUTO_NORMARE_COMENZI` (§4); coloane noi la mijlocul gridurilor (§6.1);
să publici scriptul la clienți fără cererea explicită a lui Marius; commit fără ca Marius să vadă
diff-ul.
- Conectare la Oracle de dev: vezi `COMUN\docs\conventie_mediu_oracle.md` §4. - Conectare la Oracle de dev: vezi `COMUN\docs\conventie_mediu_oracle.md` §4.
- `docs/handoff_comenzi_luna_curenta.md` și `docs/handoff_cost_materiale_manopera.md` sunt predări de - `docs/handoff_comenzi_luna_curenta.md` și `docs/handoff_cost_materiale_manopera.md` sunt predări de
subagenți, integral acoperite de acest document — de ignorat sau de șters. subagenți, integral acoperite de acest document — de ignorat sau de șters.
@@ -343,22 +382,74 @@ din text). La comenzi, `do_listare` (`:15381`) nu atinge gridul — nimic de fă
nefacturate/nevalidate** (`Programe/ovariabile_globale.prg:16`). Asta e sursa reală a comenzilor nefacturate/nevalidate** (`Programe/ovariabile_globale.prg:16`). Asta e sursa reală a comenzilor
„foarte vechi" — dar, cum s-a arătat la 3.2, vechimea nu scumpește subinterogările. „foarte vechi" — dar, cum s-a arătat la 3.2, vechimea nu scumpește subinterogările.
## 7. De verificat înainte de implementare 6. **Planul de execuție măsurat pe `MARIUSM_AUTO` nu spune nimic despre client — și greșește în
ambele sensuri.** Plătită pe 22.09.2026, măsurând aceeași interogare pe dev și pe producția
AUTOMOTIVE:
- pe dev (`RUL` = 10 374 rânduri) optimizatorul **dez-corelează** subinterogările scalare
(unnesting) într-un `GROUP BY` global și face `TABLE ACCESS FULL` pe `RUL` — concluzia ar fi
fost „indexul nu se folosește, e periculos";
- pe producție (`RUL` = 571 508 rânduri) aceeași interogare păstrează subinterogările corelate
și folosește `INDEX RANGE SCAN IDX_RUL_001` — exact invers.
1. **La clientul cu cea mai mare bază**: câte rânduri întoarce azi „Vizualizare comenzi" pe luna Costul subinterogărilor corelate se înmulțește cu numărul de rânduri afișate
curentă, și cât durează deschiderea acum. Fără numărul ăsta, procentele de la 3.4 nu spun nimic (~16 buffer gets/rând), deci și numărul acela trebuie luat de la client.
despre experiența reală.
2. Dimensiunile reale ale `RUL`, `ACT`, `DEV_OPER` la acel client. **Regulă**: orice afirmație despre plan sau cost pentru o interogare cu subinterogări corelate
3. Există `IDX_RUL_001 (ID_LUCRARE, STERS)` și la client? Aproape sigur da (creat în 2009, folosit se verifică pe un client real, nu pe `MARIUSM_AUTO`. Două lucruri trebuie luate de la client,
cu hint în `pack_auto` în 2026), dar merită confirmat cu o interogare pe `USER_INDEXES` la nu de pe dev: **forma planului** (corelat vs dez-corelat) și **numărul de rânduri returnate**.
clientul respectiv. Dacă lipsește, ăsta e **singurul** caz în care apare cu adevărat scanarea pe
toată baza de care te temeai — și se rezolvă cu un `CREATE INDEX`, nu cu rescrierea logicii. 7. **`gcCondLuna` nu înseamnă „luna curentă".** Include și comenzile vechi nefacturate
4. ~~Poate o lucrare să aibă mai multe `dev_ordl`?~~ **Închis**: Marius a confirmat — o (`inch_validare=0`) sau nevalidate (`inch_validare=1`). La AUTOMOTIVE, luna 10/2025: 107 comenzi
`NOM_LUCRARI` are exact un `DEV_ORDL`. Deschide varianta 2 ca optimizare ulterioară. ale lunii + 88 vechi = **195 de rânduri** (164 după filtrul implicit „Active") — deci coada
5. ~~„Valoare manoperă" = deviz sau facturat?~~ **Închis**: se livrează amândouă, ca în „Istoric veche e mică aici, dar numărul trebuie măsurat, nu presupus. **Atenție**: se măsoară doar cu
comenzi" — `VAL_MANOPERA` (din `DEV_OPER`, `timpn*pret`) și `VAL_MANOPERA_FACTURA` (cont 704 din `pack_sesiune.setluna/setan` inițializate (`docs/vfp_oracle_pack_sesiune.md`); altfel `validat`
`ACT`), respectiv `VAL_MATERIALE_VZ` și `VAL_MATERIALE_FACTURA`. La comenzile încă nefacturate iese 0 peste tot și numărul sare la 32 790.
există doar prima; la cele facturate, diferența dintre ele e chiar semnalul util.
## 7. Verificat pe producție (AUTOMOTIVE, 22-23.09.2026) — închis
Măsurat prin tunel SSH, strict read-only. Detalii și planuri:
`docs/review/teste_coloane_manopera_piese_viz.md`, secțiunea „Teste pe PRODUCTIE".
> **Corectat 23.09.2026.** Măsurătoarea din 22.09 (32 790 rânduri / ~50 s) era **invalidă**:
> rulată din `sqlplus` fără inițializarea lunii de lucru. Vezi
> `docs/vfp_oracle_pack_sesiune.md`. Cifrele de mai jos sunt cele refăcute corect.
1. **Câte rânduri întoarce „Vizualizare comenzi" pe luna curentă și cât durează?**
Cu luna de lucru 10/2025 inițializată (`pack_sesiune.setluna/setan`, exact ce face aplicația la
login): **195 de rânduri** cu filtrul `gcCondLuna` gol, **164** cu filtrul implicit al
formularului (`cbArhivat = "Active"` → `inchis_fortat = 0`, `Clase/oviz_devize.vc2:15630`).
**~3.3 s prin tunel.** Ecranul nu e greu la acest client.
2. **Dimensiunile reale**: `ACT` 833 257, `RUL` 571 508, `DEV_OPER` 137 285, `DEV_ORDL` 38 609.
`RUL` are 215 269 de rânduri cu `ID_LUCRARE = 0` (161 259 cu `STERS = 0`) — garda
`id_lucrare > 0` nu e teoretică, chiar ține la distanță 161 de mii de rânduri.
3. **`IDX_RUL_001` există la client?** **Da**, `NORMAL NONUNIQUE (ID_LUCRARE, STERS)`, și **este
folosit** de planul formei noi. Nu e nevoie de `CREATE INDEX`.
4. ~~Poate o lucrare să aibă mai multe `dev_ordl`?~~ **Închis**: exact unul.
5. ~~„Valoare manoperă" = deviz sau facturat?~~ **Închis**: se livrează amândouă.
### 7.6 Costul măsurat pe producție, pe filtrul real (refăcut 23.09.2026)
Aceeași sesiune, luna de lucru 10/2025 inițializată, filtrul implicit al formularului
(`inchis_fortat = 0`), 164 de rânduri, două rulări fiecare, scăzut overhead-ul de conectare:
| Variantă | timp net |
|---|---|
| fără coloanele noi | 3.3 s |
| cu cele 6 coloane noi | 3.7 s |
| raport | **×1.13 (+0.4 s)** |
Prin tunel SSH; în LAN-ul clientului, mai puțin. Costul scalează cu **numărul de rânduri
afișate** (~16 buffer gets/rând), deci diferența rămâne mică atâta timp cât ecranul întoarce
sute, nu zeci de mii de rânduri.
### 7.7 Ce facem cu asta — decis 23.09.2026
**Nu e nimic de decis.** Problema de performanță (cele 32 790 de rânduri / 50 s) nu există:
era artefactul măsurătorii, nu al datelor. Pe filtrul real ecranul întoarce 164 de rânduri, iar
coloanele noi adaugă ~0.4 s.
Variantele 2 (strângerea filtrului) și 3 (tabelă de totaluri întreținută) **nu se mai justifică**
— nu mai au ce să rezolve. Se merge cu implementarea existentă, la review pe diff.
## 8. Recomandare ## 8. Recomandare

View File

@@ -0,0 +1,130 @@
# Valorile de manoperă / materiale: cu TVA sau fără TVA?
Read-only, din sursa view-urilor Oracle (`D:\ROA\DATABASE\SCRIPTURI_CLAR\`) + codul VFP.
`Clase\oviz_devize.vc2` era editat în paralel — **liniile pot aluneca**, ancorele sigure sunt
numele claselor/procedurilor.
## Răspuns scurt
- Toate valorile de **deviz** (`val_manopera`, `ore_manopera`, `val_materiale_ach`,
`val_materiale_vz`) sunt **FĂRĂ TVA**.
- Coloanele **facturate** `val_manopera_factura` / `val_materiale_factura` (și `manopera`,
`materiale` din `AUTO_FACTURI_EMISE`) sunt **FĂRĂ TVA** — vin din conturi de venit nete
(704, 707/419).
- **Doar** `valctva` / `valctva_factura` / „Total facturi (cu TVA)" / „Valoare cu TVA" este
**CU TVA** = manoperă + materiale + 4427.
## Tabel
| valoare | sursă | cu/fără TVA | formulă | fișier:linie |
|---|---|---|---|---|
| `ore_manopera` | `DEV_ORDL` ⋈ `DEV_OPER` | n/a (ore) | `sum(b1.timpn)` | `AUTO_ISTORIC_COMENZI` `2026/09/ff_2026_09_22_01_AUTO.sql:55`; `AUTO_FACTURI_EMISE` `:145` |
| `val_manopera` | `DEV_OPER.PRET * TIMPN` | **fără TVA** | `sum(round(b1.timpn*b1.pret,2))` | view `2026/09/ff_2026_09_22_01_AUTO.sql:56` / `:146` |
| `DEV_OPER.PRET` | scris la facturare din totalul **fără TVA** | **fără TVA** | `V_PRET := tnTotalFTva / tnTimpN` | `PACK_AUTO.dev_adauga_oper_fact` `2026/03/ff_2026_03_31_02_AUTO_PACK_AUTO.sql:392,415`; apelat cu `?pnTotalFTva` din `Programe/oproceduri_devize.prg:801` |
| `DEV_OPER.PRET` (adaugare manuală) | `auto_vpreturi.pret` (tarif orar) | **fără TVA** | `Thisform.npret` = `v_preturi.pret` | `Clase/odevize.vc2:947,1082`; `auto_vpreturi` = `dev_nom_preturi` `2013/07/ff_2013_07_24_02_AUTO.sql:930`; DDL fără coloană TVA `Scripturi_instalare/tabele.sql:495` |
| `val_materiale_ach` | `RUL.PRET` (cost lot FIFO) | **fără TVA** | `sum(round(pret*cante,2))` | view `2026/09/ff_2026_09_22_01_AUTO.sql:53` / `:143` |
| `RUL.PRET` | `STOC.PRET` | **fără TVA** (cost) | `V_PRET := tab_stoc(i).PRET` | `PACK_FACTURARE.descarca_gestiune` `2026/09/ff_2026_09_16_04_COMUN_PACK_FACTURARE.sql:8975` |
| `val_materiale_vz` | `RUL.PRETV` (preț vânzare) | **fără TVA** | `sum(round(pretv*cante,2))` | view `2026/09/ff_2026_09_22_01_AUTO.sql:54` / `:144` |
| `RUL.PRETV` | `STOC.PRETV`; TVA-ul stă separat în `RUL.TVAV` / `RUL.PRETVTVA` | **fără TVA** | `V_PRETV_ORIG := tab_stoc(i).PRETV`; la insert `PRETV, TVAV, PRETVTVA` | `...COMUN_PACK_FACTURARE.sql:8977` și `:10491-10493` |
| `val_manopera_factura` | `AUTO_VORDL_FACTURI.valfactmanopera` = `MV_ORDL_SUME_ACT.manopera_ron/rol` | **fără TVA** | cont **704** | `2025/06/ff_2025_06_30_01_AUTO.sql:9-12`; MV `2013/12/ff_2013_12_09_02_AUTO.sql:50` |
| `val_materiale_factura` | `MV_ORDL_SUME_ACT.materiale_ron/rol` | **fără TVA** | cont **707, 419** | `2025/06/ff_2025_06_30_01_AUTO.sql:16-18`; MV `2013/12/ff_2013_12_09_02_AUTO.sql:68` |
| `valctva` / `valctva_factura` | `MV_ORDL_SUME_ACT` | **CU TVA** | `manopera + materiale + tva` | `2025/06/ff_2025_06_30_01_AUTO.sql:23-26` |
| `...tva_ron` (componenta TVA) | `MV_ORDL_SUME_ACT` | CU TVA | cont **4427 sau 4428** (TVA la încasare) | `2026/09/ff_2026_09_23_01_AUTO.sql`; înainte doar 4427 (`2013/12/ff_2013_12_09_02_AUTO.sql:86`) |
| `manopera`, `materiale` (`AUTO_FACTURI_EMISE`) | `MV_ORDL_SUME_ACT` (704 / 707,419) | **fără TVA** | `b.manopera_ron/rol`, `b.materiale_ron/rol` | `2026/09/ff_2026_09_22_01_AUTO.sql:119-132` |
| totaluri sub grid „Vizualizare facturi" | `crsfacturi` (`AUTO_FACTURI_EMISE`) | mixt | `clb_valctva`=Sum(valctva) **cu TVA**; `clb_manopera`/`clb_materiale`=Sum(manopera/materiale) WHERE `nrcrt=1` **fără TVA** | `Clase/oviz_devize.vc2` proc `frm_viz_facturi.refreshdata` (~`:17995`) |
Garda `MV_ORDL_SUME_ACT`: `scd in ('4111','667','482','711','6588')` și
`id_set in (31001..31007, 31011..31013)` (`2013/12/ff_2013_12_09_02_AUTO.sql:238-243`), definit
ca materialized view *fast refresh on commit* cu fallback pe view (`:39-45`).
## Observația „Total facturi (cu TVA) = val_manopera_factura + val_materiale_factura"
**Componentele nu conțin TVA.** `valctva = manopera + materiale + tva_ron`, deci egalitatea cu
`manopera + materiale` înseamnă `tva_ron = 0`.
**Cauza, măsurată pe date: firma are TVA la încasare** (`calendar.tva_incasare = 1`). Pe aceste
firme TVA-ul facturii se înregistrează `4111 → 4428` (neexigibil), nu `4111 → 4427`. Până la
`ff_2026_09_23_01_AUTO`, `MV_ORDL_SUME_ACT.tva_ron` însuma **doar `scc = '4427'`**, deci ieșea 0,
iar coloanele/totalurile „cu TVA" afișau **netul**. Afirmația anterioară din acest doc („eticheta
este corectă chiar și atunci") era dedusă doar din sursă și era **greșită**.
Dovada (`MARIUSM_AUTO`, factura 1159, `id_lucrare` 131): `4428` TVA MANOPERA 147.82 +
TVA MATERIALE 180.91 = 328.73 = 21 % din 1 565.37 (manopera 703.89 + materiale 861.48);
`tva_ron` era 0. În 2026: 97 linii `4111 → 4427`, 574 linii `4111 → 4428`.
**Fixul** (`2026/09/ff_2026_09_23_01_AUTO.sql`, aplicat pe `MARIUSM_AUTO`, nepublicat):
- `tva_ron`/`tva_rol` (și `cnt_`) însumează `scc in ('4427','4428')`;
- liniile `DISCOUNT MANOPERA%` / `DISCOUNT MATERIALE%` cu `scc = '4428'` (TVA-ul discountului)
**nu se mai scad din net** — garda era `scc <> '4427'`, deci pe TVA la încasare manopera și
materialele ieșeau subevaluate cu TVA-ul discountului (ex. `id_lucrare` 103: manopera 97.58 în
loc de 99.58, materiale 234.58 în loc de 240.41).
**Nu se dublează TVA-ul la încasare**: nota de exigibilizare e `4428 → 4427` (`scd = '4428'`),
exclusă de filtrul `scd in ('4111','667','482','711','6588')`. Verificat pe date.
## Capcane
- **Asimetrie de deduplicare** în `frm_viz_facturi.refreshdata`: `valctva` se însumează pe
**toate** rândurile `crsfacturi`, iar `manopera`/`materiale` doar pe `nrcrt=1`. Dacă un `nrord`
are >1 rând (mai multe `id_set`/`nact` în `MV_ORDL_SUME_ACT`), totalul „cu TVA" poate fi umflat
față de restul coloanelor — nu trage concluzii din diferența dintre totaluri fără verificare.
- `proc_tvav` (coloana `DEV_ORDL.PROC_TVAV`, expusă prin `AUTO_COMENZI_VALIDATE` →
`AUTO_ISTORIC_COMENZI.proc_tvav`; DDL view `2024/07/ff_2024_07_03_01_AUTO.sql:192`) este
**multiplicatorul TVA pe comandă** (`1 + cota/100`). TVA se calculează ca
`valoare * (proc_tvav - 1)` (ex. `Clase/oviz_devize.vc2:2355`). Când `proc_tvav = 1`
(scutit / taxare inversă), „cu TVA" == „fără TVA". Se stabilește la crearea comenzii și se
actualizează la validare/facturare (`Programe/oproceduri_vizualizare.prg:285-288`). **Nu** este
o opțiune de firmă.
- **Opțiunea „prețuri cu TVA"** există, dar nu e de firmă: `CRM_POLITICI_PRETURI.PRETURI_CU_TVA`
(per politică de preț), citită în `COMUN/programe/ofacturare_comun.prg:2425-2431` și
`COMUN/clase/ointroduceri.vc2:16270`, propagată pe linii ca `VANZARI_DETALII.PRET_CU_TVA` /
`cu_tva` (modulele comenzi/facturare articole). **Nu schimbă cele trei ecrane**: `RUL` ține
mereu prețul net (`PRETV`) și cel cu TVA (`PRETVTVA`) în coloane separate, iar veniturile
contabile sunt nete. `gnTipPret` nu a fost găsit în cod.
- `DEV_OPER.PRET` la corecția unor luni vechi: `pack_devize.dev_actualizeaza_operatie`
înmulțește prețul cu `10000` la trecerea ROL→RON (2005), fără legătură cu TVA
(`Scripturi_instalare/packages.sql:393-398`).
- `MV_ORDL_SUME_ACT` și `AUTO_VORDL_FACTURI` depind de luna de lucru din `PACK_SESIUNE`
(`vederi-auto-comenzi.md`, `vfp_oracle_pack_sesiune.md`) — o citire din `sqlplus` fără
`setluna/setan` întoarce tăcut alte date.
## Ecranul „Facturarea devizelor"
Clasa `frm_emitere_facturi` (`Clase/oviz_devize.vc2:505`), deschisă din
`Programe/oproceduri_vizualizare.prg:74` (`emitere_facturi`); procedurile `do_factureaza_avans`
(`:1527`) și `do_factureaza_final` (`:2226`). Afișează „Manopera"/„Materiale" (nete), „Avans cu
TVA facturat", „Total deviz cu TVA", „Total discount cu TVA", „Total factura", „TVA manopera",
„TVA materiale". Manopera facturată se scrie în `DEV_OPER.PRET` ca **total fără TVA / ore**
(`Programe/oproceduri_devize.prg:801` → `2026/03/ff_2026_03_31_02_AUTO_PACK_AUTO.sql:415`).
Prețul „cu TVA" se calculează separat, la nevoie, cu `pack_sesiune.calculeaza_pret_cu_tva`
(ex. `Clase/oviz_devize.vc2:2361`) — folosit la bonul fiscal detaliat, nu în coloanele de deviz.
## Propunere de etichetare (doar propunere, nu s-a modificat niciun `.vc2`)
`obiect -> caption propus`
**frm_viz_comenzi / grdcomenzi** (`Clase/oviz_devize.vc2`)
- `cValManopera` -> `Valoare manopera (fara TVA)`
- `cValManoperaFactura` -> `Valoare manopera factura (fara TVA)`
- `cValMaterialeVz` -> `Valoare materiale vanzare (fara TVA)`
- `cValMaterialeAch` -> `Valoare materiale achizitie (fara TVA)`
- `cValMaterialeFactura` -> `Valoare materiale factura (fara TVA)`
- `cOreManopera` -> neschimbat (ore, fără noțiune de TVA)
**frm_viz_facturi / grdfacturi + totaluri** (`Clase/oviz_devize.vc2`)
- `cManopera` -> `Manopera (fara TVA)`
- `cMateriale` -> `Materiale (fara TVA)`
- `cValManopera` -> `Valoare manopera (fara TVA)`
- `cValMaterialeAch` -> `Valoare materiale achizitie (fara TVA)`
- `cValMaterialeVz` -> `Valoare materiale vanzare (fara TVA)`
- `clb_manopera` („Manopera fact.") -> `Manopera fact. (fara TVA)`
- `clb_materiale` („Materiale fact.") -> `Materiale fact. (fara TVA)`
- `clb_val_manopera` („Val. manopera") -> `Val. manopera (fara TVA)`
- `clb_val_mat_ach` („Mat. achizitie") -> `Mat. achizitie (fara TVA)`
- `clb_val_mat_vz` („Mat. vanzare") -> `Mat. vanzare (fara TVA)`
- `cValctva` („Valoare cu TVA") și `clb_valctva` („Total facturi (cu TVA)") -> neschimbate (corecte)
**frm_emitere_facturi** („Facturarea devizelor", `Clase/oviz_devize.vc2:505`)
- „Manopera" / „Materiale" -> `Manopera (fara TVA)` / `Materiale (fara TVA)`
- „Total deviz cu TVA", „Avans cu TVA facturat", „Total factura", „TVA manopera",
„TVA materiale" -> neschimbate (deja explicite)

View File

@@ -0,0 +1,38 @@
# Vederi Oracle: „Vizualizare comenzi" / „Facturi emise"
Căile de mai jos sunt relative la `D:\ROA\DATABASE\SCRIPTURI_CLAR\`.
## Lanțul
| view | definit în | compus din |
|---|---|---|
| `AUTO_COMENZI_VALIDATE` | `2024\07\ff_2024_07_03_01_AUTO.sql:181` | `DEV_ORDL a where a.sters = 0` (`:236`) + `SYN_UTILIZATORI` b/d + `NOM_LUCRARI` c |
| `AUTO_VORDL_FACTURI` | `2025\06\ff_2025_06_30_01_AUTO.sql:4` | `AUTO_VORDL_FACTURATE` + `MV_ORDL_SUME_ACT` |
| `AUTO_ISTORIC_COMENZI` | `2026\09\ff_2026_09_22_01_AUTO.sql:35` | `AUTO_COMENZI_VALIDATE a` + `AUTO_VORDL_FACTURI c` + `DEV_MASINICLIENTI` / `DEV_NOM_MASINI` / `DEV_NOM_MARCI` / `NOM_PARTENERI` / `DEV_NOM_ASIGURATORI` / `DEV_NOM_INSPECTORI` / `DEV_TIP_DEVIZ i` |
| `AUTO_FACTURI_EMISE` | `2026\09\ff_2026_09_22_01_AUTO.sql:100` | `AUTO_COMENZI_VALIDATE` + `AUTO_VORDL_FACTURATE` + `MV_ORDL_SUME_ACT` + `AUTO_VORDL_MAN` / `AUTO_VORDL_MAT` |
## Note
- `AUTO_COMENZI_VALIDATE`: `validat`, `dataoravalid`, `util_valid`, `dataorainchis`, `util_inchis`
sunt **calculate** față de `pack_sesiune.getluna()/getan()` — motivul capcanei din
`vfp_oracle_pack_sesiune.md`.
- `AUTO_VORDL_FACTURI`: alege coloanele RON vs ROL comparând `pack_sesiune.getan/getluna` cu
`get_anron/get_lunaron`; expune `facturat`, `dataact`, `nract`, `valfactmanopera`,
`valfactmateriale`, `valctva` (redenumite în `AUTO_ISTORIC_COMENZI` în `datafact`, `nrfact`,
`val_manopera_factura`, `val_materiale_factura`, `valctva_factura`).
- `AUTO_ISTORIC_COMENZI` primește `i.inch_validare` abia în `ff_2026_09_22_01_AUTO.sql` — cerut de
`gcCondLuna` (vezi `flux-gccondluna.md`).
- Coloane calculate per rând, prin subinterogări corelate (~16 buffer gets/rând):
`val_materiale_ach` / `val_materiale_vz` din `RUL` (`sters=0 and id_lucrare = a.id_lucrare`);
`ore_manopera` / `val_manopera` din `DEV_ORDL` + `DEV_OPER`.
- **Garda `id_lucrare > 0`** pe `RUL` e obligatorie (`AUTO_FACTURI_EMISE` o are): la AUTOMOTIVE
`RUL` are 215 269 rânduri cu `ID_LUCRARE = 0` (161 259 cu `STERS = 0`) — mișcările de stoc
obișnuite.
- Indexuri de care depind subinterogările: `IDX_RUL_001 (ID_LUCRARE, STERS)`,
`IDX_ORDL_00001 (DEV_ORDL.ID_LUCRARE)`, `IDX_OPER_01 (DEV_OPER.ID_ORDL)`.
- **Capcană de plan**: pe volum mic (`MARIUSM_AUTO`) optimizatorul de-corelează subinterogările și
face `TABLE ACCESS FULL` pe `RUL`; pe volum de producție le păstrează corelate și folosește
`IDX_RUL_001`. Nu trage concluzii de plan de pe dev.
- `AUTO_NORMARE_COMENZI` **nu se modifică** — e folosit în ~10 alte locuri.
- Linia paralelă de produs: `DEVIZE_NORMARE_COMENZI`, `DEVIZE_VALIDARE_COMENZI`, `DEVIZE_VORDL`,
cu același tipar.

View File

@@ -0,0 +1,62 @@
# Capcană: view-urile ROA depind de `PACK_SESIUNE` (luna de lucru)
**Orice măsurătoare sau verificare făcută din `sqlplus` / DSN fără inițializarea lunii de lucru
întoarce alte date decât aplicația — fără nicio eroare.**
## Ce se întâmplă
Mai multe view-uri de bază nu sunt „pure": își calculează coloanele în funcție de starea de
sesiune ținută în pachetul `PACK_SESIUNE`, pe care aplicația o setează la login
(`setluna`, `setan`, `setanbal`, `setlunabal`, `set_data_init/final`, `set_id_util`, `setschema`).
Exemplu — `AUTO_COMENZI_VALIDATE` (baza lui `AUTO_ISTORIC_COMENZI`):
```sql
(case when extract(month from a.dataoravalid) + extract(year from a.dataoravalid) * 12
<= pack_sesiune.getluna() + pack_sesiune.getan() * 12
then 1 else 0 end) as validat
```
Într-o sesiune `sqlplus` proaspătă, `getluna()/getan()` nu sunt setate, comparația e falsă pentru
toate rândurile, deci **`validat` iese 0 peste tot** — și la fel `dataoravalid`, `util_valid`,
`dataorainchis`, `util_inchis`. Același tipar în `AUTO_VORDL_FACTURI` (alege coloanele RON vs ROL
după `getan/getluna` față de `get_anron/get_lunaron`) și în omoloagele `DEVIZE_*`.
## Cât de mult minte
Măsurat pe producția AUTOMOTIVE, 23.09.2026, ecranul „Vizualizare comenzi", luna 10/2025:
| | rânduri întoarse |
|---|---|
| `sqlplus` fără `pack_sesiune` inițializat | **32 790** (din 2006 încoace) |
| cu `setluna(10)/setan(2025)` | **195** (164 cu filtrul implicit „Active") |
Diferența e ×168. Motivul: `gcCondLuna` (`Programe/ovariabile_globale.prg:16`) păstrează rândurile
vechi doar dacă sunt **nevalidate sau nefacturate** — iar fără luna de lucru *totul* pare
nevalidat. Din cele 33 704 comenzi ale clientului, 32 744 sunt de fapt validate.
## Ce se face
Prima comandă din orice script de diagnostic pe o schemă ROA, imediat după conectare:
```sql
begin
<schema>.pack_sesiune.setluna(<luna>);
<schema>.pack_sesiune.setan(<an>);
end;
/
```
(`setluna/setan` sunt setări de sesiune, nu DML — nu încalcă regula „doar SELECT pe producție".)
Verificare rapidă că sesiunea e inițializată corect, înainte de a crede orice cifră:
```sql
select nvl(validat,0) validat, count(*) from <schema>.auto_comenzi_validate
group by nvl(validat,0);
```
Dacă iese **totul pe 0**, sesiunea nu e inițializată — nu interpreta rezultatele.
Vezi și: `roa-oracle-production-access` (lanțul tunel/TNS/DSN),
`COMUN\docs\conexiuni-tunel-ssh-odbc.md`.

View File

@@ -1 +1 @@
2026_03_31_02 2026_09_23_01