import json import logging from datetime import datetime from ..database import get_sqlite, get_sqlite_sync logger = logging.getLogger(__name__) async def create_sync_run(run_id: str, json_files: int = 0): """Create a new sync run record.""" db = await get_sqlite() try: await db.execute(""" INSERT INTO sync_runs (run_id, started_at, status, json_files) VALUES (?, datetime('now'), 'running', ?) """, (run_id, json_files)) await db.commit() finally: await db.close() async def update_sync_run(run_id: str, status: str, total_orders: int = 0, imported: int = 0, skipped: int = 0, errors: int = 0, error_message: str = None): """Update sync run with results.""" db = await get_sqlite() try: await db.execute(""" UPDATE sync_runs SET finished_at = datetime('now'), status = ?, total_orders = ?, imported = ?, skipped = ?, errors = ?, error_message = ? WHERE run_id = ? """, (status, total_orders, imported, skipped, errors, error_message, run_id)) await db.commit() finally: await db.close() async def add_import_order(sync_run_id: str, order_number: str, order_date: str, customer_name: str, status: str, id_comanda: int = None, id_partener: int = None, error_message: str = None, missing_skus: list = None, items_count: int = 0): """Record an individual order import result.""" db = await get_sqlite() try: await db.execute(""" INSERT INTO import_orders (sync_run_id, order_number, order_date, customer_name, status, id_comanda, id_partener, error_message, missing_skus, items_count) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, (sync_run_id, order_number, order_date, customer_name, status, id_comanda, id_partener, error_message, json.dumps(missing_skus) if missing_skus else None, items_count)) await db.commit() finally: await db.close() async def track_missing_sku(sku: str, product_name: str = "", order_count: int = 0, order_numbers: str = None, customers: str = None): """Track a missing SKU with order context.""" db = await get_sqlite() try: await db.execute(""" INSERT OR IGNORE INTO missing_skus (sku, product_name) VALUES (?, ?) """, (sku, product_name)) # Update context columns (always update with latest data) if order_count or order_numbers or customers: await db.execute(""" UPDATE missing_skus SET order_count = ?, order_numbers = ?, customers = ? WHERE sku = ? """, (order_count, order_numbers, customers, sku)) await db.commit() finally: await db.close() async def resolve_missing_sku(sku: str): """Mark a missing SKU as resolved.""" db = await get_sqlite() try: await db.execute(""" UPDATE missing_skus SET resolved = 1, resolved_at = datetime('now') WHERE sku = ? """, (sku,)) await db.commit() finally: await db.close() async def get_missing_skus_paginated(page: int = 1, per_page: int = 20, resolved: int = 0): """Get paginated missing SKUs.""" db = await get_sqlite() try: offset = (page - 1) * per_page cursor = await db.execute( "SELECT COUNT(*) FROM missing_skus WHERE resolved = ?", (resolved,) ) total = (await cursor.fetchone())[0] cursor = await db.execute(""" SELECT sku, product_name, first_seen, resolved, resolved_at, order_count, order_numbers, customers FROM missing_skus WHERE resolved = ? ORDER BY order_count DESC, first_seen DESC LIMIT ? OFFSET ? """, (resolved, per_page, offset)) rows = await cursor.fetchall() return { "missing_skus": [dict(row) for row in rows], "total": total, "page": page, "per_page": per_page, "pages": (total + per_page - 1) // per_page if total > 0 else 0 } finally: await db.close() async def get_sync_runs(page: int = 1, per_page: int = 20): """Get paginated sync run history.""" db = await get_sqlite() try: offset = (page - 1) * per_page cursor = await db.execute("SELECT COUNT(*) FROM sync_runs") total = (await cursor.fetchone())[0] cursor = await db.execute(""" SELECT * FROM sync_runs ORDER BY started_at DESC LIMIT ? OFFSET ? """, (per_page, offset)) rows = await cursor.fetchall() return { "runs": [dict(row) for row in rows], "total": total, "page": page, "pages": (total + per_page - 1) // per_page if total > 0 else 0 } finally: await db.close() async def get_sync_run_detail(run_id: str): """Get details for a specific sync run including its orders.""" db = await get_sqlite() try: cursor = await db.execute( "SELECT * FROM sync_runs WHERE run_id = ?", (run_id,) ) run = await cursor.fetchone() if not run: return None cursor = await db.execute(""" SELECT * FROM import_orders WHERE sync_run_id = ? ORDER BY created_at """, (run_id,)) orders = await cursor.fetchall() return { "run": dict(run), "orders": [dict(o) for o in orders] } finally: await db.close() async def get_dashboard_stats(): """Get stats for the dashboard.""" db = await get_sqlite() try: # Total imported cursor = await db.execute( "SELECT COUNT(*) FROM import_orders WHERE status = 'IMPORTED'" ) imported = (await cursor.fetchone())[0] # Total skipped cursor = await db.execute( "SELECT COUNT(*) FROM import_orders WHERE status = 'SKIPPED'" ) skipped = (await cursor.fetchone())[0] # Total errors cursor = await db.execute( "SELECT COUNT(*) FROM import_orders WHERE status = 'ERROR'" ) errors = (await cursor.fetchone())[0] # Missing SKUs (unresolved) cursor = await db.execute( "SELECT COUNT(*) FROM missing_skus WHERE resolved = 0" ) missing = (await cursor.fetchone())[0] # Article stats from last sync cursor = await db.execute(""" SELECT COUNT(DISTINCT sku) FROM missing_skus """) total_missing_skus = (await cursor.fetchone())[0] cursor = await db.execute(""" SELECT COUNT(DISTINCT sku) FROM missing_skus WHERE resolved = 0 """) unresolved_skus = (await cursor.fetchone())[0] # Last sync run cursor = await db.execute(""" SELECT * FROM sync_runs ORDER BY started_at DESC LIMIT 1 """) last_run = await cursor.fetchone() return { "imported": imported, "skipped": skipped, "errors": errors, "missing_skus": missing, "total_tracked_skus": total_missing_skus, "unresolved_skus": unresolved_skus, "last_run": dict(last_run) if last_run else None } finally: await db.close() async def get_scheduler_config(): """Get scheduler configuration from SQLite.""" db = await get_sqlite() try: cursor = await db.execute("SELECT key, value FROM scheduler_config") rows = await cursor.fetchall() return {row["key"]: row["value"] for row in rows} finally: await db.close() async def set_scheduler_config(key: str, value: str): """Set a scheduler configuration value.""" db = await get_sqlite() try: await db.execute(""" INSERT OR REPLACE INTO scheduler_config (key, value) VALUES (?, ?) """, (key, value)) await db.commit() finally: await db.close()