feat(mapari): regula 'exclude de la declarare' per operatie + stare preview Nedeclarat
Operatiile care nu se declara la RAR (ex. ITP facturat in service) primesc o regula exclus=1 in operations_mapping, setabila din panoul de mapare al preview-ului de import si din tab-ul Mapari (optiunea 'Nu se declara la RAR'). - resolve_prestatii(excluded_ops): item nemapat cu op exclusa -> adnotat exclus, nu mai e needs_mapping; precedenta: cod explicit > exclus > mapare > reguli text - split_prestatii_excluse: itemii exclusi nu intra niciodata in payload/cheie - preview import: rand cu toate operatiile excluse -> stare 'excluded' (eticheta Nedeclarat), necomis; operatia dispare din panoul de mapat - reresolve/corectie/API: submission cu toate operatiile excluse -> needs_data cu motiv explicit; ingestia API trateaza excluderea la clasificare - migrare: coloana operations_mapping.exclus + rebuild import_rows pentru CHECK-ul resolved_status cu 'excluded' (o singura data, gardat pe sqlite_master) - fix flake: clamp similaritate embeddings la [-1,1] (float32 dadea 1.0000001) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
59
app/db.py
59
app/db.py
@@ -178,6 +178,26 @@ def _migrate(conn: sqlite3.Connection) -> None:
|
||||
conn.execute(
|
||||
"ALTER TABLE import_rows ADD COLUMN reviewed INTEGER NOT NULL DEFAULT 0"
|
||||
)
|
||||
# CHECK-ul resolved_status trebuie sa accepte 'excluded' (operatii excluse de la
|
||||
# declarare). SQLite nu poate altera CHECK -> rebuild o singura data (detectat
|
||||
# pe textul CREATE din sqlite_master).
|
||||
create_sql = str(conn.execute(
|
||||
"SELECT sql FROM sqlite_master WHERE type='table' AND name='import_rows'"
|
||||
).fetchone()["sql"] or "")
|
||||
if "'excluded'" not in create_sql:
|
||||
_rebuild_import_rows_cu_excluded(conn)
|
||||
|
||||
# Coloana operations_mapping.exclus: regula "nu se declara la RAR" per operatie.
|
||||
om_tbl = conn.execute(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='operations_mapping'"
|
||||
).fetchone()
|
||||
if om_tbl:
|
||||
om_cols = {r["name"] for r in conn.execute("PRAGMA table_info(operations_mapping)").fetchall()}
|
||||
if "exclus" not in om_cols:
|
||||
conn.execute(
|
||||
"ALTER TABLE operations_mapping ADD COLUMN exclus INTEGER NOT NULL DEFAULT 0 "
|
||||
"CHECK (exclus IN (0, 1))"
|
||||
)
|
||||
|
||||
# Index batch_id pe submissions (poate lipsi pe DB veche)
|
||||
existing_idx = {r["name"] for r in conn.execute(
|
||||
@@ -201,6 +221,45 @@ def _migrate(conn: sqlite3.Connection) -> None:
|
||||
)
|
||||
|
||||
|
||||
def _rebuild_import_rows_cu_excluded(conn: sqlite3.Connection) -> None:
|
||||
"""Rebuild import_rows cu 'excluded' in CHECK-ul resolved_status.
|
||||
|
||||
Ruleaza O SINGURA DATA pe DB-uri create inainte de starea 'excluded' (gardat de
|
||||
apelant pe textul CREATE). Copiaza toate randurile 1:1 si recreeaza indexul.
|
||||
"""
|
||||
conn.execute("BEGIN IMMEDIATE")
|
||||
try:
|
||||
conn.execute(
|
||||
"CREATE TABLE import_rows_new ("
|
||||
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
|
||||
" batch_id INTEGER NOT NULL REFERENCES import_batches(id) ON DELETE CASCADE,"
|
||||
" row_index INTEGER NOT NULL,"
|
||||
" raw_json TEXT NOT NULL,"
|
||||
" override_json TEXT,"
|
||||
" reviewed INTEGER NOT NULL DEFAULT 0,"
|
||||
" resolved_status TEXT NOT NULL DEFAULT 'pending'"
|
||||
" CHECK (resolved_status IN ("
|
||||
" 'pending','ok','needs_mapping','needs_data',"
|
||||
" 'needs_review','already_sent','duplicate_in_file','excluded'"
|
||||
" )),"
|
||||
" error TEXT"
|
||||
")"
|
||||
)
|
||||
conn.execute(
|
||||
"INSERT INTO import_rows_new "
|
||||
" (id, batch_id, row_index, raw_json, override_json, reviewed, resolved_status, error) "
|
||||
"SELECT id, batch_id, row_index, raw_json, override_json, reviewed, resolved_status, error "
|
||||
"FROM import_rows"
|
||||
)
|
||||
conn.execute("DROP TABLE import_rows")
|
||||
conn.execute("ALTER TABLE import_rows_new RENAME TO import_rows")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_import_rows_batch ON import_rows(batch_id)")
|
||||
conn.execute("COMMIT")
|
||||
except Exception:
|
||||
conn.execute("ROLLBACK")
|
||||
raise
|
||||
|
||||
|
||||
def _migrate_accounts_medii(conn: sqlite3.Connection, acc_cols: set[str]) -> None:
|
||||
"""Coloane medii RAR per cont + backfill din ancora globala.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user