"""CRUD + status transitions for internal_tickets (the no-PSA fallback ticket model).""" from datetime import datetime, timezone from typing import Optional from uuid import UUID from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.models.internal_ticket import InternalTicket async def create_ticket( db: AsyncSession, *, account_id: UUID, created_by_user_id: UUID, problem_statement: str, customer_name: Optional[str] = None, customer_contact: Optional[str] = None, ) -> InternalTicket: """Create a new internal ticket in 'open' status.""" ticket = InternalTicket( account_id=account_id, created_by_user_id=created_by_user_id, problem_statement=problem_statement, customer_name=customer_name, customer_contact=customer_contact, ) db.add(ticket) await db.flush() return ticket async def update_status( db: AsyncSession, *, ticket_id: UUID, status: str, resolution_notes: Optional[str] = None, assigned_user_id: Optional[UUID] = None, ) -> InternalTicket: """Transition a ticket to a new status. Sets resolved_at when status='resolved'.""" ticket = await db.get(InternalTicket, ticket_id) if not ticket: raise ValueError(f"InternalTicket {ticket_id} not found") ticket.status = status if status == 'resolved': ticket.resolved_at = datetime.now(timezone.utc) if resolution_notes is not None: ticket.resolution_notes = resolution_notes if assigned_user_id is not None: ticket.assigned_user_id = assigned_user_id await db.flush() return ticket async def get_ticket(db: AsyncSession, *, ticket_id: UUID) -> Optional[InternalTicket]: """Fetch a ticket by ID. Returns None if not found.""" return await db.get(InternalTicket, ticket_id) async def list_tickets_for_account( db: AsyncSession, *, account_id: UUID, status: Optional[str] = None, limit: int = 100, ) -> list[InternalTicket]: """List tickets for an account, optionally filtered by status, newest first.""" stmt = select(InternalTicket).where(InternalTicket.account_id == account_id) if status: stmt = stmt.where(InternalTicket.status == status) stmt = stmt.order_by(InternalTicket.created_at.desc()).limit(limit) result = await db.execute(stmt) return list(result.scalars()) async def promote_to_psa( db: AsyncSession, *, ticket_id: UUID, psa_ticket_id: str, ) -> InternalTicket: """Mark an internal ticket as promoted to PSA.""" ticket = await db.get(InternalTicket, ticket_id) if not ticket: raise ValueError(f"InternalTicket {ticket_id} not found") ticket.psa_promoted_ticket_id = psa_ticket_id await db.flush() return ticket