sync SVN r18196
This commit is contained in:
156
docs/handoff_cost_materiale_manopera.md
Normal file
156
docs/handoff_cost_materiale_manopera.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# Handoff: cercetare "cost materiale / rulaj + manoperă" (read-only)
|
||||
|
||||
Sarcina (subagent `lane-cost`): găsește și documentează cum se determină azi (a) costul de
|
||||
achiziție al unei piese ieșite pe o comandă/factură și (b) valoarea + orele de manoperă,
|
||||
pentru cererea clientului de a afișa aceste valori în listele de comenzi/facturi. Cercetare
|
||||
READ-ONLY — **niciun fișier din proiect nu a fost modificat.**
|
||||
|
||||
## Stare: COMPLET
|
||||
|
||||
Toate constatările au fost transmise integral către `team-lead` prin două mesaje SendMessage
|
||||
(cu citate exacte de cod și file:line). Acest fișier e doar predarea pe disc, conform REGULA
|
||||
ZERO — pentru cazul în care mesajele s-ar pierde. Nu există lucru neterminat, fișiere editate,
|
||||
tranzacții deschise sau date de test consumate.
|
||||
|
||||
**Important**: în timp ce scriam handoff-ul am găsit că exista deja pe disc
|
||||
[`docs/propuneri_coloane_manopera_piese_viz.md`](propuneri_coloane_manopera_piese_viz.md) —
|
||||
un document mult mai complet (scris cu acces direct la Oracle: `EXPLAIN PLAN`, `autotrace`,
|
||||
măsurători reale pe schema `MARIUSM_AUTO`/`ROA_CENTRAL`), care **acoperă și depășește** tot ce
|
||||
am găsit eu static din cod. Acela e documentul de referință pentru implementare, nu acesta.
|
||||
Constatările mele (fără acces DB, doar citire de cod) coincid cu ale lui la toate punctele
|
||||
verificabile static.
|
||||
|
||||
## Inventar constatări (file:line)
|
||||
|
||||
### 1. Tabelul RUL (rulaj) — coloane relevante
|
||||
Schema cursorului `viz_rulaje`: `COMUN/programe/oproceduri_rulaje.prg:15-25`.
|
||||
`PRET n(16,4)` = preț achiziție/cost per rând de mișcare, `PRETV n(16,4)` = preț vânzare,
|
||||
`CANT`/`CANTE` = cantitate, `COD` = document sursă, `ID_LUCRARE`, `ID_GESTIUNE`, `STERS`.
|
||||
|
||||
### 2. Cost achiziție — DEJA STOCAT pe linia de vânzare/factură (nu recalculat la citire)
|
||||
- Schema cursor linii deviz: `Programe/oproceduri_devize.prg:882` — `pret_achizitie N(20,4)`.
|
||||
- Populat din lotul de stoc consumat: `COMUN/clase/ofacturare.vc2:4233,13131,13511` —
|
||||
`poArticol.pret_achizitie = Pret`.
|
||||
- Scris efectiv prin `pack_facturare.adauga_articol_factura_deviz`
|
||||
(`Programe/oproceduri_devize.prg:1218-1244`).
|
||||
- Persistă și la editare facturi: `COMUN/programe/ofacturare_editare.prg:225,547,652,775,807-817`;
|
||||
schema tabel `vanzari_det`: `COMUN/programe/oproceduri_facturare.prg:378-491,1114-1133`.
|
||||
- Rapoarte care citesc costul direct de pe linie, fără recalcul:
|
||||
`COMUN/programe/oproceduri_rapoarte_fact.prg:579-590` (view `fact_vfacturi_detalii`).
|
||||
|
||||
### 3. Algoritm de determinare a costului la ieșire — FIFO pe LOT, din tabela STOC
|
||||
Sursă (în afara repo-ului git ROAAUTO, în `D:\ROA\DATABASE\SCRIPTURI_CLAR\` — istoric SVN al
|
||||
schemei Oracle COMUN, actualizat curent, ultimul fișier relevant la 2026-09-16):
|
||||
`PACK_FACTURARE.cursor_gestiuni_articol`
|
||||
(`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\09\ff_2026_09_16_04_COMUN_PACK_FACTURARE.sql:4513-4597`).
|
||||
Selectează loturi din **`STOC`** (nu din `RUL`), filtrate pe `LUNA`/`AN`/`ID_ARTICOL`/
|
||||
`ID_GESTIUNE`, cantitate rămasă = `CANTS + CANT - CANTE > 0`, ordonate **`ORDER BY DATAIN`**
|
||||
(FIFO pe data intrării lotului). `PRET` = costul lotului ales, scris o singură dată pe linia
|
||||
de vânzare (punctul 2). Rapoartele nu re-rulează FIFO, doar re-însumează ce s-a scris deja.
|
||||
|
||||
### 4. Manoperă — ore și valoare
|
||||
DDL `DEV_OPER`: `Scripturi_instalare/tabele.sql:674-693` — `TIMPN NUMBER(8,3)` (ore),
|
||||
`PRET NUMBER(17,4)` (tarif orar), `ID_ORDL` (FK spre `DEV_ORDL`, fără index explicit pe
|
||||
`DEV_OPER.ID_ORDL` în DDL). `DEV_ORDL` are index pe `ID_LUCRARE` (`IDX_ORDL_00001`,
|
||||
`Scripturi_instalare/tabele.sql:636`).
|
||||
Valoare manoperă = `TIMPN * PRET`, agregată în raport:
|
||||
`Programe/oproceduri_listari.prg:1608-1621` (`facturi_emise_pe_sectii`).
|
||||
|
||||
### 5. Raportul cerut de client EXISTĂ DEJA — view Oracle `AUTO_ISTORIC_COMENZI`
|
||||
Versiune curentă (ultima modificare găsită, 2025-06-30, nimic mai nou):
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2025\06\ff_2025_06_30_01_AUTO.sql:37-95`.
|
||||
```sql
|
||||
(select sum(round(pret * cante, 2)) from rul where sters = 0 and id_lucrare = a.id_lucrare) as val_materiale_ach,
|
||||
(select sum(round(pretv * cante, 2)) from rul where sters = 0 and id_lucrare = a.id_lucrare) as val_materiale_vz,
|
||||
(select sum(b1.timpn) from dev_ordl a1 left join dev_oper b1 on a1.id_ordl=b1.id_ordl where a1.id_lucrare=a.id_lucrare and a1.sters=0 and b1.sters=0) as ore_manopera,
|
||||
(select sum(round(b1.timpn*b1.pret,2)) from dev_ordl a1 left join dev_oper b1 on a1.id_ordl=b1.id_ordl where a1.id_lucrare=a.id_lucrare and a1.sters=0 and b1.sters=0) as val_manopera,
|
||||
```
|
||||
Subselecte **corelate pe `id_lucrare`** (nu scan fără filtru), susținute de indexul
|
||||
`IDX_RUL_001 on RUL(ID_LUCRARE, STERS)` (creat `D:\ROA\DATABASE\SCRIPTURI\2009\1\ff_2009_01_21_01_GESTIUNI.sql:63`,
|
||||
încă folosit activ cu hint în producție — ultima apariție
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\03\ff_2026_03_31_02_AUTO_PACK_AUTO.sql:711`).
|
||||
Folosit deja în VFP: `Programe/oproceduri_vizualizare.prg:441-457` (`vizualizare_ist_comenzi`),
|
||||
afișat în grid `Clase/oviz_devize.vc2:9585-9607` (`ControlSource`: `val_materiale_ach`,
|
||||
`val_materiale_vz`, `val_materiale_factura`, `val_manopera_factura`, `ore_manopera`).
|
||||
|
||||
### 6. Raportul care CHIAR scanează tot RUL fără scopare pe lucrare (risc real, dar altă bucată de cod)
|
||||
`Programe/oproceduri_listari.prg:1607-1625` (`facturi_emise_pe_sectii`):
|
||||
```sql
|
||||
left join (select sum(round(pret*cante,2)) as valoarea, sum(round(pretv*cante,2)) as valoarev,
|
||||
id_lucrare, id_sectie from rul where sters=0 group by id_lucrare, id_sectie) e
|
||||
on a.id_lucrare = e.id_lucrare and a.id_sectie = e.id_sectie
|
||||
```
|
||||
`GROUP BY` peste tot `RUL` (fără filtru pe `id_lucrare` în where), join-ul pe perioadă se face
|
||||
abia după — spre deosebire de `AUTO_ISTORIC_COMENZI` (punctul 5), care e corelat per lucrare.
|
||||
Acesta e adevăratul candidat de "selecție pe toată baza de date", dacă vreodată devine relevant
|
||||
de optimizat.
|
||||
|
||||
## Ce s-a stabilit deja (să nu se reia)
|
||||
- Costul de achiziție e stocat pe linia de vânzare/factură (`pret_achizitie`), nu recalculat FIFO
|
||||
la fiecare citire — FIFO rulează o singură dată, la facturare, pe tabela `STOC`.
|
||||
- View-ul `AUTO_ISTORIC_COMENZI` deja livrează exact coloanele cerute de client și e deja folosit
|
||||
în ecranul „Istoric comenzi"; documentul de propuneri recomandă copierea acelorași subinterogări
|
||||
în `AUTO_NORMARE_COMENZI`/`AUTO_FACTURI_EMISE` pentru ecranele „Vizualizare comenzi"/"Facturi".
|
||||
- Sursa de adevăr pentru DDL/PL-SQL Oracle (istoric complet de migrări, inclusiv versiuni curente
|
||||
ale pachetelor și view-urilor) NU e în `Scripturi_instalare\` din ROAAUTO, ci în
|
||||
`D:\ROA\DATABASE\SCRIPTURI\` (brut, cronologic) și `D:\ROA\DATABASE\SCRIPTURI_CLAR\` (reformatat) —
|
||||
repo SVN separat, partajat între toate aplicațiile ROA.
|
||||
|
||||
## Interzis / nu s-a făcut
|
||||
Nicio modificare de cod, niciun script Oracle rulat, niciun write-back `.vc2`/`.sc2`. Cercetare
|
||||
pur read-only, conform mandatului primit.
|
||||
|
||||
## Runda 2 — întrebări punctuale de la team-lead (trimise, nu doar aici)
|
||||
Sursă: `PACK_FACTURARE.descarca_gestiune`, în
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\09\ff_2026_09_16_04_COMUN_PACK_FACTURARE.sql` (versiune
|
||||
curentă, 2026-09-16).
|
||||
|
||||
1. **`RUL.PRET` la ieșire — SIGUR**: nu se recalculează în `descarca_gestiune`. Procedura primește
|
||||
`V_PRET_ACHIZITIE IN NUMBER` ca parametru, selectează din `STOC` exact lotul cu acel preț
|
||||
(`AND A.PRET = V_PRET_ACHIZITIE`, linia 8766 și analog 8659/8899/10642), apoi
|
||||
`V_PRET := tab_stoc(i).PRET` (linia 8975) și `V_PRET as PRET` în `INSERT INTO RUL_TEMP`
|
||||
(linia 9456). FIFO-ul (alegerea lotului) se face separat, mai devreme, în
|
||||
`cursor_gestiuni_articol` (`ORDER BY DATAIN`, raportat runda 1).
|
||||
**Incert**: n-am găsit niciun `INSERT INTO RUL` literal (fără `_TEMP`) în acest fișier — nu am
|
||||
urmărit cum `RUL_TEMP` ajunge fizic în `RUL`. Nu schimbă răspunsul (valoarea `PRET` e fixată la
|
||||
`V_PRET` oricum), dar rămâne un gol de investigat dacă cineva vrea firul complet.
|
||||
2. **RUL pe `id_lucrare` = doar piese, niciodată manoperă — SIGUR**: gardă la intrarea în
|
||||
`descarca_gestiune` (liniile 8264-8270):
|
||||
```sql
|
||||
SELECT MAX(IN_STOC) INTO lnInStoc FROM NOM_ARTICOLE WHERE ID_ARTICOL = V_ID_ARTICOL;
|
||||
if lnInStoc = 0 then GOTO SFARSIT; end if;
|
||||
```
|
||||
Articolele cu `IN_STOC=0` (servicii/manoperă) nu ajung niciodată să scrie în `RUL_TEMP`/`RUL`.
|
||||
Replicat pe VFP prin `gestionabil = Iif(Nvl(in_stoc,0)<>0,1,0)`
|
||||
(`COMUN/programe/ofacturare_editare.prg:242`).
|
||||
3. **`CANTE` vs `CANT` — SIGUR**: `CANTE`=ieșire, `CANT`=intrare, din formula soldului
|
||||
`CANTS+CANT-CANTE` (folosită consecvent, ex. `cursor_gestiuni_articol`). La retur (ramura
|
||||
`WHEN pack_facturare.ntip IN (8,9)` din `descarca_gestiune`, ~linia 8355) nu se folosesc
|
||||
cantități negative — ieșirea originală (`a.cante`) devine `cant` (intrare) pe rândul nou:
|
||||
`SELECT 1 as tip, ..., a.cante as cant, 0 as cante, ... FROM RUL A ... WHERE A.CANTE<>0`.
|
||||
4. **`DEV_OPER.TIMPN` = ore — SIGUR pe bază de uz**, nicio conversie de unitate întâlnită:
|
||||
`Programe/oproceduri_listari.prg:1620` (`sum(...timpn) as ore`), `:2005` (`sum(timpn) as ore`),
|
||||
caption `Clase/odevize.vc2:6310` (`"Total ore"`). Niciun `COMMENT ON COLUMN` găsit în DDL —
|
||||
eticheta vine din convenția de cod, nu dintr-un comentariu de schemă.
|
||||
5. **`VANZARI_DETALII.PRET_ACHIZITIE` — mecanism SIGUR, procentul de 95% zero INCERT**: scris de
|
||||
același flux (`descarca_gestiune`/finalizare factură), doar pentru linii gestionabile
|
||||
(`IN_STOC<>0`), cu `V_PRET` din `STOC` (condiție de MERGE, linia 12741:
|
||||
`AND A.PRET_ACHIZITIE = V_PRET ...`). Pentru linii de manoperă (`IN_STOC=0`) rămâne 0 **prin
|
||||
design** (codul nici nu rulează pentru ele — punctul 2). Nu am verificat empiric (fără acces
|
||||
Oracle) dacă cele ~95% zero din schema de test chiar corespund liniilor de manoperă sau ascund
|
||||
și piese needescărcate din alt motiv — am recomandat team-lead-ului un count pe
|
||||
`IN_STOC × (PRET_ACHIZITIE=0)` pentru confirmare.
|
||||
|
||||
**Concluzie rundă 2**: `pret_achizitie` de pe `VANZARI_DETALII` e de încredere ca sursă a costului
|
||||
pe factură pentru liniile de piese; un 0 pe linie de manoperă e corect, nu semnal de problemă.
|
||||
|
||||
**CORECTARE ulterioară (din `docs/propuneri_coloane_manopera_piese_viz.md`, actualizat de altcineva
|
||||
cu acces Oracle, după ce am trimis răspunsul de mai sus)**: pe schema de test, `PRET_ACHIZITIE = 0`
|
||||
nu doar pe liniile de manoperă (`IN_STOC=0`: 2475/2526 = 98%), ci **și pe 96% din liniile de piese
|
||||
gestionabile** (`IN_STOC=1`: 8561/8889 = 96%). Deci concluzia mea "e de încredere pentru piese" nu
|
||||
se confirmă empiric — mecanismul de scriere există (descris mai sus), dar pe date reale coloana e
|
||||
goală aproape peste tot, inclusiv acolo unde ar trebui completată. Motivul exact nu e stabilit
|
||||
(posibil: câmpul se completează doar pe un anumit flux de facturare, sau pe majoritatea documentelor
|
||||
din baza de test descărcarea de gestiune nu s-a mai executat din alt motiv). **Nu folosiți
|
||||
`VANZARI_DETALII.PRET_ACHIZITIE` ca sursă de cost fără verificare suplimentară — `RUL.PRET` (via
|
||||
`AUTO_ISTORIC_COMENZI`) rămâne sursa confirmată empiric.**
|
||||
Reference in New Issue
Block a user