fix(dashboard): fix pill counts and Bootstrap UI cleanup

- IMPORTED pill now includes ALREADY_IMPORTED orders in count
- UNINVOICED filter includes ALREADY_IMPORTED orders
- Pill counts (Toate/Importate/Omise/Erori/Nefacturate) always reflect
  full period+search, independent of active status filter
- Nefacturate count computed from SQLite cache across full period,
  not just current page
- Bootstrap UI: design tokens, soft badge pills, consistent font sizes,
  purge inline styles from templates, move badge-pct to style.css

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-03-14 21:05:43 +00:00
parent b69b5e7104
commit 15ccbe028a
8 changed files with 283 additions and 223 deletions

View File

@@ -623,25 +623,34 @@ async def get_orders(page: int = 1, per_page: int = 50,
"""
db = await get_sqlite()
try:
where_clauses = []
params = []
# Period + search clauses (used for counts — never include status filter)
base_clauses = []
base_params = []
if period_days and period_days > 0:
where_clauses.append("order_date >= date('now', ?)")
params.append(f"-{period_days} days")
base_clauses.append("order_date >= date('now', ?)")
base_params.append(f"-{period_days} days")
elif period_days == 0 and period_start and period_end:
where_clauses.append("order_date BETWEEN ? AND ?")
params.extend([period_start, period_end])
base_clauses.append("order_date BETWEEN ? AND ?")
base_params.extend([period_start, period_end])
if search:
where_clauses.append("(order_number LIKE ? OR customer_name LIKE ?)")
params.extend([f"%{search}%", f"%{search}%"])
base_clauses.append("(order_number LIKE ? OR customer_name LIKE ?)")
base_params.extend([f"%{search}%", f"%{search}%"])
# Data query adds status filter on top of base filters
data_clauses = list(base_clauses)
data_params = list(base_params)
if status_filter and status_filter not in ("all", "UNINVOICED"):
where_clauses.append("UPPER(status) = ?")
params.append(status_filter.upper())
if status_filter.upper() == "IMPORTED":
data_clauses.append("UPPER(status) IN ('IMPORTED', 'ALREADY_IMPORTED')")
else:
data_clauses.append("UPPER(status) = ?")
data_params.append(status_filter.upper())
where = ("WHERE " + " AND ".join(where_clauses)) if where_clauses else ""
where = ("WHERE " + " AND ".join(data_clauses)) if data_clauses else ""
counts_where = ("WHERE " + " AND ".join(base_clauses)) if base_clauses else ""
allowed_sort = {"order_date", "order_number", "customer_name", "items_count",
"status", "first_seen_at", "updated_at"}
@@ -650,7 +659,7 @@ async def get_orders(page: int = 1, per_page: int = 50,
if sort_dir.lower() not in ("asc", "desc"):
sort_dir = "desc"
cursor = await db.execute(f"SELECT COUNT(*) FROM orders {where}", params)
cursor = await db.execute(f"SELECT COUNT(*) FROM orders {where}", data_params)
total = (await cursor.fetchone())[0]
offset = (page - 1) * per_page
@@ -659,17 +668,26 @@ async def get_orders(page: int = 1, per_page: int = 50,
{where}
ORDER BY {sort_by} {sort_dir}
LIMIT ? OFFSET ?
""", params + [per_page, offset])
""", data_params + [per_page, offset])
rows = await cursor.fetchall()
# Counts by status (on full period, not just this page)
# Counts by status — always on full period+search, never filtered by status
cursor = await db.execute(f"""
SELECT status, COUNT(*) as cnt FROM orders
{where}
{counts_where}
GROUP BY status
""", params)
""", base_params)
status_counts = {row["status"]: row["cnt"] for row in await cursor.fetchall()}
# Uninvoiced count: IMPORTED/ALREADY_IMPORTED with no cached invoice, same period+search
uninv_clauses = list(base_clauses) + [
"UPPER(status) IN ('IMPORTED', 'ALREADY_IMPORTED')",
"(factura_numar IS NULL OR factura_numar = '')",
]
uninv_where = "WHERE " + " AND ".join(uninv_clauses)
cursor = await db.execute(f"SELECT COUNT(*) FROM orders {uninv_where}", base_params)
uninvoiced_sqlite = (await cursor.fetchone())[0]
return {
"orders": [dict(r) for r in rows],
"total": total,
@@ -678,10 +696,12 @@ async def get_orders(page: int = 1, per_page: int = 50,
"pages": (total + per_page - 1) // per_page if total > 0 else 0,
"counts": {
"imported": status_counts.get("IMPORTED", 0),
"already_imported": status_counts.get("ALREADY_IMPORTED", 0),
"imported_all": status_counts.get("IMPORTED", 0) + status_counts.get("ALREADY_IMPORTED", 0),
"skipped": status_counts.get("SKIPPED", 0),
"error": status_counts.get("ERROR", 0),
"already_imported": status_counts.get("ALREADY_IMPORTED", 0),
"total": sum(status_counts.values())
"total": sum(status_counts.values()),
"uninvoiced_sqlite": uninvoiced_sqlite,
}
}
finally: