from fastapi import APIRouter, Depends from app.core.config import settings from app.repositories.pricing import find_effective_price_rule from app.repositories.scheme_seats import get_scheme_version_seat_by_seat_id, list_scheme_version_seats from app.repositories.scheme_versions import get_current_scheme_version from app.repositories.schemes import get_scheme_record_by_scheme_id from app.schemas.pricing_diagnostics import PricingRuleDiagnosticsResponse from app.security.auth import require_api_key from app.services.pricing_rule_diagnostics import build_pricing_rule_diagnostics router = APIRouter() @router.get( f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/pricing/rules/diagnostics", response_model=PricingRuleDiagnosticsResponse, ) async def get_pricing_rule_diagnostics( scheme_id: str, role: str = Depends(require_api_key), ): scheme = await get_scheme_record_by_scheme_id(scheme_id) version = await get_current_scheme_version( scheme_id=scheme.scheme_id, current_version_number=scheme.current_version_number, ) payload = await build_pricing_rule_diagnostics( scheme_id=scheme.scheme_id, scheme_version_id=version.scheme_version_id, ) return PricingRuleDiagnosticsResponse(**payload) @router.get(f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/pricing/coverage") async def get_pricing_coverage( scheme_id: str, role: str = Depends(require_api_key), ): scheme = await get_scheme_record_by_scheme_id(scheme_id) version = await get_current_scheme_version( scheme_id=scheme.scheme_id, current_version_number=scheme.current_version_number, ) seats = await list_scheme_version_seats(version.scheme_version_id) priced = 0 unpriced = 0 for seat in seats: if not seat.seat_id: unpriced += 1 continue try: await find_effective_price_rule( scheme_id=scheme.scheme_id, seat_id=seat.seat_id, group_id=seat.group_id, sector_id=seat.sector_id, ) priced += 1 except Exception: unpriced += 1 total = len(seats) coverage_percent = round((priced / total) * 100, 2) if total else 100.0 return { "scheme_id": scheme.scheme_id, "scheme_version_id": version.scheme_version_id, "total_seats": total, "priced_seats": priced, "unpriced_seats": unpriced, "coverage_percent": coverage_percent, } @router.get(f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/pricing/unpriced-seats") async def get_unpriced_seats( scheme_id: str, role: str = Depends(require_api_key), ): scheme = await get_scheme_record_by_scheme_id(scheme_id) version = await get_current_scheme_version( scheme_id=scheme.scheme_id, current_version_number=scheme.current_version_number, ) seats = await list_scheme_version_seats(version.scheme_version_id) items: list[dict] = [] for seat in seats: if not seat.seat_id: items.append( { "seat_record_id": seat.seat_record_id, "seat_id": seat.seat_id, "element_id": seat.element_id, "sector_id": seat.sector_id, "group_id": seat.group_id, "row_label": seat.row_label, "seat_number": seat.seat_number, "reason_code": "missing_seat_id", "reason_message": "Seat has no seat_id and cannot be priced.", } ) continue try: await find_effective_price_rule( scheme_id=scheme.scheme_id, seat_id=seat.seat_id, group_id=seat.group_id, sector_id=seat.sector_id, ) except Exception: items.append( { "seat_record_id": seat.seat_record_id, "seat_id": seat.seat_id, "element_id": seat.element_id, "sector_id": seat.sector_id, "group_id": seat.group_id, "row_label": seat.row_label, "seat_number": seat.seat_number, "reason_code": "no_price_rule", "reason_message": "No effective price rule was found for this seat.", } ) return { "scheme_id": scheme.scheme_id, "scheme_version_id": version.scheme_version_id, "total": len(items), "items": items, } @router.get(f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/pricing/explain/{{seat_id}}") async def explain_seat_pricing( scheme_id: str, seat_id: str, role: str = Depends(require_api_key), ): scheme = await get_scheme_record_by_scheme_id(scheme_id) version = await get_current_scheme_version( scheme_id=scheme.scheme_id, current_version_number=scheme.current_version_number, ) seat = await get_scheme_version_seat_by_seat_id( scheme_version_id=version.scheme_version_id, seat_id=seat_id, ) try: matched_rule_level, rule = await find_effective_price_rule( scheme_id=scheme.scheme_id, seat_id=seat.seat_id, group_id=seat.group_id, sector_id=seat.sector_id, ) return { "scheme_id": scheme.scheme_id, "scheme_version_id": version.scheme_version_id, "seat_id": seat.seat_id, "element_id": seat.element_id, "sector_id": seat.sector_id, "group_id": seat.group_id, "row_label": seat.row_label, "seat_number": seat.seat_number, "has_price": True, "reason_code": "ok", "reason_message": "Effective price rule resolved successfully.", "matched_rule": { "matched_rule_level": matched_rule_level, "matched_target_ref": rule["target_ref"], "pricing_category_id": rule["pricing_category_id"], "amount": str(rule["amount"]), "currency": rule["currency"], }, } except Exception: return { "scheme_id": scheme.scheme_id, "scheme_version_id": version.scheme_version_id, "seat_id": seat.seat_id, "element_id": seat.element_id, "sector_id": seat.sector_id, "group_id": seat.group_id, "row_label": seat.row_label, "seat_number": seat.seat_number, "has_price": False, "reason_code": "no_price_rule", "reason_message": "No effective price rule was found for this seat.", "matched_rule": None, }