======================== Endpoints de Tickets ======================== El módulo de ticketing expone una API REST bajo ``/tickets/api/`` para gestión completa de soporte técnico, incluyendo tickets, departamentos, mensajes, notas internas, asignación de agentes y acciones de flujo de trabajo. .. contents:: En esta página :local: :depth: 2 Tickets — ``/tickets/api/tickets/`` ==================================== Gestión principal de tickets de soporte. Los clientes solo ven sus propios tickets; los agentes (staff/superuser) ven todos. .. list-table:: Métodos :header-rows: 1 :widths: 15 50 35 * - Método - Endpoint - Descripción * - ``GET`` - ``/tickets/api/tickets/`` - Listar tickets (con filtros) * - ``POST`` - ``/tickets/api/tickets/`` - Crear nuevo ticket * - ``GET`` - ``/tickets/api/tickets/{id}/`` - Detalle de ticket con mensajes * - ``PUT`` - ``/tickets/api/tickets/{id}/`` - Actualizar ticket * - ``DELETE`` - ``/tickets/api/tickets/{id}/`` - Eliminar ticket Acciones de Ticket ------------------- .. list-table:: :header-rows: 1 :widths: 15 50 35 * - Método - Endpoint - Descripción * - ``POST`` - ``/tickets/api/tickets/{id}/reply/`` - Añadir respuesta al ticket * - ``POST`` - ``/tickets/api/tickets/{id}/note/`` - Añadir nota interna (solo agentes) * - ``POST`` - ``/tickets/api/tickets/{id}/assign/`` - Asignar ticket a un agente * - ``POST`` - ``/tickets/api/tickets/{id}/resolve/`` - Marcar como resuelto * - ``POST`` - ``/tickets/api/tickets/{id}/close/`` - Cerrar ticket * - ``POST`` - ``/tickets/api/tickets/{id}/reopen/`` - Reabrir ticket cerrado/resuelto Filtros disponibles -------------------- - ``?status=open`` — Filtrar por estado (new, open, pending, on_hold, resolved, closed) - ``?priority=high`` — Filtrar por prioridad (low, medium, high, urgent, critical) - ``?department=soporte`` — Filtrar por slug de departamento - ``?assigned_to=me`` — Tickets asignados al usuario actual - ``?assigned_to=unassigned`` — Tickets sin asignar **Ejemplo — Crear ticket:** .. code-block:: bash curl -X POST https://panel.example.com/tickets/api/tickets/ \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "subject": "No puedo acceder a mi sitio web", "priority": "high", "department": 1 }' **Respuesta (201 Created):** .. code-block:: json { "id": "e5f6a7b8-c9d0-1234-5678-9abcdef01234", "number": "TK-000042", "subject": "No puedo acceder a mi sitio web", "tenant": 1, "requester": 5, "requester_email": "cliente@example.com", "requester_name": "Juan Perez", "assigned_to": null, "department": 1, "status": "new", "priority": "high", "source": "api", "tags": [], "sla_policy": null, "sla_first_response_due": null, "sla_resolution_due": null, "first_responded_at": null, "resolved_at": null, "closed_at": null, "messages": [], "created_at": "2026-02-08T10:00:00Z", "updated_at": "2026-02-08T10:00:00Z" } **Ejemplo — Listar tickets abiertos:** .. code-block:: bash curl -X GET "https://panel.example.com/tickets/api/tickets/?status=open" \ -H "Authorization: Bearer $TOKEN" **Ejemplo — Responder a un ticket:** .. code-block:: bash curl -X POST https://panel.example.com/tickets/api/tickets/e5f6a7b8-c9d0-1234-5678-9abcdef01234/reply/ \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "body": "Hemos revisado el servidor y el problema era un error de DNS. Ya está corregido. Por favor, verifica si puedes acceder ahora." }' **Respuesta (201):** .. code-block:: json { "id": 15, "ticket": "e5f6a7b8-c9d0-1234-5678-9abcdef01234", "author": 1, "author_email": "agente@noxpanel.com", "author_name": "Admin NoxPanel", "message_type": "reply", "body": "Hemos revisado el servidor y el problema era un error de DNS. Ya está corregido. Por favor, verifica si puedes acceder ahora.", "body_html": "", "is_from_agent": true, "created_at": "2026-02-08T10:15:00Z" } **Ejemplo — Añadir nota interna:** .. code-block:: bash curl -X POST https://panel.example.com/tickets/api/tickets/e5f6a7b8-c9d0-1234-5678-9abcdef01234/note/ \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "body": "El DNS apuntaba a la IP antigua. Actualizado registro A a 203.0.113.10." }' **Ejemplo — Asignar ticket:** .. code-block:: bash # Asignar a uno mismo curl -X POST https://panel.example.com/tickets/api/tickets/{id}/assign/ \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" # Asignar a otro agente curl -X POST https://panel.example.com/tickets/api/tickets/{id}/assign/ \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"agent_id": 3}' **Ejemplo — Resolver y cerrar:** .. code-block:: bash # Resolver curl -X POST https://panel.example.com/tickets/api/tickets/{id}/resolve/ \ -H "Authorization: Bearer $TOKEN" # Cerrar curl -X POST https://panel.example.com/tickets/api/tickets/{id}/close/ \ -H "Authorization: Bearer $TOKEN" Departamentos — ``/tickets/api/departments/`` =============================================== Gestión de departamentos de soporte. Lectura para todos los autenticados, escritura solo para agentes (staff/superuser). .. list-table:: Métodos :header-rows: 1 :widths: 15 50 35 * - Método - Endpoint - Descripción * - ``GET`` - ``/tickets/api/departments/`` - Listar departamentos * - ``POST`` - ``/tickets/api/departments/`` - Crear departamento (agente) * - ``GET`` - ``/tickets/api/departments/{slug}/`` - Detalle por slug * - ``PUT`` - ``/tickets/api/departments/{slug}/`` - Actualizar departamento * - ``DELETE`` - ``/tickets/api/departments/{slug}/`` - Eliminar departamento **Respuesta:** .. code-block:: json { "id": 1, "name": "Soporte Técnico", "slug": "soporte-tecnico", "description": "Problemas técnicos con hosting, DNS, email y servidores", "email": "soporte@noxpanel.com", "manager": 1, "is_active": true } Estados de Ticket ================== Un ticket pasa por los siguientes estados durante su ciclo de vida: .. list-table:: :header-rows: 1 :widths: 20 80 * - Estado - Descripción * - ``new`` - Recién creado, sin primera respuesta * - ``open`` - Abierto y en proceso de atención * - ``pending`` - Pendiente de respuesta del cliente * - ``on_hold`` - En espera (dependencia externa) * - ``resolved`` - Resuelto, pendiente de confirmación * - ``closed`` - Cerrado definitivamente Prioridades ============ .. list-table:: :header-rows: 1 :widths: 20 30 50 * - Prioridad - Valor - Uso recomendado * - ``low`` - Baja - Consultas generales, mejoras * - ``medium`` - Media - Problemas que no afectan producción * - ``high`` - Alta - Problemas que afectan a la operativa * - ``urgent`` - Urgente - Servicio degradado en producción * - ``critical`` - Crítica - Servicio caído, pérdida de datos Orígenes del Ticket ==================== Los tickets pueden crearse desde diferentes fuentes: - ``web`` — Panel web de NoxPanel - ``email`` — Email recibido (IMAP/OAuth2) procesado automáticamente - ``api`` — Creado vía API REST - ``phone`` — Registrado manualmente desde llamada telefónica SLA (Service Level Agreement) ============================== El sistema de SLA permite definir tiempos máximos de respuesta y resolución según la prioridad. Las políticas SLA se asignan automáticamente al ticket según su prioridad. Las tareas de Celery verifican periódicamente si hay incumplimientos de SLA: - ``check-sla-breaches``: Cada 15 minutos - ``auto-close-resolved-tickets``: Diariamente (cierra tickets resueltos tras X días)