Files
roa2web-service-auto/backend/modules/service_auto/tests/test_comanda_persist.py
Claude Agent 32aca55c78 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>
2026-06-05 09:37:09 +00:00

140 lines
4.8 KiB
Python

"""
Integration test: SP_CREEAZA_COMANDA_PROTOTIP persist + reconnect verify — Săpt 9-10
Verifies that:
1. callproc SP_CREEAZA_COMANDA_PROTOTIP writes a row to DEV_ORDL
2. After commit + disconnect, a NEW connection sees the row (true durability)
3. Cleanup removes all prototype rows from DEV_ORDL and NOM_LUCRARI
Run:
cd /workspace/roa2web
python -m pytest backend/modules/service_auto/tests/test_comanda_persist.py -v -m integration
"""
import os
import sys
import time
import pytest
import oracledb
# Add backend to path so secrets/ is accessible
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))
HOST = "10.0.20.121"
PORT = 1521
SERVICE_NAME = "ROA"
USER = "CONTAFIN_ORACLE"
SECRETS_FILE = os.path.join(
os.path.dirname(__file__), '..', '..', '..', 'secrets', 'central.oracle_pass'
)
def _read_password() -> str:
with open(SECRETS_FILE) as f:
return f.read().strip()
def _connect() -> oracledb.Connection:
return oracledb.connect(
user=USER,
password=_read_password(),
host=HOST,
port=PORT,
service_name=SERVICE_NAME,
)
@pytest.mark.integration
def test_comanda_persist_and_reconnect():
"""
Full round-trip: callproc → commit → close → NEW connection → SELECT → assert exists.
Cleans up all inserted rows after verification.
"""
# --- Phase 1: Call SP and commit ---
conn1 = _connect()
id_ordl = None
id_lucrare = None
try:
with conn1.cursor() as cursor:
out_id_ordl = cursor.var(oracledb.NUMBER)
out_nrord = cursor.var(oracledb.STRING)
t0 = time.perf_counter()
cursor.callproc(
"MARIUSM_AUTO.SP_CREEAZA_COMANDA_PROTOTIP",
[
3, # p_tip IN NUMBER
200, # p_id_masiniclient IN NUMBER
'Test pytest persist', # p_solicitari IN VARCHAR2
110, # p_id_firma IN NUMBER
out_id_ordl, # p_id_ordl OUT NUMBER
out_nrord, # p_nrord OUT VARCHAR2
],
)
t_callproc = time.perf_counter() - t0
id_ordl = int(out_id_ordl.getvalue())
nrord = out_nrord.getvalue() or ""
print(f"\n[PERSIST] callproc OK in {t_callproc*1000:.1f}ms → id_ordl={id_ordl} nrord={nrord}")
assert id_ordl > 0, f"Expected positive id_ordl, got {id_ordl}"
assert nrord.startswith("P"), f"Expected nrord starting with 'P', got {nrord!r}"
conn1.commit()
print(f"[PERSIST] commit OK on connection 1")
finally:
conn1.close()
print("[PERSIST] connection 1 closed")
# --- Phase 2: Open NEW connection and verify row exists ---
assert id_ordl is not None, "id_ordl must be set before reconnect phase"
conn2 = _connect()
try:
with conn2.cursor() as cursor:
cursor.execute(
"SELECT id_ordl, id_lucrare FROM MARIUSM_AUTO.DEV_ORDL WHERE id_ordl = :id",
{"id": id_ordl},
)
row = cursor.fetchone()
print(f"[PERSIST] NEW connection SELECT → row={row}")
assert row is not None, f"Row id_ordl={id_ordl} not found after reconnect — durability FAILED"
assert int(row[0]) == id_ordl, f"id_ordl mismatch: got {row[0]}, expected {id_ordl}"
id_lucrare = int(row[1])
print(f"[PERSIST] ASSERT PASSED: row exists in new connection ✅ (id_lucrare={id_lucrare})")
finally:
conn2.close()
print("[PERSIST] connection 2 closed")
# --- Phase 3: Cleanup — delete child then parent ---
assert id_lucrare is not None, "id_lucrare must be set for cleanup"
conn3 = _connect()
try:
with conn3.cursor() as cursor:
# Child first (FK constraint: DEV_ORDL → NOM_LUCRARI)
cursor.execute(
"DELETE FROM MARIUSM_AUTO.DEV_ORDL WHERE id_ordl = :id",
{"id": id_ordl},
)
deleted_ordl = cursor.rowcount
print(f"[PERSIST] DELETE DEV_ORDL id_ordl={id_ordl}{deleted_ordl} row(s)")
# Parent second
cursor.execute(
"DELETE FROM MARIUSM_AUTO.NOM_LUCRARI WHERE id_lucrare = :id",
{"id": id_lucrare},
)
deleted_nom = cursor.rowcount
print(f"[PERSIST] DELETE NOM_LUCRARI id_lucrare={id_lucrare}{deleted_nom} row(s)")
conn3.commit()
print("[PERSIST] cleanup commit OK ✅")
assert deleted_ordl == 1, f"Expected 1 DEV_ORDL row deleted, got {deleted_ordl}"
assert deleted_nom == 1, f"Expected 1 NOM_LUCRARI row deleted, got {deleted_nom}"
finally:
conn3.close()
print("[PERSIST] connection 3 (cleanup) closed")