fix(anaf-dedup): fix ANAF parsing, facturare addr, compact modal layout
- Fix ANAF API: extract CUI from date_generale (not top-level), fix notFound casing (capital F) - Fix missing facturare address when same ID as livrare (copy instead of skip) - Replace ANAF cache pre-population stub with real logic (3-month CUIs) - Restructure order detail modal: inline 2-col GOMAG|ROA layout with compact address lines replacing collapsed sections - Fix addrMatch() to use field-level comparison with Romanian abbreviation stripping (STR, NR, BL, SC, AP, ET, ETAJ, APART) - Add dashboard "Diferente" filter pill for ANAF-adjusted orders - Update e2e test for new modal structure Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -82,8 +82,8 @@ async def _call_anaf_api(body: list[dict], retry: int = 0) -> dict[str, dict]:
|
||||
# Parse ANAF response
|
||||
found_list = data.get("found", [])
|
||||
for item in found_list:
|
||||
cui_str = str(item.get("cui", ""))
|
||||
date_generals = item.get("date_generale", {})
|
||||
cui_str = str(date_generals.get("cui", ""))
|
||||
results[cui_str] = {
|
||||
"scpTVA": item.get("inregistrare_scop_Tva", {}).get("scpTVA"),
|
||||
"denumire_anaf": date_generals.get("denumire", ""),
|
||||
@@ -91,9 +91,10 @@ async def _call_anaf_api(body: list[dict], retry: int = 0) -> dict[str, dict]:
|
||||
}
|
||||
|
||||
# Not found CUIs
|
||||
notfound_list = data.get("notfound", [])
|
||||
notfound_list = data.get("notFound", [])
|
||||
for item in notfound_list:
|
||||
cui_str = str(item.get("cui", ""))
|
||||
date_gen = item.get("date_generale", {})
|
||||
cui_str = str(date_gen.get("cui", item.get("cui", "")))
|
||||
results[cui_str] = {
|
||||
"scpTVA": None,
|
||||
"denumire_anaf": "",
|
||||
|
||||
@@ -365,6 +365,8 @@ def import_single_order(order, id_pol: int = None, id_sectie: int = None, app_se
|
||||
cur.execute("SELECT strada, numar, localitate, judet FROM vadrese_parteneri WHERE id_adresa = :1", [int(addr_fact_id)])
|
||||
row = cur.fetchone()
|
||||
result["adresa_facturare_roa"] = {"strada": row[0], "numar": row[1], "localitate": row[2], "judet": row[3]} if row else None
|
||||
elif addr_fact_id and addr_fact_id == addr_livr_id:
|
||||
result["adresa_facturare_roa"] = result.get("adresa_livrare_roa")
|
||||
|
||||
# Step 4: Build articles JSON and import order
|
||||
articles_json = build_articles_json(order.items, order, app_settings)
|
||||
|
||||
@@ -696,6 +696,8 @@ async def get_orders(page: int = 1, per_page: int = 50,
|
||||
if status_filter and status_filter not in ("all", "UNINVOICED"):
|
||||
if status_filter.upper() == "IMPORTED":
|
||||
data_clauses.append("UPPER(status) IN ('IMPORTED', 'ALREADY_IMPORTED')")
|
||||
elif status_filter.upper() == "DIFFS":
|
||||
data_clauses.append("(anaf_cod_fiscal_adjusted = 1 OR anaf_denumire_mismatch = 1)")
|
||||
else:
|
||||
data_clauses.append("UPPER(status) = ?")
|
||||
data_params.append(status_filter.upper())
|
||||
@@ -749,6 +751,14 @@ 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
|
||||
diffs_clauses = list(base_clauses) + [
|
||||
"(anaf_cod_fiscal_adjusted = 1 OR anaf_denumire_mismatch = 1)"
|
||||
]
|
||||
diffs_where = "WHERE " + " AND ".join(diffs_clauses)
|
||||
cursor = await db.execute(f"SELECT COUNT(*) FROM orders {diffs_where}", base_params)
|
||||
diffs_count = (await cursor.fetchone())[0]
|
||||
|
||||
return {
|
||||
"orders": [dict(r) for r in rows],
|
||||
"total": total,
|
||||
@@ -765,6 +775,7 @@ async def get_orders(page: int = 1, per_page: int = 50,
|
||||
"total": sum(status_counts.values()),
|
||||
"uninvoiced_sqlite": uninvoiced_sqlite,
|
||||
"uninvoiced_old": uninvoiced_old,
|
||||
"diffs": diffs_count,
|
||||
}
|
||||
}
|
||||
finally:
|
||||
@@ -1072,6 +1083,35 @@ async def bulk_populate_anaf_cache(results: dict[str, dict]):
|
||||
await db.close()
|
||||
|
||||
|
||||
async def get_expired_cuis_for_prepopulate() -> list[str]:
|
||||
"""Get CUIs from recent orders that need ANAF cache refresh."""
|
||||
from ..services import anaf_service
|
||||
db = await get_sqlite()
|
||||
try:
|
||||
cursor = await db.execute("""
|
||||
SELECT DISTINCT cod_fiscal_gomag FROM orders
|
||||
WHERE cod_fiscal_gomag IS NOT NULL
|
||||
AND cod_fiscal_gomag != ''
|
||||
AND order_date >= date('now', '-3 months')
|
||||
""")
|
||||
rows = await cursor.fetchall()
|
||||
|
||||
cuis_to_check = []
|
||||
for row in rows:
|
||||
raw = row["cod_fiscal_gomag"]
|
||||
bare = anaf_service.strip_ro_prefix(raw)
|
||||
if not anaf_service.validate_cui(bare):
|
||||
continue
|
||||
# Check if cache is valid
|
||||
cached = await get_anaf_cache(bare)
|
||||
if cached is None:
|
||||
cuis_to_check.append(bare)
|
||||
|
||||
return cuis_to_check
|
||||
finally:
|
||||
await db.close()
|
||||
|
||||
|
||||
# ── Partner/Address Data on Orders ─────────────────
|
||||
|
||||
async def update_order_partner_data(order_number: str, partner_data: dict):
|
||||
|
||||
@@ -638,20 +638,20 @@ async def run_sync(id_pol: int = None, id_sectie: int = None, run_id: str = None
|
||||
0, len(truly_importable),
|
||||
{"imported": 0, "skipped": skipped_count, "errors": 0, "already_imported": already_imported_count})
|
||||
|
||||
# ANAF cache pre-population check
|
||||
# ANAF cache pre-population: CUIs from last 3 months with expired/missing cache
|
||||
try:
|
||||
db_check = await sqlite_service.get_sqlite()
|
||||
try:
|
||||
cursor = await db_check.execute("SELECT COUNT(*) FROM anaf_cache WHERE checked_at > datetime('now', '-7 days')")
|
||||
row = await cursor.fetchone()
|
||||
cache_count = row[0] if row else 0
|
||||
finally:
|
||||
await db_check.close()
|
||||
|
||||
if cache_count < 10:
|
||||
_log_line(run_id, "ANAF pre-populare cache...")
|
||||
prepop_cuis = await sqlite_service.get_expired_cuis_for_prepopulate()
|
||||
if prepop_cuis:
|
||||
_log_line(run_id, f"ANAF pre-populare: {len(prepop_cuis)} CUI-uri cu cache expirat")
|
||||
prepop_results = await anaf_service.check_vat_status_batch(prepop_cuis)
|
||||
if prepop_results:
|
||||
await sqlite_service.bulk_populate_anaf_cache(prepop_results)
|
||||
_log_line(run_id, f"ANAF pre-populare: {len(prepop_results)} rezultate stocate")
|
||||
else:
|
||||
_log_line(run_id, "ANAF pre-populare: cache complet")
|
||||
except Exception as e:
|
||||
logger.warning(f"ANAF cache pre-population check failed: {e}")
|
||||
_log_line(run_id, f"ANAF pre-populare eroare: {e}")
|
||||
logger.warning(f"ANAF cache pre-population failed: {e}")
|
||||
|
||||
# Step 4: ANAF batch verification for company CUIs
|
||||
company_cuis = set()
|
||||
|
||||
Reference in New Issue
Block a user