"""Pricing & Margin Control OS""" from flask import Blueprint, request, jsonify from app.core.database import db from app.core.audit import log from app.api.routes.auth import require_auth import uuid pricing_bp = Blueprint("pricing", __name__, url_prefix="/pricing") @pricing_bp.get("/quotes") @require_auth def list_quotes(user): with db() as conn: rows = conn.execute("SELECT * FROM quotes WHERE org_id=? ORDER BY created_at DESC", (user["org_id"],)).fetchall() return jsonify([dict(r) for r in rows]) @pricing_bp.post("/quotes") @require_auth def create_quote(user): data = request.get_json() or {} qid = f"q-{uuid.uuid4().hex[:8]}" subtotal = float(data.get("subtotal", 0)) discount_pct = float(data.get("discount_pct", 0)) final_price = subtotal * (1 - discount_pct / 100) margin_pct = float(data.get("margin_pct", 0)) # Determine if approval required with db() as conn: policy = conn.execute(""" SELECT * FROM discount_policies WHERE org_id=? AND max_discount_pct <= ? AND active=1 ORDER BY deal_value_min DESC LIMIT 1 """, (user["org_id"], discount_pct)).fetchone() approval_status = "auto_approved" if discount_pct == 0 else "pending" required_role = None if discount_pct > 0: with db() as conn: policies = conn.execute("SELECT * FROM discount_policies WHERE org_id=? AND active=1 ORDER BY deal_value_min ASC", (user["org_id"],)).fetchall() for p in policies: if discount_pct <= p["max_discount_pct"]: required_role = p["approver_role"] break if not required_role: required_role = "admin" if user["role"] in ["admin"] and discount_pct <= 35: approval_status = "approved" elif user["role"] == "manager" and discount_pct <= 20: approval_status = "approved" with db() as conn: conn.execute("""INSERT INTO quotes (id,org_id,deal_id,account_id,line_items,subtotal,discount_pct,discount_reason,final_price,margin_pct,approval_status,created_by) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)""", (qid, user["org_id"], data.get("deal_id"), data.get("account_id"), str(data.get("line_items", [])), subtotal, discount_pct, data.get("discount_reason",""), final_price, margin_pct, approval_status, user["id"])) log(user["org_id"], "pricing", "quote_created", user["id"], qid, data) # Cross-reference: also log against the deal so deal evidence trail shows ≥3 entries if data.get("deal_id"): log(user["org_id"], "pricing", "deal_quote_linked", user["id"], data["deal_id"], {"quote_id": qid, "final_price": final_price}) result = {"id": qid, "final_price": final_price, "approval_status": approval_status} if required_role and approval_status == "pending": result["requires_approval"] = True result["approver_role"] = required_role return jsonify(result), 201 @pricing_bp.patch("/quotes//approve") @require_auth def approve_quote(user, qid): if user["role"] not in ["admin", "manager"]: return jsonify({"error": "Forbidden"}), 403 with db() as conn: conn.execute("UPDATE quotes SET approval_status='approved', approved_by=?, approved_at=datetime('now') WHERE id=? AND org_id=?", (user["id"], qid, user["org_id"])) log(user["org_id"], "pricing", "quote_approved", user["id"], qid, {}) return jsonify({"approved": True}) @pricing_bp.patch("/quotes//reject") @require_auth def reject_quote(user, qid): if user["role"] not in ["admin", "manager"]: return jsonify({"error": "Forbidden"}), 403 with db() as conn: conn.execute("UPDATE quotes SET approval_status='rejected', approved_by=?, approved_at=datetime('now') WHERE id=? AND org_id=?", (user["id"], qid, user["org_id"])) log(user["org_id"], "pricing", "quote_rejected", user["id"], qid, {}) return jsonify({"rejected": True}) @pricing_bp.get("/policies") @require_auth def get_policies(user): with db() as conn: rows = conn.execute("SELECT * FROM discount_policies WHERE org_id=?", (user["org_id"],)).fetchall() return jsonify([dict(r) for r in rows]) @pricing_bp.post("/analyze") @require_auth def analyze_price(user): """Margin analysis and pricing recommendation""" data = request.get_json() or {} subtotal = float(data.get("subtotal", 0)) discount_pct = float(data.get("discount_pct", 0)) cost = float(data.get("cost", subtotal * 0.6)) final = subtotal * (1 - discount_pct / 100) margin = ((final - cost) / final * 100) if final > 0 else 0 recommendation = "healthy" if margin >= 30 else ("warning" if margin >= 15 else "critical") return jsonify({ "subtotal": subtotal, "discount_pct": discount_pct, "final_price": final, "margin_pct": round(margin, 2), "margin_status": recommendation, "margin_delta_from_1pct_price_increase": round(subtotal * 0.01 * 8.7 / 100, 2) })