diff --git a/api/app/routers/sync.py b/api/app/routers/sync.py index aab6e69..09f0d7e 100644 --- a/api/app/routers/sync.py +++ b/api/app/routers/sync.py @@ -564,6 +564,13 @@ async def dashboard_orders(page: int = 1, per_page: int = 50, counts["facturate"] = max(0, imported_total - counts["nefacturate"]) counts.setdefault("total", counts.get("imported", 0) + counts.get("skipped", 0) + counts.get("error", 0)) + # Attention metrics: add unresolved SKUs count + try: + stats = await sqlite_service.get_dashboard_stats() + counts["unresolved_skus"] = stats.get("unresolved_skus", 0) + except Exception: + counts["unresolved_skus"] = 0 + # For UNINVOICED filter: apply server-side filtering + pagination if is_uninvoiced_filter: filtered = [o for o in all_orders if o.get("status") in ("IMPORTED", "ALREADY_IMPORTED") and not o.get("invoice")] diff --git a/api/app/services/sqlite_service.py b/api/app/services/sqlite_service.py index 237db92..f9d8a2c 100644 --- a/api/app/services/sqlite_service.py +++ b/api/app/services/sqlite_service.py @@ -739,6 +739,16 @@ async def get_orders(page: int = 1, per_page: int = 50, cursor = await db.execute(f"SELECT COUNT(*) FROM orders {uninv_where}", base_params) uninvoiced_sqlite = (await cursor.fetchone())[0] + # Uninvoiced > 3 days old + uninv_old_clauses = list(base_clauses) + [ + "UPPER(status) IN ('IMPORTED', 'ALREADY_IMPORTED')", + "(factura_numar IS NULL OR factura_numar = '')", + "order_date < datetime('now', '-3 days')", + ] + uninv_old_where = "WHERE " + " AND ".join(uninv_old_clauses) + cursor = await db.execute(f"SELECT COUNT(*) FROM orders {uninv_old_where}", base_params) + uninvoiced_old = (await cursor.fetchone())[0] + return { "orders": [dict(r) for r in rows], "total": total, @@ -754,6 +764,7 @@ async def get_orders(page: int = 1, per_page: int = 50, "cancelled": status_counts.get("CANCELLED", 0), "total": sum(status_counts.values()), "uninvoiced_sqlite": uninvoiced_sqlite, + "uninvoiced_old": uninvoiced_old, } } finally: diff --git a/api/app/static/css/style.css b/api/app/static/css/style.css index 1a8b638..405a271 100644 --- a/api/app/static/css/style.css +++ b/api/app/static/css/style.css @@ -995,3 +995,41 @@ tr.mapping-deleted td { margin: 0; cursor: pointer; } + +/* ── Attention card ──────────────────────────── */ +.attention-card { + display: flex; + align-items: center; + gap: 16px; + padding: 10px 16px; + border-radius: 8px; + font-size: 0.875rem; + margin-bottom: 8px; +} +.attention-ok { + background: var(--success-light); + color: var(--success-text); +} +.attention-alert { + background: var(--surface); + border: 1px solid var(--border); + flex-wrap: wrap; +} +.attention-item { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 4px 10px; + border-radius: 4px; + cursor: pointer; + transition: opacity 0.15s; +} +.attention-item:hover { opacity: 0.8; } +.attention-error { + background: var(--error-light); + color: var(--error-text); +} +.attention-warning { + background: var(--warning-light); + color: var(--warning-text); +} diff --git a/api/app/static/js/dashboard.js b/api/app/static/js/dashboard.js index ee7f760..950ea46 100644 --- a/api/app/static/js/dashboard.js +++ b/api/app/static/js/dashboard.js @@ -301,6 +301,24 @@ async function loadDashOrders() { if (el('cntNef')) el('cntNef').textContent = c.nefacturate || c.uninvoiced || 0; if (el('cntCanc')) el('cntCanc').textContent = c.cancelled || 0; + // Attention card + const attnEl = document.getElementById('attentionCard'); + if (attnEl) { + const errors = c.error || 0; + const unmapped = c.unresolved_skus || 0; + const uninvOld = c.uninvoiced_old || 0; + + if (errors === 0 && unmapped === 0 && uninvOld === 0) { + attnEl.innerHTML = '
Totul in ordine
'; + } else { + let items = []; + if (errors > 0) items.push(` ${errors} erori import`); + if (unmapped > 0) items.push(` ${unmapped} SKU-uri nemapate`); + if (uninvOld > 0) items.push(` ${uninvOld} nefacturate >3 zile`); + attnEl.innerHTML = '
' + items.join('') + '
'; + } + } + const tbody = document.getElementById('dashOrdersBody'); const orders = data.orders || []; diff --git a/api/app/templates/base.html b/api/app/templates/base.html index f4d1a4c..46dba28 100644 --- a/api/app/templates/base.html +++ b/api/app/templates/base.html @@ -19,7 +19,7 @@ {% set rp = request.scope.get('root_path', '') %} - + diff --git a/api/app/templates/dashboard.html b/api/app/templates/dashboard.html index cad8195..b95c200 100644 --- a/api/app/templates/dashboard.html +++ b/api/app/templates/dashboard.html @@ -49,6 +49,7 @@ Comenzi
+