Files
roaauto/docs/handoff_cost_materiale_manopera.md
2026-09-22 19:43:55 +03:00

11 KiB
Raw Blame History

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 — 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.

(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):

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):
    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.