"""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 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) group_id = request.args.get('group_id', type=int) branch_id = request.args.get('branch_id', type=int) from tenant_db import get_tenant_db db = get_tenant_db() since = datetime.utcnow() - timedelta(days=days) params = [since] filters = "s.created_at >= %s" if group_id: filters += " AND p.group_id = %s" params.append(group_id) if branch_id: filters += " AND s.branch_id = %s" params.append(branch_id) rows = db.execute( f"""SELECT g.name as group_name, b.name as branch_name, COUNT(DISTINCT s.id_sale) as orders, SUM(si.quantity) as qty_requested, COALESCE(SUM(si.total), 0) 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 JOIN part_groups g ON p.group_id = g.id_group LEFT JOIN branches b ON s.branch_id = b.id_branch WHERE {filters} GROUP BY g.name, b.name ORDER BY revenue DESC LIMIT 100""", tuple(params) ).fetchall() return jsonify({ 'since': since.isoformat(), 'days': days, 'demand': [ {'group': row['group_name'], 'branch': row['branch_name'], 'orders': row['orders'], 'quantity': row['qty_requested'], 'revenue': row['revenue']} for row in rows ] }, cls=DecimalEncoder) @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) from tenant_db import get_tenant_db db = get_tenant_db() since = datetime.utcnow() - timedelta(days=days) rows = db.execute( """SELECT p.oem_part_number, p.name, g.name as group_name, SUM(si.quantity) as sold, COALESCE(SUM(si.total), 0) as revenue, COALESCE(SUM(wi.stock_quantity), 0) as current_stock FROM sale_items si JOIN sales s ON si.sale_id = s.id_sale JOIN parts p ON si.part_id = p.id_part JOIN part_groups g ON p.group_id = g.id_group LEFT JOIN warehouse_inventory wi ON p.id_part = wi.part_id WHERE s.created_at >= %s GROUP BY p.oem_part_number, p.name, g.name ORDER BY sold DESC LIMIT 50""", (since,) ).fetchall() return jsonify({ 'since': since.isoformat(), 'parts': [ {'oem': row['oem_part_number'], 'name': row['name'], 'group': row['group_name'], 'sold': row['sold'], 'revenue': row['revenue'], 'stock': row['current_stock']} for row in rows ] }, cls=DecimalEncoder)