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>
780 lines
57 KiB
Markdown
780 lines
57 KiB
Markdown
# Design: Service Auto Web — Learning + Talent-Risk Hedge (rethink v2)
|
||
|
||
Generated by /plan-ceo-review on 2026-04-11 (pivot from the scrapped 2026-04-10 doc)
|
||
Revised by /plan-ceo-review on 2026-04-11 (v2 after HOLD SCOPE review + outside voice)
|
||
Branch: feat/service-auto
|
||
Repo: romfast/roa2web
|
||
Status: ACTIVE
|
||
Owner: Marius (ERP patron + sole dev)
|
||
Supersedes: `claude-main-design-20260410-205024.md` — premise invalidated (old doc was a product delivery plan; real intent is learning + capability hedge)
|
||
|
||
## What this is (and what it is NOT)
|
||
|
||
**This is:** a side-exploration prototype. Part learning project (Vue 3 + FastAPI async +
|
||
oracledb + PrimeVue), part strategic hedge against the "VFP is dead and I can't find
|
||
programmers" problem. Target = 1 end-to-end screen with 1 SP write, on the existing test
|
||
schema MARIUSM_AUTO at the office server `10.0.20.121/ROA`. Budget ≈ 2-4 hrs/week, ≈48-96
|
||
hours total over 24 weeks (doubled from the original 12-week plan after sincere budget
|
||
recalibration — see Review Corrections).
|
||
|
||
**This is NOT:** a product, an MVP, a migration plan, or a commitment to ship anything to
|
||
any client. The 4 existing clients stay on VFP + Oracle XE local. Zero migration. Zero
|
||
customer-facing delivery. Zero timeline pressure.
|
||
|
||
**The deliverable is NOT a demo.** The deliverable is **a reusable template for future
|
||
Oracle-backed modules + a decision log**. See "Final deliverable" below.
|
||
|
||
## Strategic driver (the one that matters)
|
||
|
||
Visual FoxPro is a dead language. Marius cannot hire programmers willing to learn it.
|
||
Every year on VFP is another year of compounding talent risk on an ERP that powers 4
|
||
long-term clients and generates stable revenue. The only realistic path to "someone else
|
||
can maintain this eventually" is moving incrementally to web stacks (Python/Vue) where the
|
||
labor pool exists.
|
||
|
||
**Constraint that makes this hard:** Oracle coupling. The ERP has 25 years of PL/SQL,
|
||
cross-schema synonyms, tenant-per-schema architecture. Postgres migration is not 1:1 —
|
||
the PL/SQL and schema mechanics don't translate cleanly. Therefore the migration path is
|
||
**"stay on Oracle, switch UI + business logic layer to Python/Vue, keep PL/SQL as the
|
||
durable layer."** Service auto is the lowest-risk place to probe whether this path works.
|
||
|
||
**Honest caveat on the hedge thesis:** PL/SQL + Oracle domain knowledge is itself a
|
||
scarce skill on the Romanian market. This prototype does NOT solve the hiring pipeline
|
||
problem for PL/SQL maintainers. What it solves is the Python+Vue+integration layer — the
|
||
UI/API half of the stack — where the labor pool is genuinely larger. The hedge is
|
||
"replace the half of the stack where hiring is easier"; it is NOT "fix the hiring problem
|
||
in one shot." This distinction matters for phase 2 scoping.
|
||
|
||
**Success definition for this prototype:** after 24 weeks (or sooner), Marius has
|
||
direct evidence (working code, not hand-wavy) that the roa2web monolith can drive Oracle
|
||
business logic end-to-end via PL/SQL stored procedures, AND a reusable template
|
||
documenting exactly how. If that evidence is positive, the same pattern applies to the
|
||
next module. If it's negative, Marius knows this before sinking years into it.
|
||
|
||
## The prototype — minimum viable experiment
|
||
|
||
One screen, one SP, one test schema, one developer. Absolute scope wall.
|
||
|
||
### Target feature
|
||
|
||
**Screen:** `ComandaNoua.vue` — formular creare comandă nouă service auto. Minimal
|
||
fields: tip comandă (select 4 opțiuni), client (dropdown **hardcoded în Vue** — 2-3
|
||
clienți test cu 1-2 mașini fiecare), operații solicitate (textarea). Submit → backend →
|
||
PL/SQL → insert row → return ID → display "Comanda X creată" via **PrimeVue Toast**.
|
||
|
||
**SP:** `SP_CREEAZA_COMANDA(p_tip IN, p_client_id IN, p_masina_id IN, p_operatii IN,
|
||
p_comanda_id OUT, p_numar OUT)`. **Insert într-un tabel DEDICAT de comenzi** (nume real
|
||
în MARIUSM_AUTO — de verificat în VFP înainte de a scrie SP-ul, vezi pregătire săpt 3).
|
||
**NU inserează în ACT** (registrul jurnal) — ACT se hit-uiește doar la facturare, care e
|
||
NOT IN SCOPE pentru prototype. Validare minimă, return ID + număr.
|
||
|
||
**Schema:** **MARIUSM_AUTO** — schemă dedicată de test, deja existentă pe serverul de la
|
||
biroul Marius (`10.0.20.121/ROA`), care nu e folosită de altcineva. Zero conexiune la
|
||
schemele de producție ale celor 4 clienți. Zero copy / impdp necesar — schema există deja.
|
||
|
||
**User Oracle tehnic:** **`ROA_WEB`** — user nou dedicat app-ului FastAPI, cu grants
|
||
explicite per SP (`GRANT EXECUTE ON MARIUSM_AUTO.SP_CREEAZA_COMANDA TO ROA_WEB`), fără
|
||
acces direct la tabele. Pattern multi-tenant compatibil — același user va avea grants pe
|
||
alte scheme în phase 2 dacă probează.
|
||
|
||
### Things this prototype will probe (the real learning)
|
||
|
||
Fiecare din acestea e o ipoteză pe care prototype-ul trebuie să o confirme sau să o
|
||
infirme:
|
||
|
||
| # | Ipoteză | Cum o probez |
|
||
|---|--------|-------------|
|
||
| 1 | `python-oracledb` async cleanly calls PL/SQL proc cu IN+OUT params | Săpt 1 POC: `poc/hello_async_out.py` cu `oracledb.connect_async()` + `cursor.var(oracledb.NUMBER)` + `await cursor.callproc('test_out', [out])`. **GATE**: dacă merge curat, prototype-ul continuă pe true-async. Dacă NU merge, fallback la pattern-ul sync-facade din `treasury_service.py` (deja proof-ed în prod). Fallback e pre-aprobat, NU blochează săpt 2+. |
|
||
| 2 | `session_callback` pentru CURRENT_SCHEMA switching nu leak-uiește între requests concurente | Săpt 4: 2 conexiuni paralele pe **aceeași schemă MARIUSM_AUTO**, ambele setează CURRENT_SCHEMA, rulează CALL-uri distincte, verific cu log-uri că nu se încurcă cursor tag reuse. **Limitare acceptată conștient:** testul pe 1 schemă nu dovedește 100% izolarea la multi-schemă — pentru asta ar trebui o a doua schemă test (ex: copie CLEVER), care e în afara budget-ului. Probă de primitive, nu de multi-schemă. |
|
||
| 3 | GRANTS de tip "EXECUTE ON SP, zero INSERT/UPDATE/DELETE pe tabele" țin în practică | Săpt 3: user `ROA_WEB` încearcă `INSERT INTO MARIUSM_AUTO.ACT` → `ORA-00942` sau `ORA-01031`; `SELECT * FROM MARIUSM_AUTO.ACT` → `ORA-00942`; `EXEC MARIUSM_AUTO.SP_CREEAZA_COMANDA(...)` → success. Un test automat pytest-marcat `integration` care rulează local. |
|
||
| 4 | `RAISE_APPLICATION_ERROR(-20001, 'mesaj cu diacritice ă î ș ț â')` ajunge în Vue ca eroare user-friendly, encoding corect | Săpt 11-12: SP aruncă eroare (client inexistent, tip invalid, operatii gol), serviciul traduce `oracledb.DatabaseError.code` la HTTP status (20001-20999 → 422 business, 12541/12170 → 503 infra, rest → 500), Vue afișează PrimeVue Toast cu mesajul. Obligatoriu test pe un mesaj cu diacritice pentru a proba `NLS_LANG` / encoding chain end-to-end. |
|
||
| 5 | FastAPI hot-reload + Vite dev-server + SSH tunnel Oracle e un DX acceptabil pentru side-work de 2-4h/săpt | Săpt 1: măsor timpul de la "save file" la "văd rezultatul" — dacă e > 10s, fix ecosistem înainte de content. **Documentat** în `docs/service-auto/week1-notes.md` cu numere concrete. |
|
||
| 6 | **Flux-ul de auth multi-server existent** (login → `email_server_cache` → `CONTAFIN_ORACLE.UTILIZATORI` → JWT cu `server_id` → `AuthenticationMiddleware` → `request.state.server_id`) suportă un server nou **fără modificări la shared code** | Săpt 3: (a) adaugă `MARIUSM_AUTO` la `ORACLE_SERVERS` în `backend/.env`; (b) `INSERT INTO CONTAFIN_ORACLE.UTILIZATORI (username, server_id, ...)` pentru Marius; (c) log in prin UI, verifică că server selector arată `mariusm_test`; (d) după login, inspectează JWT payload în browser devtools — confirmă `server_id='mariusm_test'`; (e) verifică ce returnează `auth_service.get_user_companies('MARIUS M', 'mariusm_test')` — dacă MARIUSM_AUTO nu are `V_NOM_FIRME`, vezi dacă login-ul tolerează `companies=[]` sau dacă trebuie un fake. Documentat în `week3-auth-audit.md`. **Gate**: dacă auth-ul cere modificări la shared code pentru a accepta un server non-CONTAFIN, scope creep → replanning sau kill criterion. |
|
||
|
||
Dacă oricare din 1-6 eșuează cu un răspuns clar, **prototype-ul s-a încheiat cu succes** —
|
||
learning obținut, decision point clar, zero cod irosit care trebuie să supraviețuiască.
|
||
|
||
## Scope wall — what is explicitly NOT in this prototype
|
||
|
||
Toate aceste subiecte aparțin doc-ului scrapped sau sunt defer-uri la TODO-phase2. Niciunul nu intră aici:
|
||
|
||
- ❌ Cei 4 clienți existenți, vreodată. Ei rămân pe VFP + XE local. Zero atingere.
|
||
- ❌ Migrare scheme, SSH tunnel VFP→Oracle central, decomisionare XE local
|
||
- ❌ eFactura / ANAF / SPV upload — irelevant fără producție
|
||
- ❌ Feature flags per-tenant, `FEATURE_FLAGS` table
|
||
- ❌ `SP_BON_CONSUM` (cross-schema synonyms), `SP_VALIDEAZA_COMANDA`, `SP_EMITE_FACTURA` — toate deferred
|
||
- ❌ **Insert în ACT la creare comandă** — ACT e registrul jurnal, se hit-uiește la facturare, care e NOT IN SCOPE
|
||
- ❌ `reconcile.py`, invariant checking, parallel testing cu VFP
|
||
- ❌ Runbook rollback, monthly restore drill, uptime monitoring, Telegram alerts
|
||
- ❌ 5 ecrane MVP (doar 1 — absolute wall)
|
||
- ❌ Mobile, responsive, iPad, tablet — desktop-only, viewport-whatever-is-convenient (accesibilitate: PrimeVue defaults gestionează keyboard tab order, ARIA labels, focus ring — **zero work custom**; nu e "ignorat", e "inherited free")
|
||
- ❌ Playwright e2e, smoke parity pentru SPs
|
||
- ❌ Endpoint `/clienti` sau `/masini` pentru populare dropdown — hardcoded în Vue
|
||
- ❌ Onboarding client nou, referral pipeline, assignment cu telefoane
|
||
- ❌ Phase 2, Phase 3, Phase 4 — menționate doar în decision-log.md la finalul prototype-ului
|
||
- ❌ SLA, RPO, RTO, warm standby, backup discipline
|
||
- ❌ `X-Idempotency-Key`, double-submit protection, retry policy
|
||
- ❌ A doua schemă de test (ex: copie CLEVER) pentru probă multi-schemă — costă prea mult budget
|
||
|
||
Dacă în timpul construcției una dintre aceste tentații începe să pară "doar 30 min în
|
||
plus", răspunsul e **scriu o notă, nu scriu cod**. Scope wall ține. Note de tipul
|
||
"probabil o să am nevoie de X pentru phase 2" merg în `docs/service-auto/TODO-phase2.md`,
|
||
nu în codul prototype-ului.
|
||
|
||
## Review corrections (from /plan-ceo-review session, 2026-04-11)
|
||
|
||
Această secțiune documentează ce s-a corectat față de prima versiune a planului, pentru a
|
||
fi transparent despre gândirea care a dus la planul final.
|
||
|
||
### Correction 1 — Nu se creează `MarciusLabPool` nou (+ patch minim la `oracle_pool.py`)
|
||
|
||
**Prima versiune** spunea: "modifică `OracleMultiPool` sau adaugă wrapper" și "creează NEW
|
||
minimal helper `MarciusLabPool`". **Realitate:** `OracleMultiPool` la
|
||
`shared/database/oracle_pool.py` are deja suport multi-server prin `_pools: Dict[server_id, ConnectionPool]`.
|
||
MARIUSM_AUTO se adaugă ca **server nou** prin `register_server('mariusm_test', host='10.0.20.121', port=1521, user='ROA_WEB', password='...', service_name='ROA')` — zero pool nou, zero clasă nouă.
|
||
|
||
**Însă NU e chiar "zero refactor".** `register_server` (linii 55-83) acceptă `**kwargs` dar le
|
||
ignoră — nu le stochează în `_pool_configs`. `_get_or_create_pool` (linii 108-117)
|
||
construiește `pool_params` dintr-un set fix de chei. **Pentru a activa `session_callback`
|
||
(ipoteza #2), trebuie un patch backward-compatible de ~8 linii la `shared/database/oracle_pool.py`:**
|
||
|
||
```python
|
||
def register_server(self, ..., session_callback=None, **kwargs):
|
||
self._pool_configs[server_id] = {
|
||
...
|
||
'session_callback': session_callback,
|
||
}
|
||
|
||
# în _get_or_create_pool, după pool_params:
|
||
if config.get('session_callback'):
|
||
pool_params['session_callback'] = config['session_callback']
|
||
```
|
||
|
||
Zero caller-i existenți folosesc `session_callback`, deci patch-ul e backward-compatible.
|
||
**Planificat explicit în săpt 5** (vezi timeline) — nu e "scope creep", e un task minim
|
||
necesar și conștient de scope wall-ul shared code.
|
||
|
||
### Correction 2 — Pattern sync-in-async-facade e deja proof-ed în prod
|
||
|
||
**Prima versiune** trata ipoteza #1 ("oracledb async + OUT params") ca unknown. **Realitate:**
|
||
`backend/modules/reports/services/treasury_service.py` deja apelează SPs cu OUT params de
|
||
tip `oracledb.CURSOR` și `oracledb.NUMBER` în producție, folosind pattern-ul
|
||
sync-in-async-facade (`async with oracle_pool.get_connection(...)`, cursor sync, fără
|
||
`await` pe execute/callproc). **Consecință:** ipoteza #1 e reîncadrată ca probă a
|
||
pattern-ului `oracledb.connect_async()` **true-async** — nou, neprobeat în codebase.
|
||
Săpt 1 e **gate** (vezi mai sus): dacă true-async merge → adoptă; dacă nu → fallback la
|
||
sync-facade care e deja dovedit.
|
||
|
||
### Correction 3 — SP nu inserează în ACT
|
||
|
||
**Prima versiune** spunea "Insert în ACT, validare minimă". **Realitate:** ACT e registrul
|
||
jurnal contabil (double-entry bookkeeping, clasa 6/7 — vezi
|
||
`.claude/rules/financial-indicators.md`). O comandă de service auto la CREARE aterizează
|
||
într-un **tabel dedicat** (ex: `COMENZI`, `COMD_SA`, nume real de verificat în VFP), NU
|
||
în ACT. ACT se hit-uiește la **facturare**, care e NOT IN SCOPE. SP-ul corect face INSERT
|
||
în tabela dedicată de comenzi.
|
||
|
||
**Task în săpt 3 (preparare):** înainte de a scrie SP_CREEAZA_COMANDA, clonează repo-ul
|
||
gitea al sursei VFP (`gitea.romfast.ro/romfast/vfp_roaauto` — importat 2026-04-11 ca
|
||
ground truth pentru acest prototype), `grep` după fluxul "creează comandă nouă service
|
||
auto" în sursele .PRG / .SCX, identifică tabelele atinse și SP-urile / UPDATE-urile
|
||
existente, documentează în `docs/service-auto/tabele-service-auto.md`. **Nu mai e nevoie
|
||
să deschizi VFP-ul producție** — gitea e strict mai sigur (zero risk de modificare
|
||
accidentală) și mai rapid (text search vs IDE navigation).
|
||
|
||
**Audit preliminar deja scris 2026-04-11**: `docs/service-auto/tabele-service-auto.md` e
|
||
un **DRAFT** generat de Claude pe baza clonei gitea. Conține (a) schema reală `comenzi` /
|
||
`vcomenzi` cu ~28 coloane, (b) SP-ul real de creare **`pack_auto.dev_adauga_lucrare`**
|
||
(17 params IN, 1 OUT — **substanțial diferit** de ipoteza inițială a planului), (c) enum
|
||
real `tip_comanda` (ID-uri 1-7 cu prefixe G/R/P/PR/C), (d) label-urile Romanian pentru
|
||
câmpuri, (e) lista funcțiilor `pack_auto.*` și `pack_comenzi.*` relevante, (f) query-uri
|
||
SQL de verificat în săpt 3 împotriva schemei reale. Task-ul săpt 3 e **să confirme** draft-ul
|
||
împotriva bazei reale, nu să-l scrie de la zero. Vezi **Correction 12** pentru implicațiile
|
||
strategice ale descoperirii SP-ului existent.
|
||
|
||
### Correction 12 — Tabela reală e `DEV_ORDL`, SP-ul are două versiuni, și există un `pack_sesiune` coupling
|
||
|
||
**Prima versiune a planului** presupunea că:
|
||
- Tabela e `comenzi` (fizică)
|
||
- SP-ul `SP_CREEAZA_COMANDA` va fi nou, simplu, cu ~4 IN + 2 OUT
|
||
- Nu există dependențe ascunse
|
||
|
||
**Realitate (2026-04-11 post-audit pe gitea VFP + scripturi instalare):**
|
||
|
||
**(a) Inheritance pattern: comandă în `nom_lucrari` + extensie auto în `dev_ordl`**
|
||
(confirmat de Marius 2026-04-11). `nom_lucrari` e tabela parent din ROA ERP generic —
|
||
conține header-ul "comenzii" (nrord), vizibil în ACT (registrul jurnal) și RUL (rulaje
|
||
gestiune) **doar când comanda e referențiată la facturare**. `dev_ordl` e extensia
|
||
ROAAUTO (id_lucrare FK → nom_lucrari.id_lucrare) care conține toate detaliile service auto
|
||
(mașină, km, termen, tip deviz, etc.). Crearea unei comenzi face INSERT în **AMBELE tabele**,
|
||
în ordine FK parent → child. **Crearea nu touch-uiește ACT/RUL** — Correction 3 rămâne validă.
|
||
Ce vedem ca `comenzi` / `vcomenzi` e un VIEW denormalizat care JOIN-uiește cele două tabele
|
||
+ lookup-uri (`dev_tip_deviz`, `dev_masiniclienti`, `parteneri`).
|
||
|
||
**(b) Tabela enum pentru `tip_comanda` este `DEV_TIP_DEVIZ`** — cu schema:
|
||
```sql
|
||
DEV_TIP_DEVIZ (ID_TIP NUMBER(5) PK, DENUMIRE VARCHAR2(50), STERS NUMBER(1))
|
||
```
|
||
Seed install (`initializari.sql`): `{1:'POST GARANTIE', 2:'GARANTIE', 3:'REGIE', 4:'PREGATIRE', 5:'REGIE 2'}`.
|
||
IDs 6 și 7 adăugate în producție: `{6:'Productie' (prefix PR), 7:'Constatare' (prefix C)}`
|
||
(confirmat de Marius 2026-04-11).
|
||
|
||
**(c) Există DOUĂ versiuni ale `dev_adauga_lucrare`**:
|
||
- **v1 INSTALL** — `pack_devize.dev_adauga_lucrare(12 IN + 1 OUT)` — body vizibil în
|
||
`Scripturi_instalare/packages.sql:182-212`
|
||
- **v2 PRODUCȚIE** — `pack_auto.dev_adauga_lucrare(17 IN + 1 OUT)` — apelat din VFP
|
||
(`Programe/oproceduri_devize.prg:147-148`), **body NU e în sursă** (pachet adăugat
|
||
post-install, trăiește doar în DB-ul lui Marius). 5 params noi: `nr_dosar`, `ore_fct`,
|
||
`operatii_csv`, `observatii`, `defectiuni`, `id_part_ref`.
|
||
|
||
**(d) `pack_sesiune.dev_idLucrare` NU e un bug, e convenție ROA ERP** — pattern-ul e:
|
||
trigger `TRG_NOM_LUCRARI_BEFOINS` populează `pack_sesiune.dev_idLucrare := :new.id_lucrare`
|
||
după INSERT-ul pe `nom_lucrari`; apoi INSERT-ul pe `dev_ordl` citește acel session state.
|
||
Confirmat prin pattern-ul identic la `dev_ordl` (`triggere.sql:1165-1172`:
|
||
`SEQ_DEV_ORDL.NEXTVAL INTO :new.id_ordl` + `pack_sesiune.dev_idOrdl := :new.id_ordl`) și
|
||
la `dev_oper` (`triggere.sql:928`).
|
||
|
||
**Pentru roa2web: bypass trivial** — folosim `RETURNING id_lucrare INTO v_local` după
|
||
INSERT-ul pe `nom_lucrari`. Trigger-ul încă rulează și populează session state (irelevant
|
||
pentru noi), iar noi citim `id_lucrare` local prin RETURNING. Standard Oracle. Zero dependency.
|
||
|
||
**(e) Flux-ul real** — v1 body face 3 operații:
|
||
1. `INSERT INTO NOM_LUCRARI (NRORD, ID_MOD) VALUES (nr_com, 1200)` — **parent** (header
|
||
generic) — ESENȚIAL
|
||
2. `INSERT INTO DEV_ORDL (..., id_lucrare, ...) RETURNING id_ordl` — **child** (extensia
|
||
auto, FK la parent) — ESENȚIAL
|
||
3. `UPDATE DEV_MASINICLIENTI SET kmint=... WHERE id_masiniclient=...` — sync odometru —
|
||
OPȚIONAL (skip pentru prototype)
|
||
|
||
Deci nu e "flux cu side effects" — e un pattern de inheritance normal (parent + child),
|
||
plus o sync colaterală opțională.
|
||
|
||
### Trei opțiuni strategice (decise în săpt 3/4 după extragerea body-ului real)
|
||
|
||
| # | Strategie | Pro | Contra |
|
||
|---|---|---|---|
|
||
| **1** | Reuse `pack_auto.dev_adauga_lucrare` v2 direct | Hedge max — dovedește reuse pachet producție cu side-effects | Depinde de `pack_sesiune`; risc sabotaj la primul call |
|
||
| **2** | Reuse `pack_devize.dev_adauga_lucrare` v1 | Body vizibil în sursă, 5 params mai puțin | Același `pack_sesiune` bug, tot 12 params |
|
||
| **3** | **SP nou minimal** `SP_CREEAZA_COMANDA_PROTOTIP` cu INSERT direct în `dev_ordl` + `id_lucrare=0` + skip side-effects | Control total, zero dependențe, ~20 linii PL/SQL, testabil clean, probează ipoteza #1 perfect | Bypass-uie business logic (dar asta oricum e phase 2) |
|
||
|
||
**Recomandare actualizată: OPȚIUNEA 3** (SP nou minimal cu două INSERT-uri parent+child).
|
||
|
||
Motivul: deși `pack_sesiune` s-a dovedit a nu fi bug ci convenție, reuse-ul direct al
|
||
v1/v2 aduce alte complicații (17 params pentru v2, business logic care ar trebui
|
||
reimplementată sau bypass-ată, etc.). **Opțiunea 3 cu cele două INSERT-uri în ordine**
|
||
(nom_lucrari → dev_ordl, cu `RETURNING id_lucrare`) e **exact pattern-ul corect pentru
|
||
inheritance**, nu un bypass urât. E idiomul Oracle modern (post-9i când RETURNING a devenit
|
||
standard), iar pack-urile legacy foloseau `pack_sesiune` doar pentru că n-aveau RETURNING
|
||
când au fost scrise inițial.
|
||
|
||
**Rezultatul**: prototype-ul dovedește ipoteza #1 pe un SP realist care atinge **două**
|
||
tabele în ordine FK corectă (nu unul banal `test_out`), iar template deliverable-ul din
|
||
săpt 21-22 documentează exact pattern-ul de inheritance parent+child cu RETURNING —
|
||
**direct reutilizabil** pentru orice alt modul ROAAUTO sau ROA.
|
||
|
||
**SP minimal propus (Opțiunea 3):** vezi §4.3 din `docs/service-auto/tabele-service-auto.md`
|
||
pentru corpul complet (~40 linii PL/SQL): două INSERT-uri parent (nom_lucrari) + child
|
||
(dev_ordl) cu `RETURNING id_lucrare` între ele, zero dependency pe `pack_sesiune`.
|
||
|
||
### Impact asupra timeline
|
||
|
||
- **Săpt 3** — task-ul își schimbă scopul: confirmă existența `pack_devize`, `pack_auto`,
|
||
`pack_sesiune` în MARIUSM_AUTO + citește body-ul real al `pack_auto.dev_adauga_lucrare`
|
||
pentru decizie finală (opțiunea 1 vs 3). Query din §4.2 tabele-service-auto.md.
|
||
- **Săpt 7-8** — "scrie SP nou" devine "scrie SP_CREEAZA_COMANDA_PROTOTIP" (opțiunea 3).
|
||
Simplu: INSERT direct în `dev_ordl` + `RETURNING id_ordl`.
|
||
- **Ipoteza #1** rămâne la fel de puternică — testezi că Python+oracledb cu OUT params
|
||
apelează un SP real care face INSERT + RETURNING, nu un `test_out(p OUT NUMBER)` trivial.
|
||
- **Ipoteza #2** (`session_callback`) devine **mai relevantă ca niciodată** — `pack_sesiune`
|
||
e exact genul de state care ar putea fi inițializat prin session_callback pattern. Săpt 5
|
||
task-ul `session_callback` devine și o investigație preliminară pentru phase 2.
|
||
|
||
**Scope wall ține** — tot 1 ecran, tot 1 SP, tot 1 schema test, tot write-only, deliverable =
|
||
template + decision-log. Ce se schimbă: **țintim o tabelă reală (`dev_ordl`), folosim un enum
|
||
real (`dev_tip_deviz`), și documentăm un path clar spre reuse-ul pachet-urilor legacy pentru
|
||
phase 2**. Hedge-ul devine mai credibil, nu mai slab.
|
||
|
||
### Correction 13 — Ground truth complet din MARIUSM_AUTO (2026-04-11 later)
|
||
|
||
**Ce s-a schimbat:** Marius a furnizat versiunile reale din producție:
|
||
- `docs/service-auto/mariusm_ddl_export.sql` (5127 linii DDL: tabele + views + triggere)
|
||
- `docs/service-auto/pack_auto.pck`, `PACK_FACTURARE.pck`, `PACK_SESIUNE.pck`,
|
||
`PACK_CONTAFIN.pck`, `PACK_COMENZI.pck` — body-urile reale
|
||
|
||
**Ce s-a invalidat:**
|
||
- **`vfp_roaauto/Scripturi_instalare/packages.sql` = alt produs** ("devize producție"), NU
|
||
service auto. Toate referințele v2 la `pack_devize.dev_adauga_lucrare` erau la un pachet
|
||
care nu există în MARIUSM_AUTO.
|
||
- **`VCOMENZI` din MARIUSM_AUTO nu e pentru service auto** — e pentru ROA ERP base
|
||
(vânzări/contracte generice), cu coloane `id_codclient`/`interna`/`id_masina` care
|
||
nu aparțin flux-ului auto.
|
||
- **`dev_distribuie_timp_n`** are semnătură nouă: `(v_luna, v_an)` nu `(v_gcs, v_filtru)`.
|
||
|
||
**Ce s-a reconfirmat ca fiind corect:**
|
||
- Pattern-ul de inheritance `NOM_LUCRARI` (parent) + `DEV_ORDL` (child, FK `id_lucrare`)
|
||
- `TRG_NOM_LUCRARI_BEFOINS` populează `pack_sesiune.dev_idLucrare` din `SEQ_NOM_LUCRARI.NEXTVAL`
|
||
- `TRG_DEV_ORDL_BEFOINS` populează `pack_sesiune.dev_idOrdl` din `SEQ_DEV_ORDL.NEXTVAL`
|
||
- Bypass `pack_sesiune` prin `RETURNING id_lucrare INTO v_local` e **trivial și safe**
|
||
(trigger-ul rulează oricum, noi îl ignorăm)
|
||
|
||
**Descoperiri NOI critice:**
|
||
1. **`DEV_ORDL` are 37 coloane în producție** (nu 28-30 cum estima v2), cu
|
||
`PROC_TVAV`, `SOLICITARI_CLIENT CLOB`, `OBSERVATII`, `DEFECTIUNI`, `NR_DOSAR`,
|
||
`ID_PART` (FK la NOM_PARTENERI — client direct, nu doar prin mașină), `ID_AGENT`,
|
||
`ID_PART_REF`, `ORE_FUNCTIONARE`, `IN_LUCRU`, `COADA_DEVIZ`, `ID_UTIL_INCHIS`,
|
||
`DATAORAINCHIS`, `DATA_IN_LUCRU`, `DATAORAINLUCRU`, `FACTUREZMIX`, `DATA_CURS`,
|
||
`ID_VALUTA_DEVIZ`, `INCHIS_FORTAT`. FK constraints ENABLE:
|
||
`FK_DEV_ORDL_001..006` pe `DEV_NOM_INSPECTORI`, `NOM_LUCRARI`, `NOM_PARTENERI` ×3,
|
||
`NOM_VALUTE`.
|
||
2. **`DEV_OPER` e polimorfic**: poate fi **manoperă** (`id_norme` non-NULL) SAU **linie
|
||
material** (`id_articol` non-NULL + `id_rul_aux` FK la mișcarea de stoc). Materialele
|
||
pe comandă nu au tabela `DEV_MAT` separată — sunt linii în `DEV_OPER` cu tip diferit.
|
||
3. **`DEV_ESTIMARI_REP`** e tabelă nouă (pre-sale estimate) — linii cu `id_lucrare` FK,
|
||
fiecare linie e fie manoperă fie material. `pack_auto.adauga_manopera_de` /
|
||
`adauga_material_de` scriu aici. View `AUTO_VESTIMARI_REP` cu `pack_sesiune.calculeaza_*`
|
||
pentru prețuri. **Out of scope** pentru prototype.
|
||
4. **`DEV_TIP_DEVIZ.INCH_VALIDARE`** (NUMBER(1) default 1) e flag-ul care decide între
|
||
**închidere prin validare** (`dev_valideaza_comanda`) sau **închidere prin arhivare**
|
||
(`dev_arhiveaza_comanda`). Citit prin `pack_auto.getOptiuneInchidere(id_tip)`.
|
||
5. **`actualizeaza_deviz` (pack_auto)** e procedura care replace-uiește vechiul
|
||
`dev_completeaza_rul`. Face 3 UPDATE-uri într-o tranzacție: `DEV_ORDL.PROC_TVAV`,
|
||
`RUL.ID_FACT` (pentru toate materialele consumate), și — condiționat de `id_set` în
|
||
(31003-31011) — `NOM_LUCRARI.ID_FACT`.
|
||
6. **Bonuri consum = flux generic ROA, nu `pack_auto`** — `ointroduceri.prg tip=3` scrie
|
||
direct în `RUL` + `RUL_AUXILIAR` cu `ID_LUCRARE` tag. `DEV_OPER` capturează liniile
|
||
prin `id_rul_aux` FK. **Out of scope.**
|
||
7. **View-urile UI**: `AUTO_NORMARE_COMENZI`, `AUTO_VALIDARE_COMENZI`, `AUTO_ORDL_FACTURARE`,
|
||
`AUTO_COMENZI_VALIDATE` (cu time-aware validat flag prin `pack_sesiune.getluna()`),
|
||
`AUTO_VORDL_MAN`, `AUTO_VORDL_MAT` (citește din `MV_ORDL_MAT` materialized view),
|
||
`AUTO_VESTIMARI_REP`.
|
||
8. **`pack_audit.verifica_val`** — trigger-ele `_BEFOUPD` pe `NOM_LUCRARI`, `DEV_ORDL`,
|
||
`DEV_OPER`, `DEV_OPER_MECANICI` apelează această procedură pentru fiecare câmp modificat
|
||
→ audit trail automat pentru TOATE UPDATE-urile. Triggerele `_BEFOINS` **nu** apelează
|
||
pack_audit — deci prototype-ul care doar inserează **nu atinge pack_audit**.
|
||
|
||
**Audit complet:** `docs/service-auto/tabele-service-auto.md` a fost rescris complet
|
||
(v3, ~500 linii) cu referințe directe la DDL + pack_auto + pack_facturare real. Conține:
|
||
- Diagrama ierarhiei `NOM_LUCRARI → DEV_ORDL → DEV_OPER → DEV_OPER_MECANICI`
|
||
- Schema reală `DEV_ORDL` (37 coloane) + `DEV_OPER` (polimorfic) + `DEV_ESTIMARI_REP`
|
||
- Map procedure → tabele pentru întreg `pack_auto` (17 proceduri/funcții)
|
||
- Flux VFP real pentru create, normare, validare operații, validare comandă, arhivare,
|
||
facturare (cu referințe la `pack_facturare.initializeaza_date_factura`,
|
||
`adauga_articol_factura_deviz`, `scrie_in_vanzari`)
|
||
- List complete de view-uri UI cu rolul fiecăruia
|
||
- SP minimal propus pentru prototype (Opțiunea 3, rafinată) — 30 linii PL/SQL, zero
|
||
dependențe pe `pack_contafin`/`STRINGAGG`/`pack_sesiune`, doar două INSERT-uri cu
|
||
RETURNING și un duplicate-check
|
||
|
||
**Scope wall reconfirmat**: prototype-ul rămâne la **creare comandă simplă**. Normare,
|
||
validare operații, validare comandă, arhivare, facturare, bonuri consum, estimare =
|
||
**phase 2+**. Fluxul complet e documentat ca referință viitoare, nu ca commitment.
|
||
|
||
**Impact asupra timeline:** **zero** — task-urile săpt 1-24 rămân identice, doar că săpt 7-8
|
||
("scrie SP_CREEAZA_COMANDA") are acum templatul PL/SQL exact definitivat în tabele-service-auto.md
|
||
§12.2, gata de copy-paste + commit.
|
||
|
||
**Impact asupra ipotezelor:** niciuna invalidată. Ipoteza #1 rămâne centrală — probă că
|
||
Python+oracledb apelează PL/SQL cu OUT params pe un INSERT dual cu RETURNING. Ipoteza #2
|
||
(`session_callback`) rămâne independentă. Ipoteza #3 (grants) este și mai **ușor de probat**
|
||
acum că știm exact cele două tabele atinse (`NOM_LUCRARI`, `DEV_ORDL`) și putem scrie
|
||
testul negativ cu nume fixe.
|
||
|
||
### Correction 4 — `connection.commit()` e explicit în pattern
|
||
|
||
**Prima versiune** nu menționa commit. **Realitate:** `oracledb` driver are autocommit OFF
|
||
default. Fără `connection.commit()` după `cursor.callproc`, SP-ul rulează dar datele NU se
|
||
salvează — **silent failure clasică**. Pattern-ul corect e:
|
||
|
||
```python
|
||
async with oracle_pool.get_connection('mariusm_test') as conn:
|
||
with conn.cursor() as cursor:
|
||
out_id = cursor.var(oracledb.NUMBER)
|
||
out_numar = cursor.var(oracledb.STRING, size=50)
|
||
cursor.callproc('SP_CREEAZA_COMANDA', [..., out_id, out_numar])
|
||
conn.commit() # <-- CRITICAL
|
||
```
|
||
|
||
**Test obligatoriu** în săpt 5-6: după `callproc + commit`, închide conexiunea, deschide
|
||
alta, `SELECT ... WHERE id = :id` — confirmă că row-ul persistă. Dacă nu, commit-ul e
|
||
problemă.
|
||
|
||
### Correction 5 — Error code classification e explicită în plan
|
||
|
||
**Prima versiune** zicea doar "ORA-20001 → toast". **Realitate:** există multe categorii
|
||
de erori Oracle, iar trducerea la HTTP trebuie să fie range-based:
|
||
|
||
| Cod Oracle | HTTP | Ce vede user-ul |
|
||
|---|---|---|
|
||
| 20001 — 20999 (`RAISE_APPLICATION_ERROR`) | 422 | Mesajul din SP, curat de prefix |
|
||
| 12541, 12170, 12154 (connection / listener errors) | 503 | "Serviciul bazei de date e temporar indisponibil" |
|
||
| 01017 (invalid credentials) | 500 + critical log | "Eroare de configurare. Contactați administratorul." |
|
||
| 00942 (table or view not exist — grants leak) | 500 + critical log | "Eroare internă. Contactați administratorul." |
|
||
| Orice alt cod | 500 + full log | "Eroare internă neașteptată" |
|
||
|
||
Săpt 11-12: scrie service-layer-ul cu `try/except oracledb.DatabaseError` + clasificare
|
||
pe range. Test cu diacritice în mesaj.
|
||
|
||
### Correction 6 — Logging persistent per-modul
|
||
|
||
**Prima versiune** nu menționa logging. **Realitate:** `backend/main.py:57` folosește
|
||
`logging.basicConfig` cu output doar în stdout. Dacă în săpt 5 vrei să recitești
|
||
log-urile din săpt 2, nu ai unde. Fix local pentru `service_auto`:
|
||
|
||
```python
|
||
# backend/modules/service_auto/__init__.py
|
||
import logging
|
||
from pathlib import Path
|
||
|
||
# Absolute path rezolvat relativ la acest file — zero dependență de CWD
|
||
_LOG_DIR = Path(__file__).resolve().parents[2] / 'logs'
|
||
_LOG_DIR.mkdir(parents=True, exist_ok=True)
|
||
|
||
logger = logging.getLogger('service_auto')
|
||
logger.propagate = False # fără dublă scriere în stdout via root logger
|
||
fh = logging.FileHandler(_LOG_DIR / 'service_auto.log')
|
||
fh.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(name)s: %(message)s'))
|
||
logger.addHandler(fh)
|
||
logger.setLevel(logging.INFO)
|
||
```
|
||
|
||
Notă: `propagate = False` evită ca mesajele să apară și în stdout prin root logger-ul
|
||
din `main.py`. Dacă vrei **ambele** (file + stdout), șterge rândul cu `propagate`.
|
||
|
||
Log structurat la fiecare call:
|
||
```python
|
||
logger.info("service_auto.create_comanda START", extra={'user': user.username, 'tip': data.tip, 'client_id': data.client_id})
|
||
logger.info("service_auto.create_comanda OK", extra={'comanda_id': comanda_id, 'duration_ms': elapsed})
|
||
logger.warning("service_auto.create_comanda BUSINESS_ERROR", extra={'ora_code': code})
|
||
logger.error("service_auto.create_comanda INFRA_ERROR", extra={'ora_code': code}, exc_info=True)
|
||
```
|
||
|
||
La sfârșit de fiecare săptămână, `grep` în log pentru count-uri și duration p99.
|
||
|
||
### Correction 9 — Week 1 gate reframing pentru ipoteza #1 (true-async)
|
||
|
||
**Prima versiune a planului** trata Week 1 gate ca un "flag flip": "dacă true-async merge
|
||
→ adoptă; dacă nu → sync-facade". **Realitate:** `shared/database/oracle_pool.py` folosește
|
||
`oracledb.create_pool()` — API sync. Pentru adevărat-async există `create_pool_async()` care
|
||
e o **clasă diferită**, cu acquire/close semantics distincte. **Integrarea în pool-ul shared
|
||
e un refactor non-trivial, NU un flag.**
|
||
|
||
**Gate reframe:**
|
||
|
||
> - Dacă `connect_async()` + OUT params merge în POC → **decizia e**: folosește `connect_async`
|
||
> ad-hoc în `service_auto` (zero pooling, acceptă trade-off-ul "1 user, 1 connection per
|
||
> request"), log-ează ca **ipoteză phase-2** că integrarea `AsyncConnectionPool` în
|
||
> `OracleMultiPool` ar fi worthwhile. Prototype-ul NU atinge shared-code async pool.
|
||
> - Dacă POC-ul eșuează → sync-facade prin pool-ul existent (treasury_service pattern).
|
||
> Pre-approved, zero timp pierdut.
|
||
|
||
Intenția originală se păstrează — învățare reală despre true-async — fără să ascundă în
|
||
Week 1 gate o săptămână de refactor la shared code.
|
||
|
||
### Correction 10 — Module layout pre-declarat în săpt 1
|
||
|
||
**Prima versiune** creează `backend/modules/service_auto/__init__.py` doar pentru logger,
|
||
restul structurii apare ad-hoc. **Realitate:** convenția repo-ului
|
||
(`backend/modules/data_entry/`) e `routers/ services/ schemas/ models/ db/`. Template
|
||
deliverable-ul săpt 21 e mai puternic dacă *documentează* o structură deja curată decât
|
||
dacă *retrofitează* una.
|
||
|
||
**Action în săpt 1 alongside logger:** `mkdir -p backend/modules/service_auto/{routers,services,schemas,models}`
|
||
+ `touch` câte un `__init__.py` gol în fiecare. Zero cod, doar scaffold.
|
||
|
||
### Correction 11 — `TODO-phase2.md` creat în săpt 1
|
||
|
||
**Prima versiune** referenția `docs/service-auto/TODO-phase2.md` ca destinație pentru scope-creep
|
||
thoughts, dar fișierul nu există. Creează-l în săpt 1 cu un header gol:
|
||
|
||
```markdown
|
||
# TODO — Phase 2 ideas for service_auto
|
||
|
||
Temptations captured during the 24-week prototype. NOT commitments. NOT scoped.
|
||
This file is a graveyard for "ooh, we could also..." thoughts.
|
||
```
|
||
|
||
Angajamentul scope-wall devine astfel durabil și citibil.
|
||
|
||
### Correction 7 — Timeline dublat: 12 → 24 săptămâni
|
||
|
||
**Prima versiune** aloca 12 săptămâni × 2-4 h/săpt = 24-48h. **Realitate (outside voice):**
|
||
10 tehnologii noi (Vue 3, Pinia, PrimeVue, Axios, FastAPI async, oracledb true-async,
|
||
`session_callback`, PL/SQL OUT params, JWT reuse cu auth store, error mapping) ÷ 24h =
|
||
~2.4h per tehnologie, **zero slack**. Plus 2-3 săpt pierdute realist pe VFP urgențe din
|
||
12. **Buget onest: 24 săptămâni × 2-4 h/săpt = 48-96h total.** Scope-ul rămâne același,
|
||
tempo-ul e mai onest.
|
||
|
||
### Correction 8 — Week-12-style deliverable schimbă: template reutilizabil, nu demo
|
||
|
||
**Prima versiune** zicea săpt 12 = "cleanup + phase 2 notes". **Realitate:** un demo pe un
|
||
branch throwaway nu e un hedge — e o demonstrație. Hedge-ul real e un **template
|
||
reutilizabil**. Noul deliverable pentru săpt 24:
|
||
|
||
- `docs/service-auto/template-modul-oracle.md` — rețetă de 1 pagină pentru "cum adaugi un
|
||
modul nou peste Oracle în roa2web": register_server pattern, SP signature convention,
|
||
grants model, error map range, `session_callback` snippet, JWT reuse via
|
||
AuthenticationMiddleware, logging setup, file layout.
|
||
- `docs/service-auto/decision-log.md` — go / no-go pentru phase 2: ce a funcționat, ce
|
||
nu, sub ce condiții se justifică un al doilea modul, când să nu.
|
||
- `docs/service-auto/learnings.md` — notele săptămânale consolidate în lesson patterns.
|
||
|
||
## UX spec — interaction states for `ComandaNoua.vue` (from /plan-design-review 2026-04-11)
|
||
|
||
Hypothesis #4 validates error *codes end-to-end*. Această secțiune fixează
|
||
comportamentul *formularului în fiecare stare* — ca să nu se improvizeze
|
||
în săptămâna 14 la 2h/săpt, în timp ce Marius debug-uiește async Oracle.
|
||
|
||
**Convenția Toast** e aliniată cu `src/modules/data-entry/views/receipts/ReceiptCreateUnifiedView.vue:666-787`
|
||
(existing `toast.add({severity, summary, detail, life})`), zero componente noi.
|
||
|
||
| State | Trigger | UX behavior | PrimeVue primitives |
|
||
|---|---|---|---|
|
||
| **Idle / first load** | Mount `ComandaNoua.vue` | Focus auto pe `Select "tip comandă"`. Placeholder-uri scurte în română ("Alege tip", "Alege client", "Alege mașina", "Descrie operațiile"). Submit button disabled until toate 4 câmpurile sunt non-empty. | `Select`, `Textarea`, `Button disabled` |
|
||
| **Loading / in-flight** | User clicks Submit | (a) Submit button → `:loading="true"` (PrimeVue spinner inline). (b) Toate câmpurile `:disabled="true"` ca să nu editeze în timpul SP call. (c) Fără overlay / modal. (d) Dacă SP depășește 10s, nimic special (rely on FastAPI default timeout) — tracking ca TODO-phase2 dacă devine problemă. | `Button :loading`, `:disabled` pe inputs |
|
||
| **Success** | HTTP 200 + `{comanda_id, numar}` | (1) Toast `severity: 'success'`, summary `'Comandă creată'`, detail `'Nr ${numar}'`, `life: 3000`. (2) Reset: `client_id=null, masina_id=null, operatii=''`. **PRESERVE `tip_comandă`** (user creează multiple same-type în succesiune). (3) Re-enable form. (4) Focus revine pe `client_id` dropdown. | `toast.add`, form ref reset parțial |
|
||
| **Business error (20001-20999)** | HTTP 422 cu detail din SP | (1) Toast `severity: 'error'`, summary `'Validare'`, detail = mesajul din SP (diacritice!), `life: 5000`. (2) Form **PRESERVĂ input-ul** (user vrea să corecteze, nu să retype). (3) Re-enable form. (4) Fără field-level highlight pentru prototype — scope wall, SP-ul nu returnează field name. | `toast.add severity error` |
|
||
| **Infra error (12xxx, 01017, 00942)** | HTTP 503 sau 500 | (1) Toast `severity: 'error'`, summary `'Eroare conexiune'` (503) sau `'Eroare internă'` (500), detail = mesaj generic din tabelul Correction 5, `life: 5000`. (2) Form preservă input. (3) Re-enable Submit — user poate retry. (4) Fără retry-uri automate (keep it simple). | `toast.add severity error` |
|
||
| **Client-side validation** | — | **NONE pentru prototype.** SP-ul e sursa de adevăr pentru validare. Rationale: o singură sursă = mai puține layer-e de debug în săpt 13-16. Fewer moving parts = more learning. Un singur control: Submit disabled dacă vreun câmp e empty (trivial, nu contează ca "validare"). | — |
|
||
|
||
**Dark mode requirement** (din `.claude/rules/css-design-system.md`): testare OBLIGATORIE
|
||
în ambele teme (auto / light / dark) via toggle din `AppHeader.vue`. Fiindcă
|
||
`ComandaNoua.vue` folosește PrimeVue + semantic tokens (`--surface-card`,
|
||
`--text-color`, etc.) importate din roa2web, **zero CSS custom** în prototype →
|
||
dark mode "free" fără efort. Dacă apare vreo regresie de culoare, e bug în
|
||
component-ul PrimeVue, nu în ComandaNoua — NU fix în prototype, log în `TODO-phase2.md`.
|
||
|
||
**Test pass în săpt 13-16**: pentru fiecare rând din tabel, un click manual
|
||
verified, documentat în `docs/service-auto/week13-ux-states.md` (1 paragraf, 6 rânduri).
|
||
Zero e2e automation — scope wall.
|
||
|
||
## What to reuse from the scrapped doc
|
||
|
||
Nu tot efortul de pe doc-ul vechi e pierdut:
|
||
|
||
- **Manual ROAAUTO PDF** (`docs/service-auto/manual_ROAAUTO.pdf`) — ground truth user-level pentru
|
||
fluxul real de service auto. Folosit ca input pentru ce câmpuri trebuie să aibă
|
||
`ComandaNoua.vue` și ca referință pentru verificarea tabelelor atinse la creare comandă.
|
||
- **Sursa VFP roaauto în gitea** (`gitea.romfast.ro/romfast/vfp_roaauto`, importată 2026-04-11)
|
||
— ground truth **code-level** pentru cum se citesc / scriu datele în schemă. Folosită
|
||
în săpt 3 pentru extragerea: (a) tabelelor atinse la creare comandă, (b) celor 4 valori
|
||
enum `tip comandă`, (c) label-urilor Romanian pentru câmpuri, (d) pattern-ului SP-urilor
|
||
existente (dacă există) ca referință pentru `SP_CREEAZA_COMANDA`. Înlocuiește nevoia de a
|
||
deschide VFP-ul producție — zero risk, text searchable, diff-abil.
|
||
- **Legacy `/workspace/roaauto/frontend/src/views/orders/OrderCreateView.vue`** —
|
||
starting point pentru `ComandaNoua.vue` la ~125 linii, audit de 30 min în săptămâna 1.
|
||
- **Convenția de services** din `.claude/rules/backend-patterns.md` — fiecare SP call trăiește
|
||
într-un service, nu în router. Decoratorul `@cached` există LOCAL la `backend/modules/reports/cache/decorators.py`,
|
||
nu în `shared/` — deci NU se importă în `service_auto`. Oricum e pentru reads, prototype-ul e
|
||
write-only. Dacă phase 2 aduce reads, decide atunci dacă e worth promovat la `shared/`.
|
||
- **Pattern-ul `treasury_service.py`** ca **golden example** de apel PL/SQL cu OUT params.
|
||
- **Design system roa2web** — `docs/DESIGN.md`, `docs/DESIGN_TOKENS.md`,
|
||
`docs/CSS_PATTERNS.md`, `.claude/rules/css-design-system.md`. `ComandaNoua.vue`
|
||
**MUST** folosi semantic tokens (`--surface-card`, `--text-color`, `--color-primary`,
|
||
spacing scale `--space-*`), zero valori hardcodate, zero CSS scoped custom (doar
|
||
layout minimal via `.form-stack { display: grid; gap: var(--space-md); }`).
|
||
Toast-uri prin `useToast()` + convenția `{severity, summary, detail, life}` cu
|
||
life 3000ms success / 5000ms error. Dark mode testare obligatorie (`[data-theme]`
|
||
toggle din `AppHeader.vue`). Zero componente noi — reuse PrimeVue `Select`,
|
||
`Textarea`, `Button`, `Toast`.
|
||
|
||
## Risks + mitigations
|
||
|
||
### Risk 1: 2-4 hrs/week + learning curve = prototype drifts into 12+ months
|
||
Corecția de buget (24 săpt) ajută. **Mitigare principală:** stop-point discipline
|
||
(milestone self-contained per săptămână) + **kill criterion explicit** (vezi mai jos).
|
||
Săpt 1 goal e **Hello World Oracle connection** — nu SP, nu schema, nu UI.
|
||
|
||
### Risk 2: oracledb async + PL/SQL OUT params sunt poorly documented
|
||
Săpt 1 POC e exact asta, pe o procedură trivială. **Fallback pre-aprobat:** dacă
|
||
true-async nu merge, prototype-ul continuă cu sync-facade (pattern deja în prod). Zero
|
||
timp pierdut.
|
||
|
||
### Risk 3: ~~CURRENT_SCHEMA switching conflictează cu OracleMultiPool~~
|
||
**Corectat:** nu conflictează. `OracleMultiPool` izolează per `server_id`.
|
||
`session_callback` se aplică la `create_pool` call, nu la nivel de instance. Poți adăuga
|
||
un argument `session_callback=` la pool creation pentru `mariusm_test` fără să atingi
|
||
pool-urile altor servere.
|
||
|
||
### Risk 4: Marius abandonează side project-ul după săpt 3 pentru că VFP-ul real cere atenție
|
||
Realitate acceptată (outside voice): 2-3 săpt pierdute în 12 e probabil. **Mitigare:**
|
||
timeline dublat la 24, fiecare săptămână e stoppable milestone, plus **kill criterion**.
|
||
|
||
### Risk 5 (NEW): Integration issues concentrate la final
|
||
Outside voice observă: fiecare layer e mock-uit până la săpt 11, apoi totul se integrează.
|
||
Dacă Vue↔FastAPI↔oracledb are un CORS/proxy/JWT header issue, apare fără buffer.
|
||
**Mitigare:** două **integration checkpoints** intermediare:
|
||
- Săpt 6 checkpoint: un `curl` hit pe endpoint-ul fără UI, cu JWT real, care cheamă SP-ul și returnează JSON. Confirmă FastAPI↔oracledb chain.
|
||
- Săpt 9 checkpoint: `ComandaNoua.vue` hit endpoint-ul cu JWT real, confirmă doar un drum happy path fără error handling. Confirmă Vue↔FastAPI chain.
|
||
|
||
### Risk 6 (NEW): Grants inventory pe MARIUSM_AUTO nedocumentat
|
||
Outside voice observă: testul negativ săpt 3 presupune clean slate. **Mitigare:** săpt 3,
|
||
înainte de testul negativ, rulează un `SELECT * FROM DBA_TAB_PRIVS WHERE grantee = 'ROA_WEB'`
|
||
+ `SELECT * FROM DBA_SYS_PRIVS WHERE grantee = 'ROA_WEB'` și documentează starting state
|
||
în `docs/service-auto/week3-grants-audit.md`.
|
||
|
||
## Kill criterion (NEW — from outside voice)
|
||
|
||
**Prototype-ul se oprește definitiv** (nu "pauză de o săptămână", ci "end of project,
|
||
scrie decision-log și gata") dacă ORICARE din:
|
||
|
||
1. **Săpt 4 checkpoint:** `session_callback` nu funcționează după 2 săpt de încercări
|
||
(adică nu ai ajuns la o conexiune care schimbă CURRENT_SCHEMA curat, fără race). Decizia:
|
||
scrie `decision-log.md` cu "session_callback nefezabil în acest oracledb/Python combo,
|
||
multi-tenant necesită alt approach", apoi stop.
|
||
2. **Săpt 8 checkpoint:** nu ai un SP `SP_CREEAZA_COMANDA` funcțional testat din SQL
|
||
Developer + Python + grants OK. Decizia: `decision-log.md` cu "pattern SP-first prea
|
||
greu pentru side-project budget", apoi stop.
|
||
3. **Săpt 14 checkpoint:** nu ai un curl care apelează endpoint-ul + JWT real + SP + returnează JSON.
|
||
4. **Oricând:** 3 săpt consecutive în care nu ai atins nici măcar 1 oră de work pe
|
||
prototype. Side project-ul e mort, acceptă realitatea, `decision-log.md` cu
|
||
"abandoned — VFP demands exceeded budget".
|
||
|
||
Stop NU înseamnă eșec. Stop înseamnă "am învățat ce trebuia, continuarea nu mai produce
|
||
valoare marginală". Fiecare stop produce un `decision-log.md` citibil în 6 luni.
|
||
|
||
## Timeline (ajustat pentru 2-4 hrs/week × 24 săptămâni)
|
||
|
||
**Fiecare săptămână e self-contained + oprire curată.** Ordering-ul original e păstrat,
|
||
doar spațiat pe 24 săpt în loc de 12, cu checkpoints de integration intermediare.
|
||
|
||
| Săpt | Target | Cum știu că e gata |
|
||
|---|---|---|
|
||
| 1 | Oracle central rulează + `poc/hello_oracle.py` (sync) + `poc/hello_oracle_async.py` (`connect_async`) conectează cu `SELECT 1 FROM DUAL`. **Gate (reframed — vezi Correction 9)**: dacă `connect_async` merge → folosește ad-hoc în service_auto, refactorul de pool rămâne phase-2; dacă nu → sync-facade. DX check (save → result < 10s?). File handler logging setup cu absolute path + `propagate=False`. **Module scaffold**: `mkdir backend/modules/service_auto/{routers,services,schemas,models}`. Creează `docs/service-auto/TODO-phase2.md` cu header gol. | Log arată rezultat, `docs/service-auto/week1-notes.md` scris, scaffold există, `TODO-phase2.md` există |
|
||
| 2 | `poc/async_out_param_probe.py` — test SP trivial (`CREATE PROCEDURE test_out(p OUT NUMBER) AS BEGIN p := 42; END;`) + Python apel cu `cursor.var(int)` | Script scris, primește `42` |
|
||
| 3 | **Preparare:** audit grants curenți pe MARIUSM_AUTO (`DBA_TAB_PRIVS`, `DBA_SYS_PRIVS`). **Clonează `gitea.romfast.ro/romfast/vfp_roaauto`** și grep prin .PRG / .SCX pentru fluxul "creează comandă nouă service auto" — scrie `tabele-service-auto.md` cu: (a) tabele atinse, (b) cele 4 valori enum `tip comandă`, (c) label-uri Romanian pentru câmpuri, (d) pattern SP-uri existente (dacă există). Creează user `ROA_WEB` + grants. **Auth path audit (ipoteza #6)**: adaugă `MARIUSM_AUTO` la `ORACLE_SERVERS` în `backend/.env`, inserează row în `CONTAFIN_ORACLE.UTILIZATORI` pentru Marius, log in prin UI, confirmă server selector + JWT payload, verifică `get_user_companies('MARIUS M', 'mariusm_test')` → scrie `week3-auth-audit.md`. | `week3-grants-audit.md` + `tabele-service-auto.md` (cu enum + labels + SP-uri din gitea) + `week3-auth-audit.md` scrise, login funcțional pentru server nou |
|
||
| 4 | Test negativ ipoteza #3 (INSERT direct → ORA-00942; SELECT direct → ORA-00942; CALL SP → success). Pytest integration marker. | Test automat rulează local, toate cele 3 asserts trec |
|
||
| 5 | `session_callback` pentru CURRENT_SCHEMA switching, test concurent pe 2 conexiuni paralele pe aceeași schemă. **Task explicit**: patch ~8 linii la `shared/database/oracle_pool.py` (`register_server` acceptă `session_callback`, `_get_or_create_pool` îl propagă la `create_pool`). Backward compatible, zero callers existenți afectați. | Log-uri clare, niciun cursor tag leak, patch la shared code review-ed și commit-ed |
|
||
| 6 | **Checkpoint integration 1**: endpoint `GET /api/service-auto/ping` care rulează `SELECT 1 FROM DUAL` pe `mariusm_test` prin `oracle_pool.get_connection('mariusm_test')`. Curl cu JWT real (după auth-ul probeat în săpt 3). Probează: auth → middleware → pool → connection → query round-trip pentru serverul nou — întregul chain, fără SP. | `curl -H "Authorization: Bearer ..." /api/service-auto/ping` returnează `{"result": 1}` |
|
||
| 7-8 | **Verify tabele** în VFP (din săpt 3), scrie `SP_CREEAZA_COMANDA` în SQL Developer, test manual cu `EXEC` | Row apare în tabela dedicată cu ID returnat prin OUT |
|
||
| 9-10 | Service-layer Python (`comenzi_service.create_comanda`) care apelează SP-ul prin pattern-ul ales în săpt 1 + `connection.commit()` + test persist după reconnect | Test automat: callproc + commit + new connection + SELECT → row există |
|
||
| 11 | Endpoint FastAPI `/api/service-auto/comenzi` care primește Pydantic, apelează service, returnează JSON | `curl` hit cu JWT real + body JSON → row inserted |
|
||
| 12 | **Checkpoint integration 2**: `ComandaNoua.vue` minimal (hardcoded dropdowns) + Pinia store + axios call → endpoint. Doar happy path, zero error handling. | Submit în browser → row inserted → console log "OK" |
|
||
| 13-16 | Error handling end-to-end: ORA-20001 (diacritice!) → HTTP 422 → PrimeVue Toast în română. ORA-12541 → HTTP 503 → Toast generic. Spinner pe buton cât SP rulează. Reset form la success. | Aruncă intenționat erori în SP, verifică fiecare drum |
|
||
| 17-20 | Buffer pentru VFP urgențe + lessons refactor (dacă săpt 1-16 au produs cod care trebuie curățat). Dacă nu e nevoie de buffer, rula ipoteza #2 mai adânc (2 conexiuni, concurență mai agresivă). | N/A — buffer |
|
||
| 21-22 | Scrie `template-modul-oracle.md` — reteta reutilizabilă | Doc scris, citibil de către un alt dev |
|
||
| 23 | Scrie `decision-log.md` — go/no-go phase 2, learnings consolidate | Doc scris, decizie clară |
|
||
| 24 | Cleanup: ștergerea `poc/` dacă e cazul, final commit pe branch, `learnings.md` consolidat | Branch clean, commit final |
|
||
|
||
**Timeline-ul e intenționat conservativ.** La 2-4 hrs/week, 24 săpt = 48-96 ore totale.
|
||
Dacă merge mai repede, perfect — atingi mai devreme la sfârșit. Dacă merge mai încet,
|
||
fiecare săptămână e încă un milestone self-contained.
|
||
|
||
## What would make this prototype fail (and it would still be useful)
|
||
|
||
- Ipoteza #1 eșuează pentru **true-async**: fallback la sync-facade, prototype continue.
|
||
Zero învățare pierdută — sync-facade e deja în producție, știi că merge.
|
||
- Ipoteza #1 eșuează pentru **ambele** (sync + true-async): dacă nici sync-facade-ul din
|
||
`treasury_service.py` nu merge la MARIUSM_AUTO, e ceva radical prost cu oracledb
|
||
instalat la tine. **Stop și investighează**.
|
||
- Ipoteza #2 eșuează: `session_callback` fragil în practică → Marius știe că pool-per-tenant
|
||
e necesar, nu pool-single-with-tag. Design major changed, decision-log documentează.
|
||
- Ipoteza #3 eșuează: GRANTS model nu ține (SP cheamă alte SPs cu privilegii neașteptate)
|
||
→ Marius știe că "Regula de aur via GRANTS" e naivă și trebuie altceva (VPD?
|
||
row-level security?). Design major changed.
|
||
- Ipoteza #4 eșuează: error propagation urâtă (encoding, truncation) → Marius știe că
|
||
trebuie protocol de eroare dedicat, nu `RAISE_APPLICATION_ERROR`.
|
||
- Ipoteza #5 eșuează: DX pentru 2-4 hrs/week e unusable → Marius știe că side project pe
|
||
acest stack nu e viabil și trebuie alt approach.
|
||
|
||
Orice din aceste failures e **valoare mai mare** decât "prototype care merge happy path
|
||
fără să fi întâmpinat nicio problemă reală". Succesul real = învățare, nu cod.
|
||
|
||
## Next actions (săpt 1, 2026-04-14 → 2026-04-18)
|
||
|
||
Cel mai concret lucru, o singură zi, 2-4 ore:
|
||
|
||
1. **Verifică SSH tunnel setup** de la containerul de dev (sau workstation-ul de acasă)
|
||
la `10.0.20.121/ROA`. Există `ssh-tunnel-manager.py` în `backend/shared/` — vezi dacă
|
||
se refolosește.
|
||
2. **`poc/hello_oracle.py`** (sync, la `MARIUSM_AUTO` user sau alt user Oracle existent) —
|
||
`oracledb.connect(...)` + `SELECT 1 FROM DUAL`.
|
||
3. **`poc/hello_oracle_async.py`** (true-async) — `oracledb.connect_async(...)` + același
|
||
`SELECT 1 FROM DUAL` cu `await cursor.execute(...)`.
|
||
4. **Setup logging file handler** pentru modulul `service_auto` (nu exista încă, dar
|
||
directory-ul `backend/modules/service_auto/` se poate crea în săpt 1 just to house
|
||
the logging setup).
|
||
5. **Raport săpt 1** — `docs/service-auto/week1-notes.md`, max 15 linii: ce a mers, ce a
|
||
fost greu, DX latency măsurat (save → result în secunde), gate decision (sync vs
|
||
true-async), buget rămas din săpt 1.
|
||
|
||
Zero SP-uri, zero Vue, zero auth, zero scheme noi. Doar "Python vorbește cu Oracle local"
|
||
în ambele pattern-uri.
|
||
|
||
## Non-negotiables
|
||
|
||
1. **Cei 4 clienți nu sunt atinși niciodată în acest prototype.** MARIUSM_AUTO e
|
||
dedicat, zero copy, zero conexiune la producție.
|
||
2. **Scope wall la 1 ecran + 1 SP.** Tentațiile de scope creep merg la
|
||
`docs/service-auto/TODO-phase2.md`, nu în cod.
|
||
3. **Stop points weekly.** Fiecare săptămână e oprire curată. Nu se acceptă "oh, nu pot
|
||
să mă opresc aici pentru că e jumătate făcut".
|
||
4. **Succesul se măsoară în învățare + template reutilizabil**, nu în ecrane livrate. Un
|
||
prototype care descoperă o problemă e mai valoros decât unul care evită toate
|
||
problemele.
|
||
5. **Kill criterion trigger-ed → scrie decision-log → stop.** Nu "mai dau 2 săpt să văd".
|
||
|
||
## Final deliverable (săpt 24)
|
||
|
||
Nu e un ecran. Nu e un demo. E:
|
||
|
||
1. `docs/service-auto/template-modul-oracle.md` — rețetă de 1 pagină citibilă de către un alt dev în 10 minute:
|
||
- Cum înregistrezi un server nou în `OracleMultiPool`
|
||
- Signature convention pentru SPs cu OUT params
|
||
- Grants model (user tehnic + `EXECUTE ON SP` + `ALTER SESSION SET CURRENT_SCHEMA`)
|
||
- Error code range classification (20xxx → 422, 12xxx → 503, else → 500)
|
||
- `session_callback` snippet pentru CURRENT_SCHEMA switching
|
||
- JWT reuse prin `AuthenticationMiddleware`
|
||
- Logging file handler per-modul
|
||
- File layout (`routers/`, `services/`, `models/`)
|
||
2. `docs/service-auto/decision-log.md` — go / no-go pentru phase 2:
|
||
- Ce ipoteze s-au confirmat, care nu
|
||
- Evidența concretă (log-uri, teste, numere DX)
|
||
- Condițiile sub care un al doilea modul e justificat
|
||
- Condițiile sub care NU e justificat (kill criterion retroactiv)
|
||
3. `docs/service-auto/learnings.md` — notele săptămânale consolidate, pattern-uri noi,
|
||
surprize, workarounds descoperite, Oracle edge cases.
|
||
4. Cod: tot sub branch `feat/service-auto`, NU merged în main. Branch = arhivă + referință.
|
||
|
||
**Acest deliverable e valoros chiar dacă prototype-ul n-a ajuns la 100% din ipoteze.**
|
||
|
||
---
|
||
|
||
**END OF RETHINK DESIGN v2. ~9 pages. Budget 2-4 hrs/week × 24 weeks = 48-96 hrs total.**
|
||
|
||
---
|
||
|
||
## GSTACK REVIEW REPORT
|
||
|
||
| Review | Trigger | Why | Runs | Status | Findings |
|
||
|--------|---------|-----|------|--------|----------|
|
||
| CEO Review | `/plan-ceo-review` | Scope & strategy | 1 | CLEAR (PLAN) | HOLD SCOPE mode, 0 critical gaps post-fix, 10 items deferred to TODO-phase2, plan file rewritten v2 with 8 review corrections |
|
||
| Codex Review | `/codex review` | Independent 2nd opinion | 0 | — | — |
|
||
| Eng Review | `/plan-eng-review` | Architecture & tests (required) | 1 | CLEAR (PLAN) | 8 issues (3 P1/P2 load-bearing + 5 minor committed), 1 critical gap (JWT auth flow) mitigated via new hypothesis #6 + week-3 auth audit, Corrections 9/10/11 added, timeline table updated for weeks 1/3/5/6 |
|
||
| Design Review | `/plan-design-review` | UI/UX gaps | 1 | CLEAR (PLAN) | score 6/10 → 9/10, 4 decisions added (interaction-states table, design-system inheritance clause, a11y one-liner, week-3 enum+labels capture), 0 unresolved, mockups skip-by-design (learning prototype on existing roa2web theme) |
|
||
| DX Review | `/plan-devex-review` | Developer experience gaps | 0 | — | — |
|
||
|
||
**OUTSIDE VOICE (CEO round):** Claude subagent (Codex unavailable). 15 findings total. 3 load-bearing surfaced as cross-model tension (SP→ACT modeling error, budget ~2x under-scoped, demo vs template deliverable). All 3 accepted by user and integrated into plan v2.
|
||
|
||
**OUTSIDE VOICE (ENG round):** Skipped. Rationale: design already absorbed one full outside-voice round in CEO review; advisor consulted during orientation as independent second perspective; prototype scope has diminishing returns on third adversarial pass; Codex CLI unavailable in this environment.
|
||
|
||
**OUTSIDE VOICE (DESIGN round):** Skipped by design. Advisor consulted once during orientation to sanity-check the "skip mockups" judgment (confirmed: generating fictional mockups for a learning prototype that must inherit existing roa2web PrimeVue theme would be actively misleading). No second adversarial pass — design surface is ~15 lines of plan text, not a visual system.
|
||
|
||
**DESIGN REVIEW SUMMARY:**
|
||
- **Passes 1, 3** (Info Arch, User Journey): no findings — single form, 1-user prototype.
|
||
- **Pass 4** (AI Slop): N/A — no custom design surface, every pixel inherited from existing roa2web theme.
|
||
- **Pass 2** (Interaction States) 3/10 → 9/10: 6-state table added (idle/loading/success/business-error/infra-error/client-validation) with concrete PrimeVue behavior, toast lifecycle aligned to `ReceiptCreateUnifiedView.vue` convention (life 3000/5000ms), `tip comandă` preserved on success reset, dark-mode inheritance documented, client-side validation intentionally omitted for prototype (fewer layers to debug).
|
||
- **Pass 5** (Design System) 2/10 → 9/10: inheritance clause added referencing `DESIGN.md`, `DESIGN_TOKENS.md`, `CSS_PATTERNS.md`, `.claude/rules/css-design-system.md`. Semantic tokens mandatory, zero hardcoded values, zero custom components.
|
||
- **Pass 6** (A11y) 5/10 → 9/10: one-liner clarifying PrimeVue defaults handle keyboard/ARIA/focus so it isn't mistaken for scope creep.
|
||
- **Pass 7** (Unresolved Decisions): 2 items (4 `tip comandă` enum values + Romanian field labels) folded into week-3 VFP audit subtask — sourced from ground truth, not invented.
|
||
|
||
**ENG REVIEW SUMMARY:**
|
||
- **Architecture (3 issues):** (#1, P1) JWT auth flow for MARIUSM_AUTO undesigned → added hypothesis #6 + week-3 auth audit subtask. (#2, P2) `oracle_pool.py` needs ~8-line backward-compatible patch to thread `session_callback`; "zero refactor" claim corrected in Correction 1 and scheduled explicitly in week 5. (#3, P2) Week 1 gate reworded: true-async success means ad-hoc `connect_async` inside service_auto, NOT pool refactor — AsyncConnectionPool integration becomes phase-2 hypothesis (Correction 9).
|
||
- **Code Quality (3 committed fixes):** Correction 6 logging snippet fixed (absolute path + `propagate=False`), `@cached` wording clarified (reports-local, not shared), Correction 10 added (module scaffold in week 1), Correction 11 added (`TODO-phase2.md` stub in week 1).
|
||
- **Test plan:** 7/12 hypothesis-branches planned, JWT flow test added (manual smoke in week 3), diacritics byte-level assertion flagged as week-17-20 buffer refinement. Test plan artifact written to `~/.gstack/projects/romfast-roa2web/claude-feat-service-auto-eng-review-test-plan-20260411-140656.md`.
|
||
- **Performance:** N/A for 1-user prototype. Optional: register `mariusm_test` with `min=1, max=2`.
|
||
- **Parallelization:** N/A — single dev, inherently sequential.
|
||
|
||
**UNRESOLVED:** 0
|
||
|
||
**VERDICT:** CEO + ENG + DESIGN CLEARED — plan v2 + eng-review corrections + design-review UX spec (1 interaction-states table, 1 design-system inheritance clause, 1 a11y note, 1 week-3 enum/labels audit task). 24-week learning prototype is ready to execute. Next action: week 1 per timeline (hello_oracle POC + DX check + module scaffold + `TODO-phase2.md` stub + logging setup).
|