from typing import Literal, Optional, Dict, Any from datetime import datetime from pydantic import BaseModel class CheckoutSessionCreate(BaseModel): plan: Literal["pro", "starter", "enterprise"] seats: int billing_interval: Literal["monthly", "annual"] = "monthly" class CheckoutSessionResponse(BaseModel): url: str class BillingPortalSessionResponse(BaseModel): url: str class SubscriptionState(BaseModel): status: str plan: str current_period_start: Optional[datetime] current_period_end: Optional[datetime] cancel_at_period_end: bool seat_limit: Optional[int] has_pro_entitlement: bool is_paid: bool class PlanBillingState(BaseModel): display_name: str description: Optional[str] = None monthly_price_cents: Optional[int] = None annual_price_cents: Optional[int] = None model_config = {"from_attributes": True} class BillingStateResponse(BaseModel): subscription: SubscriptionState plan_billing: Optional[PlanBillingState] plan_limits: Dict[str, Any] enabled_features: Dict[str, bool] class PublicPlanResponse(BaseModel): """Public-safe view of a billable plan, used by the marketing /pricing page. Sourced from `plan_billing` joined with `plan_limits.max_users` (exposed here as `max_seats`). Always filtered server-side to is_public=True and is_archived=False, so `is_public` is a constant True for any row returned here — included for clarity and forward compatibility. """ plan: str display_name: str description: Optional[str] = None monthly_price_cents: Optional[int] = None annual_price_cents: Optional[int] = None max_seats: Optional[int] = None sort_order: int is_public: bool = True model_config = {"from_attributes": True}