"""Dashboard Stats Blueprint — In-app real-time analytics. Endpoints for sales, productivity, and top products charts. """ from flask import Blueprint, request, jsonify, g from functools import wraps from datetime import datetime, timedelta from decimal import Decimal import json dashboard_stats_bp = Blueprint('dashboard_stats', __name__, url_prefix='/pos/api/dashboard') from middleware import require_auth class DecimalEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, Decimal): return float(o) return super().default(o) @dashboard_stats_bp.route('/stats', methods=['GET']) @require_auth() def get_stats(): """Summary stats for today and this month.""" from tenant_db import get_tenant_db db = get_tenant_db() today = datetime.utcnow().date() month_start = today.replace(day=1) # Sales today today_sales = db.execute( """SELECT COUNT(*) as count, COALESCE(SUM(total), 0) as total FROM sales WHERE DATE(created_at) = %s""", (today,) ).fetchone() # Sales this month month_sales = db.execute( """SELECT COUNT(*) as count, COALESCE(SUM(total), 0) as total FROM sales WHERE DATE(created_at) >= %s""", (month_start,) ).fetchone() # Top 5 products today top_products = db.execute( """SELECT p.name, SUM(si.quantity) as qty, SUM(si.total) as revenue FROM sale_items si JOIN sales s ON si.sale_id = s.id_sale JOIN parts p ON si.part_id = p.id_part WHERE DATE(s.created_at) = %s GROUP BY p.name ORDER BY revenue DESC LIMIT 5""", (today,) ).fetchall() # Hourly sales today (0-23) hourly = db.execute( """SELECT EXTRACT(HOUR FROM created_at)::int as hour, COUNT(*) as count, COALESCE(SUM(total), 0) as total FROM sales WHERE DATE(created_at) = %s GROUP BY hour ORDER BY hour""", (today,) ).fetchall() hourly_map = {row['hour']: {'count': row['count'], 'total': row['total']} for row in hourly} return jsonify({ 'today': { 'sales_count': today_sales['count'], 'sales_total': today_sales['total'], }, 'month': { 'sales_count': month_sales['count'], 'sales_total': month_sales['total'], }, 'top_products': [ {'name': row['name'], 'quantity': row['qty'], 'revenue': row['revenue']} for row in top_products ], 'hourly_sales': [ {'hour': h, 'count': hourly_map.get(h, {}).get('count', 0), 'total': hourly_map.get(h, {}).get('total', 0)} for h in range(24) ], }, cls=DecimalEncoder) @dashboard_stats_bp.route('/stats/employees', methods=['GET']) @require_auth() def get_employee_stats(): """Sales per employee today.""" from tenant_db import get_tenant_db db = get_tenant_db() today = datetime.utcnow().date() rows = db.execute( """SELECT e.name, COUNT(s.id_sale) as sales, COALESCE(SUM(s.total), 0) as total FROM sales s JOIN employees e ON s.employee_id = e.id_employee WHERE DATE(s.created_at) = %s GROUP BY e.name ORDER BY total DESC""", (today,) ).fetchall() return jsonify({ 'employees': [ {'name': row['name'], 'sales': row['sales'], 'total': row['total']} for row in rows ] }, cls=DecimalEncoder)