feat(partner): detect and resync partner mismatches on already-imported orders
Detects PF↔PJ transitions and CUI changes after import; auto-resyncs uninvoiced orders (max 5/cycle) and shows visual alert for invoiced ones. - SQLite: partner_mismatch column + batch helpers - sync_service: detection loop + _resync_partner_for_order - dashboard: red dot + attention card indicator - modal: alert with contextual message and resync button Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -701,6 +701,7 @@ async def get_orders(page: int = 1, per_page: int = 50,
|
||||
elif status_filter.upper() == "DIFFS":
|
||||
data_clauses.append(
|
||||
"(anaf_cod_fiscal_adjusted = 1 OR anaf_denumire_mismatch = 1"
|
||||
" OR partner_mismatch = 1"
|
||||
" OR (cod_fiscal_gomag IS NOT NULL AND cod_fiscal_gomag != '' AND anaf_platitor_tva IS NOT NULL"
|
||||
" AND anaf_cod_fiscal_adjusted != 1"
|
||||
" AND ((UPPER(cod_fiscal_gomag) LIKE 'RO%' AND anaf_platitor_tva = 0)"
|
||||
@@ -759,9 +760,10 @@ async def get_orders(page: int = 1, per_page: int = 50,
|
||||
cursor = await db.execute(f"SELECT COUNT(*) FROM orders {uninv_old_where}", base_params)
|
||||
uninvoiced_old = (await cursor.fetchone())[0]
|
||||
|
||||
# Diffs count: orders with ANAF adjustments or TVA mismatch (not address)
|
||||
# Diffs count: orders with ANAF adjustments, TVA mismatch, or partner mismatch
|
||||
diffs_clauses = list(base_clauses) + [
|
||||
"(anaf_cod_fiscal_adjusted = 1 OR anaf_denumire_mismatch = 1"
|
||||
" OR partner_mismatch = 1"
|
||||
" OR (cod_fiscal_gomag IS NOT NULL AND cod_fiscal_gomag != '' AND anaf_platitor_tva IS NOT NULL"
|
||||
" AND anaf_cod_fiscal_adjusted != 1"
|
||||
" AND ((UPPER(cod_fiscal_gomag) LIKE 'RO%' AND anaf_platitor_tva = 0)"
|
||||
@@ -771,6 +773,12 @@ async def get_orders(page: int = 1, per_page: int = 50,
|
||||
cursor = await db.execute(f"SELECT COUNT(*) FROM orders {diffs_where}", base_params)
|
||||
diffs_count = (await cursor.fetchone())[0]
|
||||
|
||||
# Partner mismatches count
|
||||
pm_clauses = list(base_clauses) + ["partner_mismatch = 1"]
|
||||
pm_where = "WHERE " + " AND ".join(pm_clauses)
|
||||
cursor = await db.execute(f"SELECT COUNT(*) FROM orders {pm_where}", base_params)
|
||||
partner_mismatches_count = (await cursor.fetchone())[0]
|
||||
|
||||
return {
|
||||
"orders": [dict(r) for r in rows],
|
||||
"total": total,
|
||||
@@ -788,6 +796,7 @@ async def get_orders(page: int = 1, per_page: int = 50,
|
||||
"uninvoiced_sqlite": uninvoiced_sqlite,
|
||||
"uninvoiced_old": uninvoiced_old,
|
||||
"diffs": diffs_count,
|
||||
"partner_mismatches": partner_mismatches_count,
|
||||
}
|
||||
}
|
||||
finally:
|
||||
@@ -1382,3 +1391,76 @@ async def set_incomplete_addresses_count(count: int):
|
||||
await db.commit()
|
||||
finally:
|
||||
await db.close()
|
||||
|
||||
|
||||
# ── Partner Mismatch ──────────────────────────────
|
||||
|
||||
async def get_orders_partner_data_batch(order_numbers: list) -> dict:
|
||||
"""Return {order_number: {cod_fiscal_gomag, denumire_roa, id_partener, factura_numar, id_comanda}}."""
|
||||
if not order_numbers:
|
||||
return {}
|
||||
db = await get_sqlite()
|
||||
try:
|
||||
result = {}
|
||||
for i in range(0, len(order_numbers), 500):
|
||||
batch = order_numbers[i:i+500]
|
||||
placeholders = ",".join("?" * len(batch))
|
||||
cursor = await db.execute(
|
||||
f"SELECT order_number, cod_fiscal_gomag, denumire_roa, id_partener, "
|
||||
f"factura_numar, id_comanda FROM orders WHERE order_number IN ({placeholders})",
|
||||
batch
|
||||
)
|
||||
for row in await cursor.fetchall():
|
||||
result[row[0]] = {
|
||||
"cod_fiscal_gomag": row[1],
|
||||
"denumire_roa": row[2],
|
||||
"id_partener": row[3],
|
||||
"factura_numar": row[4],
|
||||
"id_comanda": row[5],
|
||||
}
|
||||
return result
|
||||
finally:
|
||||
await db.close()
|
||||
|
||||
|
||||
async def update_partner_mismatch_batch(updates: list) -> None:
|
||||
"""Update partner_mismatch flag for a batch of orders.
|
||||
Each item: {order_number, partner_mismatch: 0|1}
|
||||
"""
|
||||
if not updates:
|
||||
return
|
||||
db = await get_sqlite()
|
||||
try:
|
||||
await db.executemany(
|
||||
"UPDATE orders SET partner_mismatch = ?, updated_at = datetime('now') WHERE order_number = ?",
|
||||
[(u["partner_mismatch"], u["order_number"]) for u in updates]
|
||||
)
|
||||
await db.commit()
|
||||
finally:
|
||||
await db.close()
|
||||
|
||||
|
||||
async def update_partner_resync_data(order_number: str, data: dict) -> None:
|
||||
"""Update partner fields + clear partner_mismatch after a successful resync."""
|
||||
db = await get_sqlite()
|
||||
try:
|
||||
await db.execute("""
|
||||
UPDATE orders SET
|
||||
id_partener = ?,
|
||||
cod_fiscal_gomag = ?,
|
||||
cod_fiscal_roa = ?,
|
||||
denumire_roa = ?,
|
||||
partner_mismatch = ?,
|
||||
updated_at = datetime('now')
|
||||
WHERE order_number = ?
|
||||
""", (
|
||||
data.get("id_partener"),
|
||||
data.get("cod_fiscal_gomag"),
|
||||
data.get("cod_fiscal_roa"),
|
||||
data.get("denumire_roa"),
|
||||
data.get("partner_mismatch", 0),
|
||||
order_number,
|
||||
))
|
||||
await db.commit()
|
||||
finally:
|
||||
await db.close()
|
||||
|
||||
Reference in New Issue
Block a user