from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from sqlalchemy.orm import selectinload import uuid from app.api import deps from app.core.database import get_db from app.models.ticket import Ticket, TicketParticipant from app.models.user import User from pydantic import BaseModel router = APIRouter() class ParticipantAdd(BaseModel): user_id: uuid.UUID class ParticipantResponse(BaseModel): id: uuid.UUID user_id: uuid.UUID ticket_id: uuid.UUID role: str user_email: str user_name: str class Config: from_attributes = True @router.get("/{ticket_id}/participants", response_model=list[ParticipantResponse]) async def list_participants( ticket_id: uuid.UUID, db: AsyncSession = Depends(get_db), current_user: User = Depends(deps.get_current_user) ): result = await db.execute( select(TicketParticipant) .where(TicketParticipant.ticket_id == ticket_id) .options(selectinload(TicketParticipant.user)) ) participants = result.scalars().all() return [ ParticipantResponse( id=p.id, user_id=p.user_id, ticket_id=p.ticket_id, role=p.role, user_email=p.user.email, user_name=f"{p.user.first_name or ''} {p.user.last_name or ''}".strip() ) for p in participants ] @router.post("/{ticket_id}/participants", response_model=ParticipantResponse) async def add_participant( ticket_id: uuid.UUID, data: ParticipantAdd, db: AsyncSession = Depends(get_db), current_user: User = Depends(deps.get_current_user) ): # Verificar que el ticket existe ticket_result = await db.execute(select(Ticket).where(Ticket.id == ticket_id)) ticket = ticket_result.scalar_one_or_none() if not ticket: raise HTTPException(status_code=404, detail="Ticket not found") # Solo el creador puede agregar participantes if ticket.created_by != current_user.id and not current_user.role.is_global: raise HTTPException(status_code=403, detail="Only the ticket creator can add participants") # Verificar que el usuario existe user_result = await db.execute(select(User).where(User.id == data.user_id)) user = user_result.scalar_one_or_none() if not user: raise HTTPException(status_code=404, detail="User not found") # Verificar que no sea duplicado existing = await db.execute( select(TicketParticipant).where( TicketParticipant.ticket_id == ticket_id, TicketParticipant.user_id == data.user_id ) ) if existing.scalar_one_or_none(): raise HTTPException(status_code=400, detail="User is already a participant") participant = TicketParticipant( ticket_id=ticket_id, user_id=data.user_id, role="participant" ) db.add(participant) await db.commit() await db.refresh(participant) return ParticipantResponse( id=participant.id, user_id=participant.user_id, ticket_id=participant.ticket_id, role=participant.role, user_email=user.email, user_name=f"{user.first_name or ''} {user.last_name or ''}".strip() ) @router.delete("/{ticket_id}/participants/{user_id}", status_code=204) async def remove_participant( ticket_id: uuid.UUID, user_id: uuid.UUID, db: AsyncSession = Depends(get_db), current_user: User = Depends(deps.get_current_user) ): ticket_result = await db.execute(select(Ticket).where(Ticket.id == ticket_id)) ticket = ticket_result.scalar_one_or_none() if not ticket: raise HTTPException(status_code=404, detail="Ticket not found") if ticket.created_by != current_user.id and not current_user.role.is_global: raise HTTPException(status_code=403, detail="Only the ticket creator can remove participants") result = await db.execute( select(TicketParticipant).where( TicketParticipant.ticket_id == ticket_id, TicketParticipant.user_id == user_id ) ) participant = result.scalar_one_or_none() if not participant: raise HTTPException(status_code=404, detail="Participant not found") await db.delete(participant) await db.commit()