from __future__ import annotations from fastapi import HTTPException, status from app.core.config import settings from app.repositories.scheme_seats import list_scheme_version_seats from app.repositories.scheme_version_pricing import ( find_effective_snapshot_price_rule, list_scheme_version_snapshot_categories, list_scheme_version_snapshot_rules, ) from app.services.scheme_validation import build_scheme_validation_report async def build_publish_readiness( *, scheme_id: str, scheme_version_id: str, ) -> dict: validation = await build_scheme_validation_report( scheme_id=scheme_id, scheme_version_id=scheme_version_id, ) seats = await list_scheme_version_seats(scheme_version_id) snapshot_categories = await list_scheme_version_snapshot_categories(scheme_version_id) snapshot_rules = await list_scheme_version_snapshot_rules(scheme_version_id) priced_seats = 0 unpriced_seats = 0 snapshot_available = bool(snapshot_categories or snapshot_rules) for seat in seats: if not seat.seat_id: unpriced_seats += 1 continue if not snapshot_available: unpriced_seats += 1 continue try: await find_effective_snapshot_price_rule( scheme_version_id=scheme_version_id, seat_id=seat.seat_id, group_id=seat.group_id, sector_id=seat.sector_id, ) priced_seats += 1 except HTTPException as exc: if exc.status_code != status.HTTP_404_NOT_FOUND: raise unpriced_seats += 1 except Exception: unpriced_seats += 1 total_seats = len(seats) coverage_percent = round((priced_seats / total_seats) * 100, 2) if total_seats else 100.0 full_pricing_coverage = unpriced_seats == 0 pricing_gate_passed = snapshot_available and ( full_pricing_coverage if settings.publish_require_full_pricing_coverage else True ) validation_publishable = bool(validation["summary"]["is_publishable"]) return { "scheme_id": scheme_id, "scheme_version_id": scheme_version_id, "status": "draft", "validation_summary": validation["summary"], "pricing_coverage": { "total_seats": total_seats, "priced_seats": priced_seats, "unpriced_seats": unpriced_seats, "coverage_percent": coverage_percent, }, "snapshot": { "available": snapshot_available, "categories_count": len(snapshot_categories), "rules_count": len(snapshot_rules), }, "readiness": { "validation_publishable": validation_publishable, "snapshot_available": snapshot_available, "require_full_pricing_coverage": settings.publish_require_full_pricing_coverage, "full_pricing_coverage": full_pricing_coverage, "pricing_gate_passed": pricing_gate_passed, "is_ready_to_publish": validation_publishable and pricing_gate_passed, }, }