From 24cdd71262c522a440652dbef8031ccf0939d990 Mon Sep 17 00:00:00 2001 From: consultoria-as Date: Mon, 18 May 2026 04:31:00 +0000 Subject: [PATCH] feat(inventory): dynamic tab badges with real tenant data - Add /pos/api/inventory/stats endpoint returning counts per tab - Replace hardcoded badge numbers (4,817, 14, 3, 23) with dynamic values - Frontend auto-fetches stats on page load and updates badges --- pos/blueprints/inventory_bp.py | 46 ++++++++++++++++++++++++++++++++++ pos/templates/inventory.html | 43 +++++++++++++++++++++++++------ 2 files changed, 82 insertions(+), 7 deletions(-) diff --git a/pos/blueprints/inventory_bp.py b/pos/blueprints/inventory_bp.py index ea17aec..f9e1fff 100644 --- a/pos/blueprints/inventory_bp.py +++ b/pos/blueprints/inventory_bp.py @@ -809,6 +809,52 @@ def physical_count_approve(): }) +# ─── Stats Summary ───────────────────────────── + +@inventory_bp.route('/stats', methods=['GET']) +@require_auth('inventory.view') +def api_inventory_stats(): + """Get inventory summary counts for dashboard badges.""" + conn = get_tenant_conn(g.tenant_id) + cur = conn.cursor() + branch_id = getattr(g, 'branch_id', None) + + # Stock count + cur.execute("SELECT COUNT(*) FROM inventory WHERE is_active = true AND (branch_id = %s OR %s IS NULL)", (branch_id, branch_id)) + stock = cur.fetchone()[0] + + # Operations counts by type + cur.execute(""" + SELECT operation_type, COUNT(*) + FROM inventory_operations + WHERE (branch_id = %s OR %s IS NULL) + GROUP BY operation_type + """, (branch_id, branch_id)) + op_counts = {row[0]: row[1] for row in cur.fetchall()} + + # Physical counts + cur.execute("SELECT COUNT(*) FROM physical_counts WHERE (branch_id = %s OR %s IS NULL)", (branch_id, branch_id)) + physical = cur.fetchone()[0] + + cur.close() + conn.close() + + # Alerts (reuse existing function) + conn2 = get_tenant_conn(g.tenant_id) + alerts_list = get_alerts(conn2, branch_id) + conn2.close() + + return jsonify({ + 'stock': stock, + 'entradas': op_counts.get('PURCHASE', 0), + 'salidas': op_counts.get('SALE', 0), + 'traspasos': op_counts.get('TRANSFER', 0), + 'ajustes': op_counts.get('ADJUST', 0), + 'conteos': physical, + 'alertas': len(alerts_list) + }) + + # ─── Alerts and History ──────────────────────── @inventory_bp.route('/alerts', methods=['GET']) diff --git a/pos/templates/inventory.html b/pos/templates/inventory.html index 9b06d3e..8678147 100644 --- a/pos/templates/inventory.html +++ b/pos/templates/inventory.html @@ -238,25 +238,25 @@
@@ -821,5 +821,34 @@ +