"""Supplier Portal Blueprint — Demand insights for vendors. Allows suppliers to view demand by zone, part type, and branch. """ from flask import Blueprint, request, jsonify, g from functools import wraps from datetime import datetime, timedelta from decimal import Decimal import json supplier_portal_bp = Blueprint('supplier_portal', __name__, url_prefix='/pos/api/supplier-portal') from middleware import require_auth from tenant_db import get_tenant_conn class DecimalEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, Decimal): return float(o) return super().default(o) @supplier_portal_bp.route('/demand', methods=['GET']) @require_auth() def get_demand(): """Aggregated demand by zone, part group, and time range.""" days = request.args.get('days', 30, type=int) branch_id = request.args.get('branch_id', type=int) conn = get_tenant_conn(g.tenant_id) cur = conn.cursor() since = datetime.utcnow() - timedelta(days=days) try: params = [since] filters = "s.created_at >= %s" if branch_id: filters += " AND s.branch_id = %s" params.append(branch_id) cur.execute( f"""SELECT b.name as branch_name, COUNT(DISTINCT s.id) as orders, SUM(si.quantity) as qty_requested, COALESCE(SUM(si.subtotal), 0) as revenue FROM sale_items si JOIN sales s ON si.sale_id = s.id LEFT JOIN branches b ON s.branch_id = b.id WHERE {filters} GROUP BY b.name ORDER BY revenue DESC LIMIT 100""", tuple(params) ) rows = cur.fetchall() return jsonify({ 'since': since.isoformat(), 'days': days, 'demand': [ {'branch': row[0] or 'Sin sucursal', 'orders': row[1], 'quantity': row[2], 'revenue': float(row[3]) if row[3] is not None else 0} for row in rows ] }) finally: cur.close() conn.close() @supplier_portal_bp.route('/top-parts', methods=['GET']) @require_auth() def get_top_parts(): """Top moving parts for suppliers to restock.""" days = request.args.get('days', 30, type=int) conn = get_tenant_conn(g.tenant_id) cur = conn.cursor() since = datetime.utcnow() - timedelta(days=days) try: cur.execute( """SELECT si.part_number, si.name, SUM(si.quantity) as sold, COALESCE(SUM(si.subtotal), 0) as revenue FROM sale_items si JOIN sales s ON si.sale_id = s.id WHERE s.created_at >= %s GROUP BY si.part_number, si.name ORDER BY sold DESC LIMIT 50""", (since,) ) rows = cur.fetchall() return jsonify({ 'since': since.isoformat(), 'parts': [ {'part_number': row[0], 'name': row[1], 'sold': row[2], 'revenue': float(row[3]) if row[3] is not None else 0} for row in rows ] }) finally: cur.close() conn.close()