"""Order router — select highest-scoring supplier and record profit. select_supplier: eligible = active supplier, linked supplier_product, stock >= qty. route_order: assigns supplier, computes supplier_cost / shipping_cost / fees, records net profit = retail_total - supplier_cost - shipping_cost - fees. """ from decimal import ROUND_HALF_UP, Decimal from app.engines import scoring from app.models import AuditLog, Product, Supplier, SupplierProduct CENT = Decimal("0.01") FEE_RATE = Decimal("0.05") # payment processing estimate FEE_FLAT = Decimal("0.30") def _f(value) -> float: try: return float(value or 0) except (TypeError, ValueError): return 0.0 def select_supplier(db, product_id, qty): """Return (result_dict, error_str). result = {supplier, supplier_product, score}.""" product = db.query(Product).filter(Product.id == product_id).first() if product is None: return None, "product not found" rows = ( db.query(SupplierProduct, Supplier) .join(Supplier, SupplierProduct.supplier_id == Supplier.id) .filter( SupplierProduct.product_id == product_id, Supplier.status == "active", SupplierProduct.supplier_inventory >= qty, ) .all() ) if not rows: return None, "no eligible supplier" pool = {"avg_cost": sum(_f(sp.supplier_cost) for sp, _ in rows) / len(rows)} scored = [ (scoring.score_supplier(db, supplier, sp, qty, pool), sp, supplier) for sp, supplier in rows ] best_score, best_sp, best_supplier = max(scored, key=lambda t: t[0]) return { "supplier": best_supplier, "supplier_product": best_sp, "score": best_score, }, None def route_order(db, order): """Route a newly created order to the best supplier(s) and record profit.""" supplier_id = None supplier_cost = Decimal("0") shipping_cost = Decimal("0") routing_detail = [] for item in order.items or []: result, err = select_supplier(db, item["product_id"], int(item["qty"])) if err: routing_detail.append({"product_id": item["product_id"], "error": err}) continue sp = result["supplier_product"] if supplier_id is None: supplier_id = sp.supplier_id supplier_cost += Decimal(str(sp.supplier_cost or 0)) * int(item["qty"]) shipping_cost += Decimal(str(sp.shipping_cost or 0)) routing_detail.append( { "product_id": item["product_id"], "supplier": result["supplier"].name, "supplier_score": result["score"], } ) order.supplier_id = supplier_id order.supplier_cost = supplier_cost.quantize(CENT, rounding=ROUND_HALF_UP) order.shipping_cost = shipping_cost.quantize(CENT, rounding=ROUND_HALF_UP) order.fees = (Decimal(str(order.retail_total or 0)) * FEE_RATE + FEE_FLAT).quantize( CENT, rounding=ROUND_HALF_UP ) order.profit = ( Decimal(str(order.retail_total or 0)) - order.supplier_cost - order.shipping_cost - order.fees ).quantize(CENT, rounding=ROUND_HALF_UP) db.add( AuditLog( actor="order_router", action="order_routed", entity="order", entity_id=order.order_number, detail={ "supplier_id": str(supplier_id) if supplier_id else None, "profit": float(order.profit), "routing": routing_detail, }, ) ) if supplier_id is None: order.status = "new" # stays unfulfilled; no eligible supplier db.commit() return {"routed": False, "reason": "no eligible supplier for any item"} order.status = "pending_payment" db.commit() return { "routed": True, "supplier_id": str(supplier_id), "profit": float(order.profit), "supplier_cost": float(order.supplier_cost), "shipping_cost": float(order.shipping_cost), "fees": float(order.fees), }