Files
roa2web-service-auto/docs/service-auto/tabele-service-auto.md
Claude Agent 43484db45e docs(service-auto): ground truth audit v3 from MARIUSM_AUTO production
Add real production sources as authoritative reference (supersedes
vfp_roaauto/Scripturi_instalare/packages.sql which is for a different
product — devize producție, not service auto):

- mariusm_ddl_export.sql: 5127 lines DDL from DBMS_METADATA (tables,
  views, triggers) of MARIUSM_AUTO schema
- pack_auto.pck: main business package (17 procedures)
- PACK_FACTURARE.pck, PACK_SESIUNE.pck, PACK_CONTAFIN.pck,
  PACK_COMENZI.pck: dependency packages
- export_ddl.sql: SQL export helper using DBMS_METADATA + DBMS_OUTPUT
  with discovery via ALL_OBJECTS LIKE patterns

Rewrite tabele-service-auto.md v3 (~600 lines) fully grounded in
production sources. Map all flows end-to-end:

- Create (pack_auto.dev_adauga_lucrare) → NOM_LUCRARI + DEV_ORDL
- Normare (dev_adauga_operatie) → DEV_OPER + DEV_OPER_MECANICI
- Validate ops (dev_valideaza_operatii) → DEV_OPER.VALIDAT
- Validate order (dev_valideaza_comanda) → DEV_ORDL.VALIDAT + CALENDAR
- Archive (dev_arhiveaza_comanda) → DEV_ORDL.INCHIS_FORTAT
- Bonuri consum: generic ROA (ointroduceri.prg tip=3) → RUL.id_lucrare
- Facturare: pack_facturare.* + pack_auto.actualizeaza_deviz

Key business semantics confirmed by Marius 2026-04-11:

- DEV_TIP_DEVIZ.inch_validare = 1 means validation alone closes the
  order (no closing note). inch_validare = 0 means additional closing
  required (via invoice for billable types, or 711=332 journal entry
  for internal types). View AUTO_LISTARE_MAN_TOT_COM has the exact
  "closed" condition as (validat=1 AND inch_validare=1) OR
  (facturat=1 AND inch_validare=0).
- Live DEV_TIP_DEVIZ values: 1=POST GARANTIE, 2=GARANTIE, 3=REGIE,
  4=PREGATIRE, 5=REGIE 2, 6=PRODUCTIE, 7=CONSTATARE. REGIE/PRODUCTIE/
  CONSTATARE have inch_validare=1 (internal, closed at validation).
- DEV_OPER for service auto contains only manopera (id_norme). The
  id_articol/id_rul_aux columns exist in DDL for another product that
  shares the table but are not populated by pack_auto.
- Real materials consumed on an order live in RUL tagged by id_lucrare,
  not in DEV_OPER. DEV_ESTIMARI_REP is a separate pre-sale estimate
  (both manopera and materiale lines) given to the client, independent
  of the real manopera (DEV_OPER) and real materials (RUL).

Plan Correction 13 (claude-main-design-20260411-rethink.md):

- Invalidate Scripturi_instalare references
- Confirm NOM_LUCRARI ← DEV_ORDL inheritance pattern
- Confirm pack_sesiune.dev_idLucrare/dev_idOrdl populated by triggers
- Refine prototype SP (Option 3) template based on real schema
- Timeline unchanged, scope wall reconfirmed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-05 09:37:09 +00:00

48 KiB

Tabele + SP-uri Service Auto — MARIUSM_AUTO ground truth (v3)

Status: v3 complet rescris 2026-04-11 pe baza sursă producție.

Surse (toate din docs/service-auto/):

  • mariusm_ddl_export.sql — DDL exportat din producție (tabele, views, triggere)
  • pack_auto.pck — pachet principal service auto
  • PACK_FACTURARE.pck — pachet facturare
  • PACK_SESIUNE.pck — session state (dev_idLucrare, dev_idOrdl, getAn/getLuna)
  • PACK_CONTAFIN.pck — financial utilities (getCotaTVAStandard, get_idFact)
  • PACK_COMENZI.pckpentru ROA ERP base comenzi, NU service auto

Versiuni anterioare invalidate:

  • v1/v2 a referit vfp_roaauto/Scripturi_instalare/packages.sql → acel fișier era pentru alt produs ("devize producție"), NU service auto.
  • v2 a presupus că tabela e comenzi/vcomenzi → view-ul VCOMENZI din MARIUSM_AUTO nu e pentru service auto (e pentru ROA ERP base, tabela sursă comenzi + nom_masini + id_codclient + field interna cu valori INTERNA/EXTERNA/GESTIUNE/SECTIE).
  • Service auto = DEV_ORDL + NOM_LUCRARI (pattern de inheritance), cu view-uri dedicate prefixate AUTO_*.

1. Model de entități — ierarhie ROA + extensie ROAAUTO

┌──────────────────────────────────────────────────────────────────────────┐
│ NOM_LUCRARI (ROA ERP base — header generic al oricărei "lucrări"/comenzi) │
│   id_lucrare PK, nrord, id_mod, facturata, id_fact, id_tata               │
│   TRIGGER TRG_NOM_LUCRARI_BEFOINS: NEXTVAL → id_lucrare                   │
│                                     pack_sesiune.dev_idLucrare := ID      │
└────────────────────────────────┬─────────────────────────────────────────┘
                                 │ FK id_lucrare (FK_DEV_ORDL_002)
                                 ▼
┌──────────────────────────────────────────────────────────────────────────┐
│ DEV_ORDL (ROAAUTO — extensie service auto)                               │
│   id_ordl PK, id_lucrare FK, id_tip FK, id_masiniclient FK,              │
│   id_inspector, id_asigurator, id_part, id_part_ref, id_agent,           │
│   validat, inchis_fortat, proc_tvav, kmint, ore_functionare,             │
│   solicitari_client CLOB, observatii, defectiuni, nr_dosar, ...          │
│   TRIGGER TRG_DEV_ORDL_BEFOINS: NEXTVAL → id_ordl                        │
│                                  pack_sesiune.dev_idOrdl := ID           │
└──┬───────────────────────────────────────────────┬───────────────────────┘
   │                                               │
   │ FK id_ordl                                    │ id_lucrare (NU FK direct,
   ▼                                               │  tag logic prin coloană)
┌─────────────────────────────────────┐         ┌─────────────────────────────┐
│ DEV_OPER                            │         │ RUL (ROA generic warehouse) │
│ (NUMAI manoperă pentru service auto)│         │  id_rul PK, id_lucrare,     │
│   id_oper PK, id_ordl FK,           │         │  id_articol, cante, pretv,  │
│   id_norme FK → DEV_NOM_NORME,      │         │  id_set, id_fact, ...       │
│   timpn, pret, validat,             │         │                             │
│   id_util, dataora, sters, nou      │         │ Populat de "Bon consum"     │
│                                     │         │ (ointroduceri.prg tip=3)    │
│ Coloane id_articol / id_rul_aux:    │         │ cu ID_LUCRARE tag.          │
│ EXISTĂ în DDL (pentru alt produs    │         └─────────────────────────────┘
│ "producție" care partajează schema),│
│ dar NU sunt populate de service auto│
└────┬────────────────────────────────┘
     │ FK id_oper
     ▼
┌──────────────────────────────────────────────────────────────────────────┐
│ DEV_OPER_MECANICI — distribuția timpului pe mecanici                      │
│   id_opermecanic PK, id_oper FK, id_mecanic FK, ore                       │
└──────────────────────────────────────────────────────────────────────────┘

Materialele consumate pe o comandă NU sunt în DEV_OPER. Sunt în RUL (tabela generică ROA de rulaje / mișcări de stoc), legate de comandă prin coloana RUL.ID_LUCRARE. Flow-ul e:

  1. User face "Bon consum" în ointroduceri.prg (tip=3) → selectează articole din stoc + tag-uiește comandă (id_lucrare) → salvare
  2. Generic ROA warehouse scrie rânduri în RUL cu ID_LUCRARE = X, SCD = '3xx', SCC = '6xx' (consum de stoc)
  3. La afișarea devizului și la facturare, materialele se citesc ca SUM(cante * pretv) FROM RUL WHERE id_lucrare = X

Notă business Marius 2026-04-11: este posibil ca DEV_OPER să fie folosit de alt program de producție care are și materiale în DEV_OPER (cu id_articol + id_rul_aux populate), dar pentru service auto ROAAUTO, DEV_OPER conține doar operații de manoperă — fiecare linie are id_norme non-NULL și id_articol NULL.

Separat, deviz estimativ (pre-sale, ofertă către client):

DEV_ESTIMARI_REP (deviz estimativ — ofertă pentru client înainte de a începe lucrarea)
   id_dev_estimare_rep PK, id_lucrare FK,
   id_norme (manoperă estimată) SAU id_articol (material estimat),
   cantitate, pret, pret_cu_tva, cota_tva, id_sectie, id_valuta, ...

Cele trei flux-uri paralele și independente pe o lucrare (id_lucrare):

# Tabel Ce conține Când se populează
1 DEV_ESTIMARI_REP Deviz estimativ (manoperă + materiale estimate) dat ca ofertă clientului Înainte de a începe lucrarea
2 DEV_OPER Manopera reală executată (doar id_norme, service auto) În timpul lucrării
3 RUL cu id_lucrare Materialele reale consumate (bonuri de consum din stoc) În timpul lucrării

Nu există sincronizare automată: estimarea e doar o ofertă pre-sale, iar lucrarea reală (manoperă + materiale) poate devia de la ea. Comparațiile estimat vs. real se fac în rapoarte analitice, nu în flux-ul operațional.


2. DEV_ORDL — schema reală producție

Exportat via DBMS_METADATA.GET_DDL pe 2026-04-11 din MARIUSM_AUTO. 37 coloane, FK-uri active:

Coloană Tip Null Note
id_ordl NUMBER(10) NN PK, alocat de trigger din SEQ_DEV_ORDL
luna NUMBER(2) NN Luna contabilă (0 default)
an NUMBER(4) NN Anul contabil (0 default)
id_inspector NUMBER(5) Y FK → DEV_NOM_INSPECTORI
id_lucrare NUMBER(10) NN FK → NOM_LUCRARI (FK_DEV_ORDL_002)
termen DATE Y Termen execuție (default SYSDATE + gnTermenZileService, de obicei +10 zile)
datai DATE Y Data intrării
orai / orae NUMBER(5) Y Ora intrare/ieșire
datae DATE Y Data ieșirii
validat NUMBER(1) NN 0/1
id_util_ad NUMBER(5) NN User creator
id_util_valid NUMBER(5) Y User care a validat
dataoraad DATE Y Audit: momentul creării
dataoravalid DATE Y Audit: momentul validării
id_utils / dataoras Y Audit: ștergere logică
id_masiniclient NUMBER(5) Y FK → DEV_MASINICLIENTI
id_asigurator NUMBER(5) Y FK → DEV_NOM_ASIGURATORI
sters NUMBER(1) NN Soft delete
id_tip NUMBER(5) NN FK → DEV_TIP_DEVIZ (default 1)
inchis_fortat NUMBER(1) NN 0/1 — arhivat fără validare
kmint NUMBER(10) Y Km la bord intrare
nr_dosar VARCHAR2(40) Y Nr. dosar daună (pentru garanție asigurator)
solicitari_client CLOB Y Text denormalizat: numele normelor solicitate (agregat prin STRINGAGG din DEV_NOM_NORME la crearea comenzii)
proc_tvav NUMBER(10,4) Y Procent TVA (citit din pack_contafin.getCotaTVAStandard(luna, an) la creare)
id_part NUMBER(10) Y FK → NOM_PARTENERI — clientul direct pe comandă (nu doar prin mașină)
coada_deviz NUMBER(1) NN Flag "în coada devizelor"
observatii VARCHAR2(1000) Y
data_curs DATE Y Pentru comenzi în valută
in_lucru NUMBER(1) NN Flag "comanda în lucru"
id_valuta_deviz NUMBER(10) Y FK → NOM_VALUTE
facturezmix NUMBER(1) NN Flag "facturare mixtă"
data_in_lucru / dataorainlucru DATE Y Audit trecere în lucru
id_agent NUMBER(10) Y FK → NOM_PARTENERI (agent vânzări)
id_util_inchis / dataorainchis Y Audit "închidere forțată" (arhivare)
id_part_ref NUMBER(10) Y FK → NOM_PARTENERI (partener referent)
ore_functionare NUMBER(10) Y Pentru vehicule utilitare (ore motor în loc de km)
defectiuni VARCHAR2(200) Y

PK: PK_DEV_ORDL pe id_ordl.

FK active în producție:

  • FK_DEV_ORDL_001DEV_NOM_INSPECTORI(id_inspector) ENABLE
  • FK_DEV_ORDL_002NOM_LUCRARI(id_lucrare) ENABLE ← constraint critic
  • FK_DEV_ORDL_003NOM_PARTENERI(id_part) ENABLE (client direct)
  • FK_DEV_ORDL_004NOM_VALUTE(id_valuta) ENABLE
  • FK_DEV_ORDL_005NOM_PARTENERI(id_agent) ENABLE
  • FK_DEV_ORDL_006NOM_PARTENERI(id_part_ref) ENABLE

Nu există FK pe id_masiniclient (probabil pentru a permite comenzi pentru mașini temporare sau fără înmatriculare persistentă).

Coloane AVANS, VALCTVA, TIP_INCAS, ID_CTR, ID_FACT, ID_CONTRACT care apăreau în v2 DDL NU există în producție reală. Sunt artefacte ale scripturilor de instalare vechi care au fost abandonate.


3. NOM_LUCRARI — header parent (ROA ERP base)

NOM_LUCRARI (
  id_lucrare   NUMBER(10) NN PK,
  nrord        VARCHAR2(50),
  sters        NUMBER(1) NN default 0,
  id_mod       NUMBER(20) NN default 0,   -- 1200 pentru service auto
  inactiv      NUMBER(1) NN default 0,
  facturata    NUMBER(1) NN default 0,
  id_tata      NUMBER(10),                 -- parent hierarchy
  id_fact      NUMBER(20)                  -- populat la facturare
)

Trigger TRG_NOM_LUCRARI_BEFOINS:

select SEQ_NOM_LUCRARI.NEXTVAL into :new.ID_LUCRARE from dual;
pack_sesiune.dev_idLucrare := :new.id_lucrare;  -- <-- session state pentru pack_auto

Implicație pentru roa2web: după INSERT INTO nom_lucrari ... RETURNING id_lucrare INTO v_local, ai id-ul în două locuri simultan — în v_local (prin RETURNING) și în pack_sesiune.dev_idLucrare (prin trigger). Poți folosi oricare. pack_auto.dev_adauga_lucrare folosește intern pack_sesiune.dev_idLucrare pentru step-ul 2 (INSERT în DEV_ORDL).

Trigger TRG_NOM_LUCRARI_BEFOUPD: cheamă pack_audit.verifica_val(...) pentru fiecare câmp modificat → toate UPDATE-urile pe NOM_LUCRARI sunt audit trail-uite automat într-un pachet separat pack_audit (nu am încă sursa, nu e în scope imediat).


4. DEV_OPER — liniile de operații manoperă (doar)

Important: pentru service auto ROAAUTO, DEV_OPER conține numai operații de manoperă. Deși schema fizică are coloanele id_articol, id_rul_aux, id_dev_estimare_rep (probabil pentru compatibilitate cu alt produs de producție care partajează aceeași tabelă), SP-urile pack_auto.* pentru service auto nu le populează. Verificare în body-ul dev_adauga_operatie și dev_adauga_oper_fact: ambele inserează doar id_norme, nu id_articol.

DEV_OPER (
  id_oper            NUMBER(10) NN PK,
  id_ordl            NUMBER(10) NN FK  DEV_ORDL,
  id_norme           NUMBER(10)    FK  DEV_NOM_NORME   -- SERVICE AUTO: mereu non-NULL
  timpn              NUMBER(8,3) NN default 0,           -- ore manoperă
  pret               NUMBER(17,4) NN default 0,          -- preț oră (lei/oră)
  datai              DATE NN default SYSDATE,
  id_sectie          NUMBER(5)     FK  NOM_SECTII,
  id_util            NUMBER(5),                          -- validator (populat la validare)
  dataora            DATE,                               -- momentul validării
  id_utili           NUMBER(5),                          -- creator (introducător)
  id_utils           NUMBER(5),                          -- user care a șters
  dataoras           DATE,
  sters              NUMBER(1) NN default 0,
  validat            NUMBER(1) NN default 0,
  nou                NUMBER(1) NN default 0,             -- flag heritage-currency RON/ROL
  id_fact            NUMBER(20)   FK  DOCUMENTE        -- populat la facturare
  -- Coloanele următoare există în DDL dar NU sunt folosite de service auto:
  -- id_articol         NUMBER(20) FK → NOM_ARTICOLE       (pentru alt produs: producție)
  -- id_dev_estimare_rep NUMBER(20) FK → DEV_ESTIMARI_REP  (pentru alt produs)
  -- id_rul_aux          NUMBER(20) FK → RUL_AUXILIAR     (pentru alt produs)
)

Materialele consumate NU sunt aici. Sunt în RUL.id_lucrare (vezi secțiunea 8 pentru flux-ul de bon consum).

Câmpul nou = flag heritage-currency (RON denominat 2005+ vs vechiul ROL). Setat automat în SP-uri pe baza comparației lună curentă vs pack_sesiune.GET_ANRON() / GET_LUNARON(). Pentru orice lucrare modernă (post-2005) → mereu nou = 1. View-urile AUTO_VOPER conțin un CASE care împarte pret la 10000 pentru valorile ROL vechi. Artefact istoric, zero impact asupra prototype-ului nou.

Trigger TRG_DEV_OPER_BEFOINS:

select SEQ_dev_oper.NEXTVAL into :new.id_oper from dual;

(Nu populează session state — deosebire față de DEV_ORDL.)


5. DEV_ESTIMARI_REP — deviz estimativ pentru client (pre-sale)

Rol: deviz estimativ pe care service-ul îl oferă clientului înainte ca lucrarea să înceapă — o "ofertă" care conține estimarea de manoperă și materiale pentru o reparație propusă. Este complet separat de lucrarea reală.

DEV_ESTIMARI_REP        ≠  DEV_OPER              ≠  RUL (id_lucrare)
(deviz estimativ           (manopera reală           (bonuri consum materiale
 către client,              cronometrată pe            reale pe comandă, din stoc,
 manopera + materiale)      comandă)                   din warehouse generic ROA)

Cele trei flux-uri sunt independente:

  1. DEV_ESTIMARI_REP — înainte de lucrare, utilizatorul face o estimare pentru client cu linii mixte (manoperă estimată + materiale estimate). Clientul primește devizul, decide dacă aprobă lucrarea.
  2. DEV_OPER — în timpul lucrării, se înregistrează manopera efectiv executată (doar operații cu id_norme, timp real, preț manoperă).
  3. RUL cu id_lucrare — în paralel, bonurile de consum reale scot materiale din stoc tag-uite pe comandă.

Nu există sincronizare automată între estimare și real — un client poate aproba un deviz estimativ de 1000 lei, dar lucrarea reală să se termine la 1200 lei (fie pentru că s-a găsit ceva în plus, fie pentru că au fost piese mai scumpe decât s-a estimat). Comparația real vs. estimat se face probabil la facturare sau în raporte.

Schema: fiecare linie e fie manoperă estimată (id_norme NN) fie material estimat (id_articol NN):

DEV_ESTIMARI_REP (
  id_dev_estimare_rep NUMBER(20) NN PK,
  id_lucrare          NUMBER(20) NN FK  NOM_LUCRARI,
  id_norme            NUMBER(20)    FK  DEV_NOM_NORME,
  id_articol          NUMBER(20)    FK  NOM_ARTICOLE,
  cantitate           NUMBER(20,4) NN,
  pret                NUMBER(20,4) NN default 0,
  pret_cu_tva         NUMBER(1) NN default 0,
  cota_tva            NUMBER(10),
  id_sectie           NUMBER(10) FK  NOM_SECTII,
  id_pol              NUMBER(20) FK  CRM_POLITICI_PRETURI,
  id_dev_estimare_prod NUMBER(20) FK  DEV_ESTIMARI_PRODUSE,
  id_articol_grupare  NUMBER(20),
  cu_pierderi         NUMBER(1) NN default 0,
  id_valuta           NUMBER(10),
  semifabricat_ales / semifabricat_id NUMBER(10),
  id_util / dataora, id_utils / dataoras, sters
)

View-ul UI: AUTO_VESTIMARI_REP — denormalizează dev_estimari_rep cu dev_nom_norme + nom_articole, calculează pretftva / pretctva / valftva / valtva / valoare prin pack_sesiune.calculeaza_pret_* + calculeaza_total_*.

SP-uri pentru estimare (din pack_auto):

  • adauga_manopera_de(id_lucrare, id_norme, cantitate, pret, pret_cu_tva, cota_tva, id_util)
  • adauga_material_de(id_lucrare, id_articol, cantitate, pret, pret_cu_tva, cota_tva, id_util)
  • modifica_pret_de, modifica_cota_tva_de, modifica_cantitate_de, sterge_articol_de

NOT IN SCOPE pentru prototype — estimarea e un sub-flux pre-sale dedicat.


6. DEV_TIP_DEVIZ — enum tip comandă (cu flag închidere prin validare)

DEV_TIP_DEVIZ (
  id_tip        NUMBER(5) NN PK,
  denumire      VARCHAR2(50) NN,
  sters         NUMBER(1) NN default 0,
  inch_validare NUMBER(1) NN default 1   -- 1 = închidere prin validare, 0 = alt mod
)

Coloana inch_validare e cheia pentru a înțelege flux-ul post-validare. Default = 1 (închidere implicită prin validare). Setată per tip-comandă prin pack_auto.setOptiuneInchidere(v_tip, v_inchidere_validare) și citită prin pack_auto.getOptiuneInchidere(v_tip) RETURN NUMBER.

Valori live confirmate 2026-04-11 de Marius (SELECT id_tip, denumire, sters, inch_validare FROM MARIUSM_AUTO.DEV_TIP_DEVIZ ORDER BY id_tip):

id_tip denumire prefix sters inch_validare Natura comenzii Închidere reală
1 POST GARANTIE (fără) 0 0 Se facturează client direct prin factură (pack_facturare.*) → facturat=1
2 GARANTIE G 0 0 Se facturează asigurator prin dosar daună prin factură → facturat=1
3 REGIE R 0 1 Auto proprii — NU se facturează validare directăvalidat=1 suficient
4 PREGATIRE P 0 0 Se facturează prin factură → facturat=1
5 REGIE 2 (fără) 0 0 Se facturează prin factură → facturat=1
6 PRODUCTIE PR 0 1 Producție internă — NU se facturează validare directăvalidat=1 suficient
7 CONSTATARE C 0 1 Doar diagnostic — NU se facturează validare directăvalidat=1 suficient

Prefixele sunt construite în VFP la oproceduri_devize.prg:108-120 (hardcodate în client, nu în DB).

Semantica inch_validare (corectată 2026-04-11 după clarificare iterativă Marius):

Flag-ul decide dacă validarea comenzii e suficientă pentru a o considera închisă, sau e necesară încă o notă contabilă suplimentară.

  • inch_validare = 1Validarea ESTE închiderea. Comanda se consideră închisă prin simplul fapt că DEV_ORDL.VALIDAT = 1. NU se generează nicio notă contabilă suplimentară. Folosit tipic pentru comenzi interne (REGIE = auto proprii, PRODUCTIE, CONSTATARE) unde nu se facturează nimic și nu se dorește impact contabil la închidere.

  • inch_validare = 0Validarea NU e închiderea. Comanda rămâne "deschisă" contabil chiar și după VALIDAT = 1. E nevoie de o notă contabilă suplimentară pentru a o închide real:

    • Pentru tipuri facturabile (GARANTIE, POST GARANTIE, PREGATIRE, REGIE 2) → nota vine prin facturare (pack_facturare.*), care setează și facturat = 1 pe flux-ul de agregate.
    • Pentru tipuri nefacturabile (teoretic REGIE/PRODUCTIE dacă ar fi configurate așa) → se generează o notă contabilă 711 = 332 care recunoaște venitul intern și închide stocul "servicii în curs de execuție".

Dovada în cod — view-urile AUTO_LISTARE_MAN_TOT_COM și AUTO_LISTARE_MAN_TOT_DESF (mariusm_ddl_export.sql:1795-1800 și :1842-1847) au condiția exactă pentru "comandă închisă în luna curentă":

WHERE a.sters = 0
  AND ( (extract(month from a.dataoravalid) = pack_sesiune.getluna()
         AND extract(year  from a.dataoravalid) = pack_sesiune.getan()
         AND a.validat = 1
         AND e.inch_validare = 1)                     -- inchis prin validare singura
        OR
        (extract(month from b.dataact) = pack_sesiune.getluna()
         AND extract(year  from b.dataact) = pack_sesiune.getan()
         AND b.facturat = 1
         AND e.inch_validare = 0))                    -- inchis prin facturare/nota

Cu alte cuvinte, view-ul consideră o comandă "închisă" DOAR dacă:

  • inch_validare = 1 + VALIDAT = 1 (calea A: validarea închide) SAU
  • inch_validare = 0 + FACTURAT = 1 (calea B: trebuie factură/notă de închidere)

Configurare live MARIUSM_AUTO (2026-04-11):

Tip comandă Configurare Efect
REGIE, PRODUCTIE, CONSTATARE inch_validare = 1 Validarea e închiderea. Zero notă contabilă.
POST GARANTIE, GARANTIE, PREGATIRE, REGIE 2 inch_validare = 0 Validarea nu e suficientă. Trebuie factură.

Marius poate schimba configurarea per tip — ex: dacă schimbă REGIE la inch_validare = 0, atunci comenzile REGIE nu se mai consideră închise la validare, ci necesită o notă contabilă 711 = 332 suplimentară înainte ca FACTURAT = 1 să apară în agregat.

dev_arhiveaza_comanda este o procedură complet separată (setează INCHIS_FORTAT = 1), apelată doar pentru a abandona forțat o comandă — nu e legată de inch_validare. Folosit doar pentru cazuri excepționale (client a renunțat, constatare fără urmare tehnică, etc.).

Implicație pentru prototype (creare only): irelevant pentru scope wall. Critic pentru phase 2+ când se implementează închiderea comenzii: UI-ul trebuie să știe că validarea singură NU închide în toate cazurile, și să navigheze la facturare sau notă contabilă de închidere în funcție de tip.inch_validare.


7. Pachetul principal pack_auto — map procedure → tabel

Map complet (din docs/service-auto/pack_auto.pck):

7.1. Create comandă

Procedură Operație
dev_adauga_lucrare (15 params, overload scurt) Wrapper peste versiunea lungă. Apelează versiunea cu 17 params cu defaults pe pnOreFct, pcObservatii, pcDefectiuni.
dev_adauga_lucrare (17 params, overload lung) Flux real: (1) INSERT NOM_LUCRARI(nrord, id_mod=1200); (2) agregă solicitari_client din DEV_NOM_NORME.DENOP pentru id-urile din CSV; (3) INSERT DEV_ORDL cu toate câmpurile; (4) UPDATE DEV_MASINICLIENTI SET kmint, ore_functionare. Verifică mai întâi că NRORD nu e duplicat pe NOM_LUCRARI (aruncă ORA-20000).

Dependențe runtime ale versiunii lungi:

  • pack_sesiune.dev_idLucrare — populat de TRG_NOM_LUCRARI_BEFOINS, citit intern la step 3
  • pack_contafin.getCotaTVAStandard(luna, an) — pentru proc_tvav (citit din CALENDAR / config lunar)
  • STRINGAGG(DENOP) agregat peste DEV_NOM_NORME.ID_NORME IN (...) unde ... provine din parsarea CSV
  • (Oracle 19c+ are STRINGAGG ca user-defined aggregate; verifică dacă există în MARIUSM_AUTO)

7.2. Normare operații

Procedură Operație
dev_adauga_operatie(v_gcs, id_sectie, id_ordl, pret, id_util, timpn, id_norme, csv_id_mecanic, an?, luna?) (1) Citește DEV_ORDL.VALIDAT → dacă = 1, aruncă ORA-20000 Comanda validata nu se mai poate modifica. (2) INSERT DEV_OPER cu validat=0, nou=1. (3) Sparge csv_id_mecanic pe ; → insert multiplu în DEV_OPER_MECANICI cu ore = timpn / count(mecanici).
dev_actualizeaza_operatie(v_gcs, camp, valoare_noua, id_oper, luna, an) Verifică VALIDAT=0. Actualizează PRET sau TIMPN. Suportă tranziția RON/ROL: dacă DATAI < get_lunaron() și luna-țintă ≥ get_lunaron() atunci valoare_noua * 10000.
dev_valideaza_operatii(v_gcs, id_ordl, id_util) Verifică mai întâi DEV_ORDL.VALIDAT = 0. Setează VALIDAT=1, ID_UTIL, DATAORA=SYSDATE pe toate liniile din DEV_OPER WHERE id_ordl = X AND sters=0 AND validat=0.
valideaza_operatie(schema, validat, id_oper, id_util) Setează manual VALIDAT pe o singură operație.
sterge_operatie(schema, id_oper, id_util) Soft delete: sters=1, dataoras=SYSDATE.
modifica_sectie(schema, id_sectie, id_oper, id_util) UPDATE secție pe operație.
dev_distribuie_timp_n(v_luna, v_an) MERGE peste DEV_OPER_MECANICI: pentru operațiile unde sum(ore_mecanici) <> timpn, redistribuie uniform. Folosit ca housekeeping periodic.

View-ul UI pentru normare: AUTO_NORMARE_COMENZI — filtrat pe inchis_fortat = 0 AND validat = 0 (din AUTO_COMENZI_VALIDATE).

7.3. Validare comandă

Procedură Operație
dev_valideaza_comanda(v_gcs, id_ordl, id_util, an?, luna?) (1) Verifică DEV_OPER WHERE id_ordl = X AND sters=0 AND validat=0 → dacă există, aruncă ORA-20000 Mai sunt operatii nevalidate. (2) Calculează ldData = SYSDATE sau ultima zi a lunii vechi. (3) Verifică CALENDAR că luna e deschisă. (4) UPDATE DEV_ORDL SET VALIDAT=1, ID_UTIL_VALID, DATAORAVALID=ldData, PROC_TVAV = pack_contafin.getCotaTVAStandard(luna, an).
dev_invalideaza_comanda(v_gcs, id_ordl, id_utils) Reverse: VALIDAT=0, DATAORAVALID=NULL, recalculează PROC_TVAV din luna/an curentă a comenzii.
dev_arhiveaza_comanda(id_ordl, id_util) Alternativă la validare — pentru tipuri cu inch_validare=0. Verifică CALENDAR luna deschisă, setează INCHIS_FORTAT=1, ID_UTIL_INCHIS, DATAORAINCHIS = SYSDATE.
dev_dezarhiveaza_comanda(id_ordl) Reverse: INCHIS_FORTAT=0.
dev_sterge_comanda(schema, id_util, id_ordl, id_lucrare) Verifică că RUL WHERE id_lucrare = X AND sters=0 e gol la sum(cante*pretv). Verifică DEV_OPER WHERE id_ordl = X AND sters=0 = 0. Setează sters=1 pe DEV_ORDL și inactiv=1 pe NOM_LUCRARI.

View-ul UI: AUTO_VALIDARE_COMENZI — JOIN peste AUTO_COMENZI_VALIDATE + AUTO_VORDL_MAN (manoperă agregată) + AUTO_VORDL_MAT (materiale agregate) + AUTO_VORDL_FACTURI (info factură emisă).

Flux de validare condiționat: tipul comenzii (dev_tip_deviz.inch_validare) decide care dintre dev_valideaza_comanda (dacă inch_validare=1) sau dev_arhiveaza_comanda (dacă inch_validare=0) se apelează la închiderea comenzii. View-ul AUTO_COMENZI_VALIDATE are chiar o logică "time-aware": consideră o comandă validată doar dacă dataoravalid e ≤ luna curentă din pack_sesiune.getluna() + pack_sesiune.getan() * 12. Validările în viitor apar ca validat=0 în view, ceea ce e intenționat pentru izolare contabilă pe lună.

7.4. Facturare

Procedură Operație
dev_adauga_oper_fact(schema, id_ordl, id_sectie, id_norme, total_f_tva, timpn, ore, id_util, id_mecanic) Folosit pentru tipuri speciale ITP/SPALARE/DIVERSE unde se adaugă o operație "sintetică" direct la facturare. Setează DEV_ORDL.VALIDAT=1 + INSERT în DEV_OPER + DEV_OPER_MECANICI. V_PRET = total_f_tva / timpn (calcul reverse pentru a păstra total exact).
actualizeaza_deviz(proc_tvav, csv_id_ordl, id_set) Apelat la final de facturare. (1) Ia ultimul ID_FACT din ACT WHERE cod = current_cod AND scd NOT LIKE '5%'. (2) UPDATE DEV_ORDL SET PROC_TVAV pentru id-urile din CSV. (3) UPDATE RUL SET ID_FACT = v_id_fact WHERE id_set <> 229 AND id_lucrare IN (...) (index hint IDX_RUL_001). (4) Pentru id_set în (31003-31011), UPDATE și NOM_LUCRARI SET ID_FACT.
citeste_sume_stornare(csv_id_lucrare, delim, cursor OUT) Citește sume storno avans pentru listele CSV de lucrări.
citeste_date_avans(csv_id_lucrare, delim, cursor OUT) Citește avansurile pentru facturare.
citeste_discount_contract / salveaza_discount_contract Citește / salvează discount-uri contract per partener + sucursală.

Flux facturare real (VFP factureaza_comandafactureaza_devizpack_facturare.*):

1. [pack_auto.dev_adauga_lucrare]  — uneori se creează o comandă ad-hoc pentru facturi
                                     ITP/SPALARE/DIVERSE (altfel se pleacă de la o comandă existentă)
2. User completează date factură (client, valoare, TVA, incasare) în VFP form
3. [lans(lnIdSet, ...)]            — VFP generează note contabile pentru factură în cursor actactan
4. [verificare_note_contabile()]   — validare locală VFP
5. [pack_auto.dev_adauga_oper_fact] — pentru tipuri ITP/SPALARE/DIVERSE, adaugă operația sintetică
6. [factureaza_deviz]:
   a. [pack_facturare.initializeaza_date_factura(...)] → INSERT în VANZARI header (20+ param)
   b. pentru fiecare articol în crsvanztemp:
      [pack_facturare.adauga_articol_factura_deviz(...)] → INSERT în VANZARI_DETALII
   c. [oscrie_in_fisiere(...)] — scrie cursor actactan în ACT (registrul jurnal)
   d. [pack_facturare.scrie_in_vanzari(...)] → finalizare VANZARI (incasare, discount, delegat)
      apelează în aceeași tranzacție:
      [pack_auto.actualizeaza_deviz(proc_tvav, csv_id_ordl, id_set)]
      → UPDATE DEV_ORDL.PROC_TVAV + RUL.ID_FACT + NOM_LUCRARI.ID_FACT (pentru id_set specifice)
   e. MERGE INTO vanzari SET id_fact FROM act WHERE cod=v.cod AND scd='4111'
7. COMMIT sau ROLLBACK

Tabele atinse la facturare: VANZARI, VANZARI_DETALII, ACT, DEV_ORDL.PROC_TVAV, RUL.ID_FACT (pentru materiale consumate), NOM_LUCRARI.ID_FACT, ACT.ID_FACT (prin pack_facturare). IN SCOPE abia pentru phase 3-4, după ce prototype-ul probează crearea unei comenzi simple.

7.5. Alte operații

  • modifica_date_comanda(id_ordl, id_tip, kmint, ore_functionare, id_util) — edit rapid
  • modifica_tip_comanda(schema, id_tip, id_ordl, id_util) — schimbă tip
  • modifica_client_comanda(schema, id_ordl, id_masiniclient, id_util) — schimbă mașina

8. Bonuri consum = flow generic ROA, în RUL.id_lucrare

pack_auto nu are nicio procedură pentru bonuri consum. Materialele consumate pe comandă sunt 100% în tabela generică RUL (rulaje ROA), tag-uite prin RUL.ID_LUCRARE = X. Flux-ul:

  1. VFP ointroduceri.prg cu tip=3 (BON CONSUM) deschide un form de introducere articole din stoc → user selectează linii + alege comanda (id_lucrare) → salvare.
  2. Generic ROA warehouse SP generează rânduri în RUL cu:
    • ID_LUCRARE = X (tag-ul comenzii)
    • SCD = '3xx' (contul de stoc), SCC = '6xx' sau '332' (contul de destinație)
    • CANTE, PRETV (cantitate + preț unitar)
    • ID_SET care tipizează operațiunea de stoc
  3. La afișarea devizului (view-urile AUTO_VORDL_MAT, AUTO_VALIDARE_COMENZI), materialele se citesc ca agregat din MV_ORDL_MAT (materialized view peste RUL) pe id_lucrare.
  4. La facturare, factureaza_deviz citește suma materialelor din cursoarele actactan
    • vanzari (generate de lans(lnIdSet...) local în VFP), apoi pack_auto.actualizeaza_deviz face UPDATE RUL SET ID_FACT = :v_id_fact WHERE ID_LUCRARE IN (...) AND ID_SET <> 229 — marchează materialele ca facturate.

Impact asupra DEV_OPER: zero. Pentru service auto, DEV_OPER conține doar manoperă; materialele nu intră în DEV_OPER deloc.

Implicație pentru prototype: Bonul de consum este out of scope. Flux-ul atinge pachete generice ROA (neauditate) + tabela RUL (nu e în scheme ROAAUTO dedicate). Dacă phase 2 cere "service auto complet", bonul de consum va fi un sub-modul separat cu propriul audit asupra pachetului generic ROA pack_intrari_iesiri (sau similar).

Observație specială pentru tipurile nefacturabile (inch_validare = 1 în live MARIUSM_AUTO): REGIE/PRODUCTIE/CONSTATARE se închid prin simpla validare — zero notă contabilă. Bonurile de consum materiale rămân în RUL cu ID_FACT = NULL permanent (fără a fi legate de vreo factură), dar comanda e considerată "închisă" în agregatele de raportare. Impactul contabil al materialelor consumate pe aceste comenzi se face prin flux-ul generic ROA de rulaje (stocul e deja scăzut prin scd='3xx', scc='6xx' la momentul bonului de consum).

Dacă Marius ar schimba REGIE la inch_validare = 0 (scenariu teoretic), atunci pentru a închide o comandă REGIE ar trebui:

  1. Validare (VALIDAT = 1) — doar un pas intermediar
  2. O notă contabilă suplimentară 711 = 332 (care recunoaște venitul intern aferent materialelor deja consumate) — această notă trebuie să seteze facturat = 1 sau un mecanism echivalent ca să apară în agregatele view-ului
  3. Abia atunci view-ul AUTO_LISTARE_MAN_TOT_COM consideră comanda "închisă"

Acest scenariu nu e activ în configurarea curentă, dar e permis de schema.


9. View-uri cheie pentru UI service auto

Toate definite în mariusm_ddl_export.sql (secțiunea VIEWS). Cele relevante pentru ecrane:

View Rol JOIN-uri principale
AUTO_COMENZI_VALIDATE Base view — "comenzi cu time-aware validat flag" (validat = 1 doar dacă dataoravalid ≤ luna curentă session) dev_ordl + syn_utilizatori + nom_lucrari
AUTO_NORMARE_COMENZI Listare comenzi care așteaptă normare operații. Filtru tipic: inchis_fortat=0 AND validat=0 auto_comenzi_validate + auto_vordl_facturi + dev_masiniclienti + nom_parteneri + dev_tip_deviz
AUTO_VALIDARE_COMENZI Listare comenzi în curs de validare + manopera/materiale agregate auto_comenzi_validate + auto_vordl_man + auto_vordl_mat + auto_vordl_facturi + lookup-uri
AUTO_ORDL_FACTURARE Listare comenzi pregătite pentru facturare dev_ordl + nom_lucrari + dev_masiniclienti + nom_parteneri + dev_nom_masini + dev_nom_marci + dev_nom_asiguratori + dev_nom_inspectori WHERE sters = 0
AUTO_VORDL Listare completă comandă (toate câmpurile expuse) ~10 JOIN-uri
AUTO_VORDL_MAN Agregat manoperă pe comandă (sum după pack_sesiune RON/ROL) derivat
AUTO_VORDL_MAT Agregat materiale pe comandă — folosește MV_ORDL_MAT (materialized view) cu pack_sesiune currency logic MV_ORDL_MAT grupat pe id_lucrare
AUTO_VORDL_FACTURI Facturile emise per id_lucrare derivat
AUTO_VESTIMARI_REP Linii estimare pentru un deviz pre-sale dev_estimari_rep + dev_nom_norme + nom_articole + syn_utilizatori
AUTO_VOPER Liniile de operație cu lookup norme + ansamblu + mașină + secție + mecanic dev_oper + dev_nom_norme + dev_nom_ansamble + dev_nom_masini + nom_sectii + syn_utilizatori
AUTO_VOPER_DETALII_M Detalii mecanici per operație dev_oper_mecanici + dev_mecanici + nom_parteneri
AUTO_VMASINICLIENTI Lista mașini + clienți pentru dropdown-uri dev_masiniclienti + dev_nom_masini + dev_nom_marci + nom_parteneri
AUTO_VNORME Catalog norme manoperă pentru picker dev_nom_norme + dev_nom_masini + dev_nom_ansamble

Notă pack_sesiune currency logic: multe view-uri (AUTO_VOPER, AUTO_VORDL_MAT) conțin CASE WHEN pack_sesiune.getAn()*12 + getLuna() >= GET_ANRON()*12 + GET_LUNARON() THEN ron ELSE rol END. Acesta e un heritage-currency switch (RON denominat 2005 vs vechiul ROL) — după 2005 toate înregistrările noi sunt RON, deci în practică întotdeauna se ia branch-ul RON. Pentru prototype modern, acest CASE e un artefact istoric care nu trebuie replicat — noi inserăm direct RON fără switch.


10. Flux end-to-end real (VFP → DB)

10.1. Creare comandă

[VFP: frm_gencom] Submit
  ↓
VFP SQL: begin pack_auto.dev_adauga_lucrare(
  gcS, gnAn, gnLuna, gnIdUtil,
  pcNr,              -- 'G12345' / 'R...'
  pnIdInsp,
  pnIdAsig, pcNrDosar,
  pnIdMC, pnKmInt, pnOreFct,
  to_date(pdTermen, 'DD/MM/YYYY'),
  pntipcom,
  pcSirIDOperatiiClient,
  pcObservatii, pcDefectiuni,
  pnIdPartRef,
  ?@pnIdOrdl); end;
  ↓
PACK_AUTO.DEV_ADAUGA_LUCRARE (overload 17 params):
  1. SELECT COUNT(*) FROM NOM_LUCRARI WHERE sters=0 AND nrord=pcNr
     → IF > 0 THEN RAISE ORA-20000 'Mai exista o lucrare...'
  2. INSERT INTO NOM_LUCRARI (nrord, id_mod) VALUES (pcNr, 1200)
     → TRG_NOM_LUCRARI_BEFOINS populează :new.id_lucrare din SEQ_NOM_LUCRARI
       + pack_sesiune.dev_idLucrare := :new.id_lucrare
  3. IF pcSirIdOperatii IS NOT NULL THEN
       SELECT STRINGAGG(DENOP) INTO v_solicitari_client FROM DEV_NOM_NORME
        WHERE id_norme IN (<parsed CSV>)
  4. INSERT INTO DEV_ORDL (an, luna, id_inspector, id_lucrare, datai,
        id_util_ad, id_masiniclient, id_asigurator, id_tip, kmint,
        ore_functionare, termen, nr_dosar, dataoraad, solicitari_client,
        observatii, defectiuni, proc_tvav, id_part_ref)
      VALUES (tnAn, tnLuna, pnIdInsp,
              pack_sesiune.dev_idLucrare,  -- <-- citit din session state populat la pasul 2
              SYSDATE, tnIdUtil, pnIdMC, pnIdAsig, pnTipCom, pnKmInt,
              pnOreFct, pdTermen, pcNrDosar, SYSDATE, v_solicitari_client,
              pcObservatii, pcDefectiuni,
              pack_contafin.getCotaTVAStandard(tnLuna, tnAn),
              decode(pnIdPartRef, 0, NULL, pnIdPartRef))
      RETURNING id_ordl INTO pnIdOrdl
     → TRG_DEV_ORDL_BEFOINS populează :new.id_ordl din SEQ_DEV_ORDL
       + pack_sesiune.dev_idOrdl := :new.id_ordl
  5. UPDATE DEV_MASINICLIENTI SET kmint, ore_functionare WHERE id_masiniclient=pnIdMC

Nu touch-uiește ACT, nici RUL, nici VANZARI. Facturare e un flux separat.

10.2. Normare operații (adaugă manoperă pe o comandă existentă)

[VFP: normare_comanda()] deschide FRM_NOM_COM cu cursor AUTO_NORMARE_COMENZI
  ↓
User selectează o comandă + alege norme din AUTO_VNORME + alocă mecanici
  ↓
VFP SQL: begin pack_auto.dev_adauga_operatie(
  gcS, pnid_sectie, pnIdOrdl, pnpret, gnIdUtil,
  pntimpn, pnid_norme, pcsir_idmecanic); end;
  ↓
PACK_AUTO.DEV_ADAUGA_OPERATIE:
  1. SELECT VALIDAT FROM DEV_ORDL WHERE id_ordl = X
     → IF validat=1 THEN RAISE ORA-20000 'Comanda validata nu mai poate fi modificata'
  2. INSERT INTO DEV_OPER (id_ordl, id_sectie, timpn, pret, id_norme,
                            id_utili, nou, datai, dataora)
     VALUES (..., 1, SYSDATE, SYSDATE)
     RETURNING id_oper INTO v_id_oper
     → TRG_DEV_OPER_BEFOINS populează :new.id_oper din SEQ_dev_oper
  3. PARSE csv_id_mecanic pe ';' → FOR i IN 1..count LOOP
       INSERT INTO DEV_OPER_MECANICI (id_oper, id_mecanic, ore)
       VALUES (v_id_oper, id_mec_i, timpn / count)

10.3. Validare operații (marchează fiecare operație ca "gata")

[VFP user click "Valideaza operatii"] pe o comandă
  ↓
VFP SQL: begin pack_auto.dev_valideaza_operatii(gcS, pnIdOrdl, gnIdUtil); end;
  ↓
PACK_AUTO.DEV_VALIDEAZA_OPERATII:
  1. SELECT VALIDAT FROM DEV_ORDL WHERE id_ordl = X
     → IF validat=1 THEN RAISE ORA-20000 'Comanda validata...'
  2. UPDATE DEV_OPER SET validat=1, id_util, dataora=SYSDATE
     WHERE id_ordl = X AND sters=0 AND validat=0

Alternativ, linie cu linie:

begin pack_auto.dev_valideaza_operatie(gcS, pn_id_oper, gnIdUtil); end;
→ UPDATE DEV_OPER SET VALIDAT=1 WHERE id_oper=X

10.4. Validare comandă (finalizează comanda după ce toate operațiile sunt validate)

[VFP user click "Valideaza comanda"]
  ↓
VFP SQL: begin pack_auto.dev_valideaza_comanda(gcS, pnIdOrdl, gnIdUtil, an?, luna?); end;
  ↓
PACK_AUTO.DEV_VALIDEAZA_COMANDA:
  1. SELECT COUNT(*) FROM DEV_OPER WHERE id_ordl = X AND sters=0 AND validat=0
     → IF > 0 THEN RAISE ORA-20000 'Mai sunt operatii nevalidate'
  2. Calculează ldData: SYSDATE dacă luna curentă = luna_comandă, else LAST_DAY
  3. SELECT COUNT(*) FROM CALENDAR WHERE an=.. AND luna=..
     → IF 0 THEN RAISE ORA-20000 'Nu puteti valida deoarece nu este deschisa luna'
  4. UPDATE DEV_ORDL SET VALIDAT=1, ID_UTIL_VALID, DATAORAVALID=ldData,
                          PROC_TVAV = pack_contafin.getCotaTVAStandard(luna, an)
     WHERE id_ordl = X

10.5. Închidere forțată (arhivare — pentru tipuri cu inch_validare=0)

[VFP user click "Inchide comanda" pe tip POST_GARANTIE/etc.]
  ↓
VFP SQL: begin pack_auto.dev_arhiveaza_comanda(pnIdOrdl, gnIdUtil); end;
  ↓
PACK_AUTO.DEV_ARHIVEAZA_COMANDA:
  1. Verifică CALENDAR luna curentă deschisă
  2. UPDATE DEV_ORDL SET INCHIS_FORTAT=1, ID_UTIL_INCHIS, DATAORAINCHIS=SYSDATE

10.6. Facturare

Vezi secțiunea 7.4 de mai sus. IN SCOPE abia pentru phase 3-4.

10.7. Bonuri consum

Vezi secțiunea 8. Out of scope — e flux generic ROA.


11. Labelurile UI (Romanian)

Câmp DB Label UI (din VFP ground truth)
id_tip Tip comandă
nrinmat (via masiniclienti) Număr înmatriculare / Mașină
id_part (via masiniclienti.id_partener) Client
solicitari_client (derivat din norme) Operații solicitate
kmint Km la bord
ore_functionare Ore funcționare (pt utilitare)
termen Termen execuție
observatii Observații
defectiuni Defecțiuni
nr_dosar Nr. dosar (doar pentru tip=garanție)
id_inspector Inspector
id_asigurator Asigurator
id_part_ref Partener referent
id_agent Agent vânzări

Toast-uri (convenție ROA2WEB din ReceiptCreateUnifiedView.vue):

  • Success: summary="Comandă creată", detail="Nr ${nr_comanda}"
  • Business error: summary="Validare", detail=<mesaj SP după strip prefix ORA-20xxx>
  • Infra: summary="Eroare conexiune" (503) / "Eroare internă" (500)

12. Implicații pentru prototype-ul roa2web

12.1. Scope wall reconfirmat

Prototype-ul scrie 1 SP minimal pentru 1 acțiune = creare comandă. Tot restul (normare, validare operații/comandă, arhivare, facturare, bonuri consum, estimare) e out of scope.

12.2. Opțiunea 3 (SP nou minimal) — actualizată

Față de v2, acum știm exact ce face pack_auto.dev_adauga_lucrare versiunea lungă. Versiunea minimală a SP-ului nostru va:

CREATE OR REPLACE PROCEDURE MARIUSM_AUTO.SP_CREEAZA_COMANDA_PROTOTIP(
  p_id_tip          IN NUMBER,      -- FK dev_tip_deviz.id_tip
  p_id_masiniclient IN NUMBER,      -- FK dev_masiniclienti.id_masiniclient
  p_kmint           IN NUMBER,
  p_termen          IN DATE,
  p_id_util         IN NUMBER,
  p_nr_comanda      IN VARCHAR2,    -- generat în Python cu prefix (G/R/P/PR/C)
  p_id_ordl         OUT NUMBER,
  p_numar_out       OUT VARCHAR2
) AS
  v_id_lucrare NUMBER;
  v_nr_existent NUMBER;
  v_now         DATE := SYSDATE;
BEGIN
  -- 1. Duplicate-check (paritate cu pack_auto)
  SELECT COUNT(*) INTO v_nr_existent
    FROM MARIUSM_AUTO.NOM_LUCRARI
   WHERE sters = 0 AND nrord = p_nr_comanda;
  IF v_nr_existent > 0 THEN
    RAISE_APPLICATION_ERROR(-20001,
      'Mai exista o comanda cu numarul ' || p_nr_comanda);
  END IF;

  -- 2. Parent INSERT (trigger-ul alocă id_lucrare + populează pack_sesiune.dev_idLucrare)
  INSERT INTO MARIUSM_AUTO.NOM_LUCRARI (nrord, id_mod)
    VALUES (p_nr_comanda, 1200)
    RETURNING id_lucrare INTO v_id_lucrare;

  -- 3. Child INSERT minimal — doar coloane obligatorii + clientul (prin masiniclient)
  INSERT INTO MARIUSM_AUTO.DEV_ORDL (
    an, luna,
    id_lucrare,
    datai, dataoraad,
    id_util_ad,
    id_masiniclient,
    id_tip,
    kmint,
    termen
  ) VALUES (
    EXTRACT(YEAR FROM v_now), EXTRACT(MONTH FROM v_now),
    v_id_lucrare,
    v_now, v_now,
    p_id_util,
    p_id_masiniclient,
    p_id_tip,
    p_kmint,
    p_termen
  ) RETURNING id_ordl INTO p_id_ordl;

  p_numar_out := p_nr_comanda;
END;
/

~30 linii PL/SQL, două INSERT-uri, zero dependency pe pack_contafin / STRINGAGG / pack_sesiune — minim absolut ca să probeze ipoteza #1 (Python + oracledb + OUT params + PL/SQL procedure call pe un INSERT dual cu RETURNING).

Trigger-ele rulează oricumpack_sesiune.dev_idLucrare și dev_idOrdl vor fi populate, dar nu le citim. E trivial de demonstrat că e safe: pattern-ul Oracle RETURNING INTO e standard.

Coloane SĂRITE pe care SP-ul real le are:

  • id_inspector, id_asigurator — folosite doar pentru service cu asigurator
  • nr_dosar, pcNrDosar — dosar daună
  • ore_functionare, pnOreFct — pentru utilitare
  • solicitari_client (agregat din STRINGAGG) — derivat din CSV, dispensabil pentru prototype
  • observatii, defectiuni — free text opțional
  • id_part_ref — referent
  • proc_tvav (via pack_contafin.getCotaTVAStandard) — dacă e NOT NULL vor primi default implicit (NULL); dacă schema real e NOT NULL, adăugăm valoarea 19 hardcodat

De verificat în săpt 3: rulează DESC MARIUSM_AUTO.DEV_ORDL sau din mariusm_ddl_export.sql linia 565 — PROC_TVAV e NUMBER(10,4) nullable, deci OK.

12.3. GRANTS pentru ROA_WEB user

CREATE USER ROA_WEB IDENTIFIED BY "...";
GRANT CONNECT, CREATE SESSION TO ROA_WEB;
GRANT EXECUTE ON MARIUSM_AUTO.SP_CREEAZA_COMANDA_PROTOTIP TO ROA_WEB;

-- Pentru read-only selectors (ipoteza #3 = grants model funcționează)
GRANT SELECT ON MARIUSM_AUTO.AUTO_VMASINICLIENTI TO ROA_WEB;
GRANT SELECT ON MARIUSM_AUTO.DEV_TIP_DEVIZ TO ROA_WEB;

12.4. Test negativ pentru ipoteza #3

-- Connected as ROA_WEB:
INSERT INTO MARIUSM_AUTO.DEV_ORDL ... ;                  -- așteptat: ORA-00942
SELECT * FROM MARIUSM_AUTO.DEV_ORDL WHERE ROWNUM < 2;    -- așteptat: ORA-00942
EXEC MARIUSM_AUTO.SP_CREEAZA_COMANDA_PROTOTIP(...);       -- așteptat: succes + row inserted

13. Gap-uri rămase (de acoperit după sapt 3)

  • PACK_SESIUNE.pck citit — de confirmat că dev_idLucrare, dev_idOrdl, getAn, getLuna, GET_ANRON, GET_LUNARON, get_cod, get_id_util sunt toate exported și nu ascund ceva surprinzător (nu am citit încă body-ul, doar referințe).
  • PACK_CONTAFIN.pck citit — de confirmat getCotaTVAStandard(luna, an) și get_idFact().
  • PACK_FACTURARE.pck citit — necesar doar când intrăm în flux-ul de facturare (phase 3-4).
  • DEV_TIP_DEVIZ.inch_validare per rând — rulează query-ul de verificare:
    SELECT id_tip, denumire, sters, inch_validare FROM MARIUSM_AUTO.DEV_TIP_DEVIZ ORDER BY id_tip;
    
  • MV_ORDL_MAT materialized view — de verificat refresh schedule; dacă refresh e "on commit" atunci UPDATE-urile pe RUL sunt imediate în AUTO_VORDL_MAT; dacă e "on demand" cu DBMS_JOB atunci e latency în UI.
  • pack_audit.verifica_val — folosit de toate trigger-ele _BEFOUPD. E dependency ascuns pentru orice UPDATE pe NOM_LUCRARI, DEV_ORDL, DEV_OPER, etc. Nu e folosit la INSERT, deci prototype-ul (care doar inserează) nu-l atinge.

14. Referințe

  • Ground truth DDL: docs/service-auto/mariusm_ddl_export.sql (5127 linii)
  • Pachete production: pack_auto.pck, PACK_FACTURARE.pck, PACK_SESIUNE.pck, PACK_CONTAFIN.pck, PACK_COMENZI.pck (toate în docs/service-auto/)
  • VFP consumer code: gitea.romfast.ro/romfast/vfp_roaauto/Programe/oproceduri_devize.prg (generare_com, normare_comanda, factureaza_comanda, factureaza_deviz)
  • Manual utilizator: docs/service-auto/manual_ROAAUTO.pdf
  • Plan master: docs/service-auto/claude-main-design-20260411-rethink.md