feat(dashboard): redesign UI with smart polling, unified sync card, filter bar
Replace SSE with smart polling (30s idle / 3s when running). Unify sync panel into single two-row card with live progress text. Add unified filter bar (period dropdown, status pills, search) with period-total counts. Add Client/Cont tooltip for different shipping/billing persons. Add SKU mappings pct_total badges + complete/incomplete filter + 409 duplicate check. Add missing SKUs search + rescan progress UX. Migrate SQLite orders schema (shipping_name, billing_name, payment_method, delivery_method). Fix JSON_OUTPUT_DIR path for server running from project root. Fix pagination controls showing top+bottom with per-page selector (25/50/100/250). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -91,7 +91,11 @@ CREATE TABLE IF NOT EXISTS orders (
|
||||
times_skipped INTEGER DEFAULT 0,
|
||||
first_seen_at TEXT DEFAULT (datetime('now')),
|
||||
last_sync_run_id TEXT REFERENCES sync_runs(run_id),
|
||||
updated_at TEXT DEFAULT (datetime('now'))
|
||||
updated_at TEXT DEFAULT (datetime('now')),
|
||||
shipping_name TEXT,
|
||||
billing_name TEXT,
|
||||
payment_method TEXT,
|
||||
delivery_method TEXT
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_orders_status ON orders(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_orders_date ON orders(order_date);
|
||||
@@ -195,18 +199,15 @@ def init_sqlite():
|
||||
);
|
||||
""")
|
||||
# Copy latest record per order_number into orders
|
||||
# Note: old import_orders didn't have address columns — those stay NULL
|
||||
conn.execute("""
|
||||
INSERT INTO orders
|
||||
(order_number, order_date, customer_name, status,
|
||||
id_comanda, id_partener, id_adresa_facturare, id_adresa_livrare,
|
||||
error_message, missing_skus, items_count, last_sync_run_id)
|
||||
id_comanda, id_partener, error_message, missing_skus,
|
||||
items_count, last_sync_run_id)
|
||||
SELECT io.order_number, io.order_date, io.customer_name, io.status,
|
||||
io.id_comanda, io.id_partener,
|
||||
CASE WHEN io.order_number IN (SELECT order_number FROM import_orders WHERE id_adresa_facturare IS NOT NULL) THEN
|
||||
(SELECT id_adresa_facturare FROM import_orders WHERE order_number = io.order_number AND id_adresa_facturare IS NOT NULL LIMIT 1) ELSE NULL END,
|
||||
CASE WHEN io.order_number IN (SELECT order_number FROM import_orders WHERE id_adresa_livrare IS NOT NULL) THEN
|
||||
(SELECT id_adresa_livrare FROM import_orders WHERE order_number = io.order_number AND id_adresa_livrare IS NOT NULL LIMIT 1) ELSE NULL END,
|
||||
io.error_message, io.missing_skus, io.items_count, io.sync_run_id
|
||||
io.id_comanda, io.id_partener, io.error_message, io.missing_skus,
|
||||
io.items_count, io.sync_run_id
|
||||
FROM import_orders io
|
||||
INNER JOIN (
|
||||
SELECT order_number, MAX(id) as max_id
|
||||
@@ -272,6 +273,19 @@ def init_sqlite():
|
||||
conn.execute("ALTER TABLE sync_runs ADD COLUMN error_message TEXT")
|
||||
logger.info("Migrated sync_runs: added column error_message")
|
||||
|
||||
# Migrate orders: add shipping/billing/payment/delivery columns
|
||||
cursor = conn.execute("PRAGMA table_info(orders)")
|
||||
order_cols = {row[1] for row in cursor.fetchall()}
|
||||
for col, typedef in [
|
||||
("shipping_name", "TEXT"),
|
||||
("billing_name", "TEXT"),
|
||||
("payment_method", "TEXT"),
|
||||
("delivery_method", "TEXT"),
|
||||
]:
|
||||
if col not in order_cols:
|
||||
conn.execute(f"ALTER TABLE orders ADD COLUMN {col} {typedef}")
|
||||
logger.info(f"Migrated orders: added column {col}")
|
||||
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
logger.warning(f"Migration check failed: {e}")
|
||||
|
||||
Reference in New Issue
Block a user