feat(ux): import compact + preview format Trimiteri + navigatie + scoatere auto_send (5.11)
8 stories TDD (echipa Sonnet, lead orchestreaza). US-001 scoate hold-ul auto_send din mapare (has_no_auto_send->False, simbol pastrat; cod rezolvat->queued). US-002 scoate bifa auto_send din UI. US-003 preview pas 3 in format .tabel-trimiteri (STARI_PREVIEW + nota_umana_preview, fara repr Python; view-model prez). US-004 filtre layout/stil ca referinta + buton Custom. US-005 navigatie Trimiteri/Mapari sub contoare pe toate paginile. US-006 import <details> nativ colapsabil. US-007 post-commit reveal (OOB _coada/_status + HX-Trigger). US-008 auto-refresh dupa actiuni (nudge eliminat). VERIFY context curat PASS (8/8). /code-review high: 3 buguri reparate (tab nav la self-refresh, pill Custom valori stale, nota_umana_preview precedenta needs_mapping). 934 passed, 1 skipped. Backend trimitere + schema NEATINSE. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -380,9 +380,12 @@ def test_unmapped_are_3niveluri(client):
|
||||
assert err["fix"]
|
||||
|
||||
|
||||
def test_auto_send_oprit_3niveluri(client):
|
||||
"""Mapare cu auto_send=0 -> needs_mapping; rar_error are cheie 'auto_send'
|
||||
PASTRATA + campurile AUTO_SEND_OPRIT (cod/problema/cauza/fix)."""
|
||||
def test_auto_send_oprit_3niveluri_noul_comportament(client):
|
||||
"""Mapare cu auto_send=0 -> queued (auto_send ignorat dupa US-001).
|
||||
|
||||
Dupa US-001: classify_prezentare nu mai produce ramura AUTO_SEND_OPRIT.
|
||||
O operatie cu cod rezolvat (indiferent de auto_send) -> queued direct.
|
||||
"""
|
||||
import json
|
||||
from app.mapping import classify_prezentare
|
||||
|
||||
@@ -396,15 +399,9 @@ def test_auto_send_oprit_3niveluri(client):
|
||||
mapping = {"OP_REVIEW": "OE-1"}
|
||||
mapping_meta = {"OP_REVIEW": {"cod_prestatie": "OE-1", "auto_send": False}}
|
||||
res = classify_prezentare(content, mapping, mapping_meta)
|
||||
assert res["status"] == "needs_mapping"
|
||||
err = json.loads(res["rar_error"])
|
||||
# Cheia originala pastrata
|
||||
assert "auto_send" in err
|
||||
# 3 niveluri prezente
|
||||
assert err["cod"] == "AUTO_SEND_OPRIT"
|
||||
assert err["problema"]
|
||||
assert err["cauza"]
|
||||
assert err["fix"]
|
||||
assert res["status"] == "queued", (
|
||||
f"dupa US-001 auto_send=0 -> queued (nu needs_mapping), got {res['status']}"
|
||||
)
|
||||
|
||||
|
||||
def test_needs_data_pass_through(client):
|
||||
@@ -431,3 +428,153 @@ def test_needs_data_pass_through(client):
|
||||
assert "cod" in e, f"lipseste 'cod' in {e}"
|
||||
assert "problema" in e, f"lipseste 'problema' in {e}"
|
||||
assert "fix" in e, f"lipseste 'fix' in {e}"
|
||||
|
||||
|
||||
# =========================================================================== #
|
||||
# US-001: Scoate hold auto_send din mapare — teste RED (inainte de implementare)
|
||||
# =========================================================================== #
|
||||
|
||||
@pytest.fixture()
|
||||
def db_conn(monkeypatch, tmp_path):
|
||||
"""Conexiune directa la o DB temporara, fara client HTTP."""
|
||||
db_path = str(tmp_path / "us001.db")
|
||||
monkeypatch.setenv("AUTOPASS_DB_PATH", db_path)
|
||||
from app.config import get_settings
|
||||
get_settings.cache_clear()
|
||||
from app.db import init_db
|
||||
init_db()
|
||||
from app.db import get_connection
|
||||
c = get_connection()
|
||||
yield c
|
||||
c.close()
|
||||
get_settings.cache_clear()
|
||||
|
||||
|
||||
def test_operatie_mapata_intra_in_queued_indiferent_de_autosend():
|
||||
"""classify_prezentare cu mapare auto_send=0 -> queued (nu needs_mapping).
|
||||
|
||||
Dupa US-001: has_no_auto_send nu mai blocheaza; un cod rezolvat e direct queued.
|
||||
"""
|
||||
from app.mapping import classify_prezentare
|
||||
content = {
|
||||
"vin": "WVWZZZ1KZAW000123",
|
||||
"nr_inmatriculare": "B999TST",
|
||||
"data_prestatie": "2026-06-15",
|
||||
"odometru_final": "123456",
|
||||
"prestatii": [{"cod_op_service": "OP_REVIEW", "denumire": "Operatie cu review"}],
|
||||
}
|
||||
mapping = {"OP_REVIEW": "OE-1"}
|
||||
mapping_meta = {"OP_REVIEW": {"cod_prestatie": "OE-1", "auto_send": False}}
|
||||
valid_codes = {"OE-1"}
|
||||
result = classify_prezentare(content, mapping, mapping_meta, valid_codes)
|
||||
assert result["status"] == "queued", (
|
||||
f"asteptat queued (auto_send ignorat), got {result['status']}: {result.get('rar_error')}"
|
||||
)
|
||||
|
||||
|
||||
def test_regula_text_rezolvata_nu_mai_tine_randul():
|
||||
"""Regula text cu auto_send=0 rezolva codul -> queued (nu needs_mapping held).
|
||||
|
||||
Dupa US-001: regula_fara_autosend nu se mai seteaza; codul rezolvat = queued direct.
|
||||
"""
|
||||
from app.mapping import classify_prezentare
|
||||
content = {
|
||||
"vin": "WVWZZZ1KZAW000123",
|
||||
"nr_inmatriculare": "B999TST",
|
||||
"data_prestatie": "2026-06-15",
|
||||
"odometru_final": "123456",
|
||||
"prestatii": [{"cod_op_service": "X99", "denumire": "Verificare faruri"}],
|
||||
}
|
||||
text_rules = [{"pattern": "verificare", "cod_prestatie": "OE-2", "auto_send": 0, "priority": 0}]
|
||||
valid_codes = {"OE-2"}
|
||||
result = classify_prezentare(content, {}, {}, valid_codes, text_rules)
|
||||
assert result["status"] == "queued", (
|
||||
f"asteptat queued (regula text, auto_send ignorat), got {result['status']}: {result.get('rar_error')}"
|
||||
)
|
||||
|
||||
|
||||
def test_fara_stare_needs_mapping_pe_auto_send_oprit():
|
||||
"""has_no_auto_send intotdeauna False dupa US-001; nu mai produce AUTO_SEND_OPRIT."""
|
||||
from app.mapping import has_no_auto_send
|
||||
mapping_meta_false = {"OP_REVIEW": {"cod_prestatie": "OE-1", "auto_send": False}}
|
||||
resolved = [{"cod_op_service": "OP_REVIEW", "cod_prestatie": "OE-1"}]
|
||||
assert has_no_auto_send(resolved, mapping_meta_false) is False, (
|
||||
"has_no_auto_send trebuie sa intoarca mereu False dupa US-001"
|
||||
)
|
||||
resolved_cu_flag = [{"cod_op_service": "X", "cod_prestatie": "OE-1", "regula_fara_autosend": True}]
|
||||
assert has_no_auto_send(resolved_cu_flag, {}) is False, (
|
||||
"has_no_auto_send ignora regula_fara_autosend dupa US-001"
|
||||
)
|
||||
|
||||
|
||||
def test_niciun_rand_existent_nu_se_dezgheata(db_conn):
|
||||
"""Randuri legacy needs_mapping-din-auto_send: fara afordanta UI (cod prezent),
|
||||
dezghetabile via reresolve_account explicit (nu automat).
|
||||
|
||||
_nemapate_pentru_submission -> [] (fara panou mapare in UI).
|
||||
reresolve_account cu mapare activa -> requeued=1 (dezghet via actiune explicita).
|
||||
"""
|
||||
import json as _json
|
||||
payload = {
|
||||
"vin": "WVWZZZ1KZAW000123", "nr_inmatriculare": "B1",
|
||||
"data_prestatie": "2026-06-15", "odometru_final": "123456",
|
||||
"prestatii": [{"cod_op_service": "X1", "cod_prestatie": "OE-1"}],
|
||||
}
|
||||
rar_error = _json.dumps({"auto_send": "cod mapat cu auto_send=0; review manual"})
|
||||
db_conn.execute(
|
||||
"INSERT INTO submissions (idempotency_key, account_id, status, payload_json, rar_error) "
|
||||
"VALUES (?, ?, ?, ?, ?)",
|
||||
("k-legacy-us001", 1, "needs_mapping", _json.dumps(payload), rar_error),
|
||||
)
|
||||
db_conn.execute(
|
||||
"INSERT OR IGNORE INTO nomenclator_rar (cod_prestatie, nume_prestatie) VALUES ('OE-1', 'Test')"
|
||||
)
|
||||
db_conn.execute(
|
||||
"INSERT OR REPLACE INTO operations_mapping "
|
||||
"(account_id, cod_op_service, cod_prestatie, auto_send) VALUES (1, 'X1', 'OE-1', 0)"
|
||||
)
|
||||
db_conn.commit()
|
||||
|
||||
row = db_conn.execute(
|
||||
"SELECT * FROM submissions WHERE idempotency_key='k-legacy-us001'"
|
||||
).fetchone()
|
||||
nomenclator = [{"cod_prestatie": "OE-1", "nume_prestatie": "Test"}]
|
||||
|
||||
# Nicio afordanta UI (cod deja prezent -> nu se arata panoul de mapare)
|
||||
from app.web.routes import _nemapate_pentru_submission
|
||||
assert _nemapate_pentru_submission(row, nomenclator) == [], (
|
||||
"_nemapate_pentru_submission trebuie sa intoarca [] (cod deja prezent)"
|
||||
)
|
||||
|
||||
# Dezghetare via reresolve_account explicit (actiune admin la deploy)
|
||||
from app.mapping import reresolve_account
|
||||
stats = reresolve_account(db_conn, 1)
|
||||
assert stats["requeued"] == 1, (
|
||||
f"reresolve_account trebuie sa requeueze randul legacy: {stats}"
|
||||
)
|
||||
row2 = db_conn.execute(
|
||||
"SELECT status FROM submissions WHERE idempotency_key='k-legacy-us001'"
|
||||
).fetchone()
|
||||
assert row2["status"] == "queued"
|
||||
|
||||
|
||||
def test_canal_api_auto_send_ignorat_intra_queued():
|
||||
"""classify_prezentare (canal API) cu mapping_meta auto_send=0 -> queued.
|
||||
|
||||
Campul auto_send din mapping_meta nu mai afecteaza decizia de clasificare.
|
||||
"""
|
||||
from app.mapping import classify_prezentare
|
||||
content = {
|
||||
"vin": "WVWZZZ1KZAW000123",
|
||||
"nr_inmatriculare": "B999TST",
|
||||
"data_prestatie": "2026-06-15",
|
||||
"odometru_final": "123456",
|
||||
"prestatii": [{"cod_op_service": "ITP-CHECK", "denumire": "Inspectie"}],
|
||||
}
|
||||
mapping = {"ITP-CHECK": "OE-1"}
|
||||
mapping_meta = {"ITP-CHECK": {"cod_prestatie": "OE-1", "auto_send": False}}
|
||||
valid_codes = {"OE-1"}
|
||||
result = classify_prezentare(content, mapping, mapping_meta, valid_codes)
|
||||
assert result["status"] == "queued", (
|
||||
f"canal API: auto_send ignorat -> asteptat queued, got {result['status']}"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user