"""Teste T7: batch_id/row_index scope reresolve_account (R1 INCHIS). Verify: (a) salvare mapare in batch A NU trimite randuri din batch B / feed API. (b) canal API (batch_id NULL) tot se re-rezolva ca azi (regresie). """ from __future__ import annotations import json import os import tempfile import pytest @pytest.fixture() def env(monkeypatch): tmp = tempfile.mkdtemp() monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "t7.db")) from app.config import get_settings get_settings.cache_clear() from app.db import init_db init_db() yield monkeypatch get_settings.cache_clear() @pytest.fixture() def conn(env): from app.db import get_connection c = get_connection() yield c c.close() def _insert_batch(conn, account_id=1): """Creeaza un import_batch si returneaza id-ul.""" cur = conn.execute( "INSERT INTO import_batches (account_id, filename, status) VALUES (?, ?, 'staging')", (account_id, "test.xlsx"), ) return int(cur.lastrowid) def _insert_submission(conn, account_id=1, batch_id=None, cod_op="ITP-1", key_sfx=None): """Insereaza un submission needs_mapping (cu sau fara batch).""" content = { "vin": "WVWZZZ1KZAW000123", "nr_inmatriculare": "B1", "data_prestatie": "2026-06-15", "odometru_final": "123456", "prestatii": [{"cod_op_service": cod_op, "denumire": "Test"}], } sfx = key_sfx or os.urandom(4).hex() if batch_id is not None: cur = conn.execute( "INSERT INTO submissions (idempotency_key, account_id, status, payload_json, batch_id) " "VALUES (?, ?, 'needs_mapping', ?, ?)", (f"k-{sfx}", account_id, json.dumps(content), batch_id), ) else: cur = conn.execute( "INSERT INTO submissions (idempotency_key, account_id, status, payload_json) " "VALUES (?, ?, 'needs_mapping', ?)", (f"k-{sfx}", account_id, json.dumps(content)), ) return int(cur.lastrowid) def _add_mapping(conn, account_id=1, cod_op="ITP-1", cod_prestatie="OE-1", auto_send=True): conn.execute( "INSERT OR IGNORE INTO nomenclator_rar (cod_prestatie, nume_prestatie) VALUES (?, ?)", (cod_prestatie, "Test operatie"), ) conn.execute( "INSERT OR REPLACE INTO operations_mapping (account_id, cod_op_service, cod_prestatie, auto_send) " "VALUES (?, ?, ?, ?)", (account_id, cod_op, cod_prestatie, 1 if auto_send else 0), ) # --- Scoping --- def test_reresolve_batch_specific_nu_atinge_alt_batch(conn): """(a) reresolve_account cu batch_id=A nu atinge randuri din batch_id=B.""" from app.mapping import reresolve_account batch_a = _insert_batch(conn) batch_b = _insert_batch(conn) sid_a = _insert_submission(conn, batch_id=batch_a, cod_op="ITP-1", key_sfx="a1") sid_b = _insert_submission(conn, batch_id=batch_b, cod_op="ITP-1", key_sfx="b1") _add_mapping(conn, cod_op="ITP-1", cod_prestatie="OE-1", auto_send=True) # Re-rezolva NUMAI batch_a stats = reresolve_account(conn, 1, batch_id=batch_a) assert stats["requeued"] == 1 # Batch B nemodificat row_a = conn.execute("SELECT status FROM submissions WHERE id=?", (sid_a,)).fetchone() row_b = conn.execute("SELECT status FROM submissions WHERE id=?", (sid_b,)).fetchone() assert row_a["status"] == "queued", "batch A trebuie requeued" assert row_b["status"] == "needs_mapping", "batch B trebuie sa ramana needs_mapping" def test_reresolve_fara_batch_nu_atinge_batches(conn): """(a) reresolve fara batch (POST /v1/mapari) NU atinge batch submissions.""" from app.mapping import reresolve_account batch_a = _insert_batch(conn) sid_batch = _insert_submission(conn, batch_id=batch_a, cod_op="ITP-1", key_sfx="ba") sid_api = _insert_submission(conn, batch_id=None, cod_op="ITP-1", key_sfx="ap") _add_mapping(conn, cod_op="ITP-1", cod_prestatie="OE-1", auto_send=True) # Fara batch (cum apeleaza POST /v1/mapari) stats = reresolve_account(conn, 1) assert stats["requeued"] == 1 # numai API canal row_batch = conn.execute("SELECT status FROM submissions WHERE id=?", (sid_batch,)).fetchone() row_api = conn.execute("SELECT status FROM submissions WHERE id=?", (sid_api,)).fetchone() assert row_batch["status"] == "needs_mapping", "batch submission NU trebuie atins de reresolve global" assert row_api["status"] == "queued", "API canal trebuie requeued" def test_reresolve_canal_api_regresie(conn): """(b) Canal API (batch_id NULL) tot se re-rezolva ca azi.""" from app.mapping import reresolve_account # Doua submission-uri API fara batch sid1 = _insert_submission(conn, batch_id=None, cod_op="ITP-2", key_sfx="r1") sid2 = _insert_submission(conn, batch_id=None, cod_op="ITP-2", key_sfx="r2") _add_mapping(conn, cod_op="ITP-2", cod_prestatie="OE-1", auto_send=True) stats = reresolve_account(conn, 1) # fara batch — re-rezolva tot API assert stats["requeued"] == 2 for sid in (sid1, sid2): row = conn.execute("SELECT status FROM submissions WHERE id=?", (sid,)).fetchone() assert row["status"] == "queued" def test_reresolve_batch_explicit_nu_atinge_api(conn): """Batch explicit: nu atinge feed API (batch_id IS NULL).""" from app.mapping import reresolve_account batch_a = _insert_batch(conn) sid_batch = _insert_submission(conn, batch_id=batch_a, cod_op="ITP-3", key_sfx="ba3") sid_api = _insert_submission(conn, batch_id=None, cod_op="ITP-3", key_sfx="ap3") _add_mapping(conn, cod_op="ITP-3", cod_prestatie="OE-1", auto_send=True) stats = reresolve_account(conn, 1, batch_id=batch_a) assert stats["requeued"] == 1 row_batch = conn.execute("SELECT status FROM submissions WHERE id=?", (sid_batch,)).fetchone() row_api = conn.execute("SELECT status FROM submissions WHERE id=?", (sid_api,)).fetchone() assert row_batch["status"] == "queued" assert row_api["status"] == "needs_mapping", "API canal nu trebuie atins de reresolve batch-specific" def test_submissions_au_batch_id_si_row_index(conn): """Schema: submissions.batch_id si .row_index exista si se pot seta.""" batch_id = _insert_batch(conn) conn.execute( "INSERT INTO submissions (idempotency_key, account_id, status, payload_json, batch_id, row_index) " "VALUES (?, ?, 'queued', '{}', ?, ?)", ("k-test-bi", 1, batch_id, 5), ) row = conn.execute("SELECT batch_id, row_index FROM submissions WHERE idempotency_key='k-test-bi'").fetchone() assert row["batch_id"] == batch_id assert row["row_index"] == 5 def test_reresolve_multiple_batches_izolate(conn): """R1 INCHIS: 3 batches, fiecare re-rezolvat independent.""" from app.mapping import reresolve_account batches = [_insert_batch(conn) for _ in range(3)] sids = { b: _insert_submission(conn, batch_id=b, cod_op="ITP-4", key_sfx=f"mb{i}") for i, b in enumerate(batches) } _add_mapping(conn, cod_op="ITP-4", cod_prestatie="OE-1", auto_send=True) # Re-rezolva batch 0, verifica ca 1 si 2 nu sunt atinse reresolve_account(conn, 1, batch_id=batches[0]) statuses = { b: conn.execute("SELECT status FROM submissions WHERE id=?", (sid,)).fetchone()["status"] for b, sid in sids.items() } assert statuses[batches[0]] == "queued" assert statuses[batches[1]] == "needs_mapping" assert statuses[batches[2]] == "needs_mapping"