feat(service-auto): săpt 3-phase2 — toate ipotezele confirmate + modul funcțional

Backend:
- service_auto module complet: router, service, schemas, 5 teste suites (22/22 passed)
- 5 endpoints: GET /ping, /firme, /tip-deviz, /masini, POST /comenzi
- SP_CREEAZA_COMANDA_PROTOTIP creat în MARIUSM_AUTO (VALID, 5.9ms)
- oracle_pool.py: session_callback backward-compat patch
- ROA_WEB user: grants SP-only confirmate (H3), mariusm_test pool switchat
- pyproject.toml: integration pytest marker înregistrat

Frontend:
- ComandaNoua.vue: date reale din Oracle (firme/tip-deviz/masini), nu hardcodate
- src/modules/service-auto/services/api.js: axios service cu Bearer token
- src/router/index.js: rută /service-auto/comanda-noua

Docs:
- decision-log.md: verdict MERGE, toate 6 ipoteze CONFIRMED
- learnings.md: 7 patterns reutilizabile
- grants-audit.md: arhitectura multi-tenant + proxy auth analysis + V_NOM_FIRME loop
- template-modul-oracle.md: rețetă completă pentru module Oracle noi
- TODO-phase2.md: 7 items concrete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-04-12 09:36:56 +00:00
parent 4162e0711c
commit 32aca55c78
30 changed files with 2866 additions and 1 deletions

View File

@@ -0,0 +1,100 @@
"""
POC: Oracle OUT param probe — Săpt 2 Gate
Tests that oracledb cursor.var(oracledb.NUMBER) correctly round-trips an
Oracle OUT NUMBER parameter via cursor.callproc().
Steps:
1. Connect (sync, same pattern as hello_oracle.py)
2. CREATE OR REPLACE a minimal test procedure with OUT param
3. callproc → assert OUT value == 42
4. DROP the procedure (cleanup)
5. Print timing summary
Usage:
cd /workspace/roa2web
backend/venv/bin/python poc/async_out_param_probe.py
"""
import time
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'backend'))
import oracledb
HOST = "10.0.20.121"
PORT = 1521
SERVICE_NAME = "ROA"
USER = "CONTAFIN_ORACLE"
SECRETS_FILE = os.path.join(os.path.dirname(__file__), '..', 'backend', 'secrets', 'central.oracle_pass')
def read_password() -> str:
with open(SECRETS_FILE) as f:
return f.read().strip()
def test_out_param():
print(f"[OUT_PROBE] Connecting to {HOST}:{PORT}/{SERVICE_NAME} as {USER}")
password = read_password()
t0 = time.perf_counter()
conn = oracledb.connect(
user=USER,
password=password,
host=HOST,
port=PORT,
service_name=SERVICE_NAME,
)
t_connect = time.perf_counter() - t0
print(f"[OUT_PROBE] Connected in {t_connect*1000:.1f}ms")
with conn.cursor() as cursor:
# --- Step 1: CREATE the test procedure ---
t1 = time.perf_counter()
cursor.execute("""
CREATE OR REPLACE PROCEDURE MARIUSM_AUTO.test_out(p OUT NUMBER) AS
BEGIN
p := 42;
END;
""")
t_create = time.perf_counter() - t1
print(f"[OUT_PROBE] CREATE PROCEDURE in {t_create*1000:.1f}ms")
# --- Step 2: Call the procedure via callproc ---
t2 = time.perf_counter()
out_var = cursor.var(oracledb.NUMBER)
cursor.callproc('MARIUSM_AUTO.test_out', [out_var])
t_call = time.perf_counter() - t2
result = out_var.getvalue()
print(f"[OUT_PROBE] callproc → out_var.getvalue() = {result} ({t_call*1000:.1f}ms)")
# --- Step 3: Assert ---
assert result == 42, f"Expected 42, got {result}"
print("[OUT_PROBE] ASSERT PASSED: OUT param == 42 ✅")
# --- Step 4: DROP the procedure (cleanup) ---
t3 = time.perf_counter()
cursor.execute("DROP PROCEDURE MARIUSM_AUTO.test_out")
t_drop = time.perf_counter() - t3
print(f"[OUT_PROBE] DROP PROCEDURE in {t_drop*1000:.1f}ms — cleanup OK ✅")
conn.close()
total = time.perf_counter() - t0
print(f"[OUT_PROBE] Total: {total*1000:.1f}ms ✅")
return {
"connect_ms": round(t_connect * 1000, 1),
"create_ms": round(t_create * 1000, 1),
"callproc_ms": round(t_call * 1000, 1),
"drop_ms": round(t_drop * 1000, 1),
"total_ms": round(total * 1000, 1),
"out_value": result,
}
if __name__ == "__main__":
stats = test_out_param()
print(f"\n[OUT_PROBE] Summary: connect={stats['connect_ms']}ms "
f"callproc={stats['callproc_ms']}ms total={stats['total_ms']}ms")