"""Warranty / RMA blueprint. Endpoints (all under /pos/api): GET/POST /warranties GET /warranties/ GET /customers//warranties POST /warranty-claims GET /warranty-claims GET /warranty-claims/ PUT /warranty-claims//resolve PUT /warranty-claims//close """ from flask import Blueprint, request, jsonify, g from middleware import require_auth from tenant_db import get_tenant_conn from services.warranty_engine import ( register_warranty, create_claim, resolve_claim, close_claim, get_warranty, list_warranties, get_claim, list_claims, expire_warranties, ) warranty_bp = Blueprint('warranty', __name__, url_prefix='/pos/api') # ── WARRANTIES ───────────────────────────────────────────────────────────── @warranty_bp.route('/warranties', methods=['GET']) @require_auth('inventory.view') def get_warranties(): """List warranties.""" conn = get_tenant_conn(g.tenant_id) status = request.args.get('status') customer_id = request.args.get('customer_id', type=int) limit = request.args.get('limit', 50, type=int) offset = request.args.get('offset', 0, type=int) data = list_warranties(conn, customer_id=customer_id, status=status, limit=limit, offset=offset) conn.close() return jsonify({'data': data}) @warranty_bp.route('/warranties', methods=['POST']) @require_auth('pos.sell') def post_warranty(): """Register a warranty (usually called at sale time).""" data = request.get_json() or {} required = ['sale_id', 'sale_item_id', 'inventory_id', 'customer_id', 'warranty_months'] missing = [f for f in required if f not in data] if missing: return jsonify({'error': f'Missing fields: {missing}'}), 400 conn = get_tenant_conn(g.tenant_id) try: w_id = register_warranty( conn, sale_id=data['sale_id'], sale_item_id=data['sale_item_id'], inventory_id=data['inventory_id'], customer_id=data['customer_id'], warranty_months=int(data['warranty_months']), supplier_id=data.get('supplier_id'), part_number=data.get('part_number'), name=data.get('name'), notes=data.get('notes'), ) conn.commit() conn.close() return jsonify({'id': w_id, 'message': 'Warranty registered'}), 201 except ValueError as e: conn.rollback() conn.close() return jsonify({'error': str(e)}), 400 except Exception as e: conn.rollback() conn.close() return jsonify({'error': str(e)}), 500 @warranty_bp.route('/warranties/', methods=['GET']) @require_auth('inventory.view') def get_warranty_detail(warranty_id): """Get warranty by ID.""" conn = get_tenant_conn(g.tenant_id) w = get_warranty(conn, warranty_id) conn.close() if not w: return jsonify({'error': 'Warranty not found'}), 404 return jsonify(w) @warranty_bp.route('/customers//warranties', methods=['GET']) @require_auth('inventory.view') def get_customer_warranties(customer_id): """List warranties for a customer.""" conn = get_tenant_conn(g.tenant_id) data = list_warranties(conn, customer_id=customer_id) conn.close() return jsonify({'data': data}) # ── WARRANTY CLAIMS ──────────────────────────────────────────────────────── @warranty_bp.route('/warranty-claims', methods=['POST']) @require_auth('inventory.edit') def post_claim(): """File a warranty claim.""" data = request.get_json() or {} if not data.get('warranty_id') or not data.get('reason'): return jsonify({'error': 'warranty_id and reason are required'}), 400 conn = get_tenant_conn(g.tenant_id) try: claim_id = create_claim( conn, warranty_id=data['warranty_id'], reason=data['reason'], employee_id=g.employee_id, notes=data.get('notes') ) conn.commit() conn.close() return jsonify({'id': claim_id, 'message': 'Claim filed'}), 201 except ValueError as e: conn.rollback() conn.close() return jsonify({'error': str(e)}), 400 except Exception as e: conn.rollback() conn.close() return jsonify({'error': str(e)}), 500 @warranty_bp.route('/warranty-claims', methods=['GET']) @require_auth('inventory.view') def get_claims(): """List warranty claims.""" conn = get_tenant_conn(g.tenant_id) status = request.args.get('status') warranty_id = request.args.get('warranty_id', type=int) limit = request.args.get('limit', 50, type=int) offset = request.args.get('offset', 0, type=int) data = list_claims(conn, status=status, warranty_id=warranty_id, limit=limit, offset=offset) conn.close() return jsonify({'data': data}) @warranty_bp.route('/warranty-claims/', methods=['GET']) @require_auth('inventory.view') def get_claim_detail(claim_id): """Get claim by ID.""" conn = get_tenant_conn(g.tenant_id) c = get_claim(conn, claim_id) conn.close() if not c: return jsonify({'error': 'Claim not found'}), 404 return jsonify(c) @warranty_bp.route('/warranty-claims//resolve', methods=['PUT']) @require_auth('inventory.edit') def put_resolve_claim(claim_id): """Resolve a claim.""" data = request.get_json() or {} resolution = data.get('resolution') if not resolution: return jsonify({'error': 'resolution is required'}), 400 conn = get_tenant_conn(g.tenant_id) try: ok = resolve_claim( conn, claim_id, resolution, diagnosis=data.get('diagnosis'), replacement_inventory_id=data.get('replacement_inventory_id'), refund_amount=data.get('refund_amount'), labor_cost=data.get('labor_cost'), supplier_rma_number=data.get('supplier_rma_number'), notes=data.get('notes') ) conn.commit() conn.close() if not ok: return jsonify({'error': 'Claim not found or already closed'}), 400 return jsonify({'message': 'Claim resolved'}) except ValueError as e: conn.rollback() conn.close() return jsonify({'error': str(e)}), 400 except Exception as e: conn.rollback() conn.close() return jsonify({'error': str(e)}), 500 @warranty_bp.route('/warranty-claims//close', methods=['PUT']) @require_auth('inventory.edit') def put_close_claim(claim_id): """Close a resolved claim.""" conn = get_tenant_conn(g.tenant_id) try: ok = close_claim(conn, claim_id) conn.commit() conn.close() if not ok: return jsonify({'error': 'Claim not found or not resolved'}), 400 return jsonify({'message': 'Claim closed'}) except Exception as e: conn.rollback() conn.close() return jsonify({'error': str(e)}), 500