from typing import List from fastapi import APIRouter, Depends, HTTPException, status, Request, Body from sqlalchemy.orm import Session from adapters.db.session import get_db from adapters.db.repositories.support.ticket_repository import TicketRepository from adapters.db.repositories.support.message_repository import MessageRepository from adapters.api.v1.schemas import QueryInfo, PaginatedResponse, SuccessResponse from adapters.api.v1.support.schemas import ( CreateMessageRequest, UpdateStatusRequest, AssignTicketRequest, TicketResponse, MessageResponse ) from app.core.auth_dependency import get_current_user, AuthContext from app.core.permissions import require_app_permission from app.core.responses import success_response, format_datetime_fields router = APIRouter() @router.post("/tickets/search", response_model=SuccessResponse) @require_app_permission("support_operator") async def search_operator_tickets( request: Request, query_info: QueryInfo = Body(...), current_user: AuthContext = Depends(get_current_user), db: Session = Depends(get_db) ): """جستجو در تمام تیکت‌ها برای اپراتور""" ticket_repo = TicketRepository(db) # تنظیم فیلدهای قابل جستجو if not query_info.search_fields: query_info.search_fields = ["title", "description", "user_email", "user_name"] tickets, total = ticket_repo.get_operator_tickets(query_info) # تبدیل به dict ticket_dicts = [] for ticket in tickets: ticket_dict = { "id": ticket.id, "title": ticket.title, "description": ticket.description, "user_id": ticket.user_id, "category_id": ticket.category_id, "priority_id": ticket.priority_id, "status_id": ticket.status_id, "assigned_operator_id": ticket.assigned_operator_id, "is_internal": ticket.is_internal, "closed_at": ticket.closed_at, "created_at": ticket.created_at, "updated_at": ticket.updated_at, "user": { "id": ticket.user.id, "first_name": ticket.user.first_name, "last_name": ticket.user.last_name, "email": ticket.user.email } if ticket.user else None, "assigned_operator": { "id": ticket.assigned_operator.id, "first_name": ticket.assigned_operator.first_name, "last_name": ticket.assigned_operator.last_name, "email": ticket.assigned_operator.email } if ticket.assigned_operator else None, "category": { "id": ticket.category.id, "name": ticket.category.name, "description": ticket.category.description, "is_active": ticket.category.is_active, "created_at": ticket.category.created_at, "updated_at": ticket.category.updated_at } if ticket.category else None, "priority": { "id": ticket.priority.id, "name": ticket.priority.name, "description": ticket.priority.description, "color": ticket.priority.color, "order": ticket.priority.order, "created_at": ticket.priority.created_at, "updated_at": ticket.priority.updated_at } if ticket.priority else None, "status": { "id": ticket.status.id, "name": ticket.status.name, "description": ticket.status.description, "color": ticket.status.color, "is_final": ticket.status.is_final, "created_at": ticket.status.created_at, "updated_at": ticket.status.updated_at } if ticket.status else None } ticket_dicts.append(ticket_dict) paginated_data = PaginatedResponse.create( items=ticket_dicts, total=total, page=(query_info.skip // query_info.take) + 1, limit=query_info.take ) # Format datetime fields based on calendar type formatted_data = format_datetime_fields(paginated_data.dict(), request) return success_response(formatted_data, request) @router.get("/tickets/{ticket_id}", response_model=SuccessResponse) @require_app_permission("support_operator") async def get_operator_ticket( request: Request, ticket_id: int, current_user: AuthContext = Depends(get_current_user), db: Session = Depends(get_db) ): """مشاهده تیکت برای اپراتور""" ticket_repo = TicketRepository(db) ticket = ticket_repo.get_operator_ticket_with_details(ticket_id) if not ticket: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="تیکت یافت نشد" ) # Format datetime fields based on calendar type ticket_data = TicketResponse.from_orm(ticket).dict() formatted_data = format_datetime_fields(ticket_data, request) return success_response(formatted_data, request) @router.put("/tickets/{ticket_id}/status", response_model=SuccessResponse) @require_app_permission("support_operator") async def update_ticket_status( request: Request, ticket_id: int, status_request: UpdateStatusRequest, current_user: AuthContext = Depends(get_current_user), db: Session = Depends(get_db) ): """تغییر وضعیت تیکت""" ticket_repo = TicketRepository(db) ticket = ticket_repo.update_ticket_status( ticket_id=ticket_id, status_id=status_request.status_id, operator_id=status_request.assigned_operator_id or current_user.get_user_id() ) if not ticket: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="تیکت یافت نشد" ) # دریافت تیکت با جزئیات ticket_with_details = ticket_repo.get_operator_ticket_with_details(ticket_id) # Format datetime fields based on calendar type ticket_data = TicketResponse.from_orm(ticket_with_details).dict() formatted_data = format_datetime_fields(ticket_data, request) return success_response(formatted_data, request) @router.post("/tickets/{ticket_id}/assign", response_model=SuccessResponse) @require_app_permission("support_operator") async def assign_ticket( request: Request, ticket_id: int, assign_request: AssignTicketRequest, current_user: AuthContext = Depends(get_current_user), db: Session = Depends(get_db) ): """تخصیص تیکت به اپراتور""" ticket_repo = TicketRepository(db) ticket = ticket_repo.assign_ticket(ticket_id, assign_request.operator_id) if not ticket: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="تیکت یافت نشد" ) # دریافت تیکت با جزئیات ticket_with_details = ticket_repo.get_operator_ticket_with_details(ticket_id) # Format datetime fields based on calendar type ticket_data = TicketResponse.from_orm(ticket_with_details).dict() formatted_data = format_datetime_fields(ticket_data, request) return success_response(formatted_data, request) @router.post("/tickets/{ticket_id}/messages", response_model=SuccessResponse) @require_app_permission("support_operator") async def send_operator_message( request: Request, ticket_id: int, message_request: CreateMessageRequest, current_user: AuthContext = Depends(get_current_user), db: Session = Depends(get_db) ): """ارسال پیام اپراتور به تیکت""" ticket_repo = TicketRepository(db) message_repo = MessageRepository(db) # بررسی وجود تیکت ticket = ticket_repo.get_operator_ticket_with_details(ticket_id) if not ticket: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="تیکت یافت نشد" ) # ایجاد پیام message = message_repo.create_message( ticket_id=ticket_id, sender_id=current_user.get_user_id(), sender_type="operator", content=message_request.content, is_internal=message_request.is_internal ) # اگر تیکت هنوز به اپراتور تخصیص نشده، آن را تخصیص ده if not ticket.assigned_operator_id: ticket_repo.assign_ticket(ticket_id, current_user.get_user_id()) # Format datetime fields based on calendar type message_data = MessageResponse.from_orm(message).dict() formatted_data = format_datetime_fields(message_data, request) return success_response(formatted_data, request) @router.post("/tickets/{ticket_id}/messages/search", response_model=SuccessResponse) @require_app_permission("support_operator") async def search_operator_ticket_messages( request: Request, ticket_id: int, query_info: QueryInfo = Body(...), current_user: AuthContext = Depends(get_current_user), db: Session = Depends(get_db) ): """جستجو در پیام‌های تیکت برای اپراتور""" ticket_repo = TicketRepository(db) message_repo = MessageRepository(db) # بررسی وجود تیکت ticket = ticket_repo.get_operator_ticket_with_details(ticket_id) if not ticket: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="تیکت یافت نشد" ) # تنظیم فیلدهای قابل جستجو if not query_info.search_fields: query_info.search_fields = ["content"] messages, total = message_repo.get_ticket_messages(ticket_id, query_info) # تبدیل به dict message_dicts = [] for message in messages: message_dict = { "id": message.id, "ticket_id": message.ticket_id, "sender_id": message.sender_id, "sender_type": message.sender_type, "content": message.content, "is_internal": message.is_internal, "created_at": message.created_at, "sender": { "id": message.sender.id, "first_name": message.sender.first_name, "last_name": message.sender.last_name, "email": message.sender.email } if message.sender else None } message_dicts.append(message_dict) paginated_data = PaginatedResponse.create( items=message_dicts, total=total, page=(query_info.skip // query_info.take) + 1, limit=query_info.take ) # Format datetime fields based on calendar type formatted_data = format_datetime_fields(paginated_data.dict(), request) return success_response(formatted_data, request)