from __future__ import annotations from typing import Optional from decimal import Decimal from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from models.calendars import CalendarEntry async def update_ticket_config( session: AsyncSession, entry_id: int, ticket_price: Optional[Decimal], ticket_count: Optional[int], ) -> tuple[bool, Optional[str]]: """ Update ticket configuration for a calendar entry. Args: session: Database session entry_id: Calendar entry ID ticket_price: Price per ticket (None = no tickets) ticket_count: Total available tickets (None = unlimited) Returns: (success, error_message) """ # Get the entry entry = await session.scalar( select(CalendarEntry).where( CalendarEntry.id == entry_id, CalendarEntry.deleted_at.is_(None) ) ) if not entry: return False, "Calendar entry not found" # Validate inputs if ticket_price is not None and ticket_price < 0: return False, "Ticket price cannot be negative" if ticket_count is not None and ticket_count < 0: return False, "Ticket count cannot be negative" # Update ticket configuration entry.ticket_price = ticket_price entry.ticket_count = ticket_count return True, None async def get_available_tickets( session: AsyncSession, entry_id: int, ) -> tuple[Optional[int], Optional[str]]: """ Get the number of available tickets for a calendar entry. Returns: (available_count, error_message) - available_count is None if unlimited tickets - available_count is the remaining count if limited """ entry = await session.scalar( select(CalendarEntry).where( CalendarEntry.id == entry_id, CalendarEntry.deleted_at.is_(None) ) ) if not entry: return None, "Calendar entry not found" # If no ticket configuration, return None (unlimited) if entry.ticket_price is None: return None, None # If ticket_count is None, unlimited tickets if entry.ticket_count is None: return None, None # Returns total count (booked tickets not yet subtracted) return entry.ticket_count, None