@hed-hog/ticket
v0.0.294
Published
O módulo Ticket centraliza as interações de suporte omnichannel para a plataforma Hcode. Ele oferece modelagem completa do banco de dados, interfaces administrativas estáticas e governança de acessos, canais e configurações. Atualmente, o backend possui a
Readme
Módulo Ticket (@hed-hog/ticket)
1. Visão Geral do Módulo
O módulo Ticket centraliza as interações de suporte omnichannel para a plataforma Hcode. Ele oferece modelagem completa do banco de dados, interfaces administrativas estáticas e governança de acessos, canais e configurações. Atualmente, o backend possui apenas scaffolding e mocks, sem integrações reais ou lógica de negócio implementada.
2. Escopo e Responsabilidades
- Gerenciamento de tickets de atendimento (criação, atualização, respostas, notas internas).
- Administração de canais e contas de canais de comunicação.
- Configuração de parâmetros globais e específicos para canais.
- Controle de acesso baseado em papéis (roles).
- Visualização de dashboards, filas de revisão AI, relatórios e matrizes de permissão.
- Suporte a metadados, tags, categorias e contexto dos tickets.
3. Endpoints
Ticket Data Controller
| Método | Path | Autenticação | Descrição | Parâmetros / Body | Resposta | Erros Comuns |
|--------|----------------|--------------|----------------------------------|-------------------|---------------------------|-----------------------|
| GET | /ticket/dashboard | Sim (admin, admin-ticket, analyst-ticket) | Retorna dados do dashboard | - | { items: [] } | 401 Unauthorized |
| GET | /ticket/inbox | Sim (admin, admin-ticket, operator-ticket, analyst-ticket) | Retorna a caixa de entrada | - | { items: [] } | 401 Unauthorized |
| GET | /ticket/ai-review | Sim (admin, admin-ticket, operator-ticket) | Retorna fila de revisão AI | - | { items: [] } | 401 Unauthorized |
| GET | /ticket/reports | Sim (admin, admin-ticket, analyst-ticket) | Retorna relatórios | - | { items: [] } | 401 Unauthorized |
| GET | /ticket/roles | Sim (admin, admin-ticket) | Retorna matriz de papéis | - | { items: [] } | 401 Unauthorized |
| GET | /ticket | Sim (admin, admin-ticket, operator-ticket, analyst-ticket) | Lista tickets | - | { items: [] } | 401 Unauthorized |
Ticket Items Controller
| Método | Path | Autenticação | Descrição | Parâmetros / Body | Resposta | Erros Comuns |
|--------|--------------------|--------------|----------------------------------|------------------------------------------------|---------------------------------|-----------------------|
| GET | /ticket/:id | Sim (admin, admin-ticket, operator-ticket, analyst-ticket) | Obtém ticket por ID | id (path) | { id: number } | 401 Unauthorized, 404 Not Found |
| POST | /ticket/:id/reply | Sim (admin, admin-ticket, operator-ticket) | Cria resposta pública para ticket | { subject?: string, body?: string } | { id, subject?, body? } | 401 Unauthorized, 400 Bad Request |
| POST | /ticket/:id/internal-note | Sim (admin, admin-ticket, operator-ticket) | Cria nota interna para ticket | { body?: string } | { id, body? } | 401 Unauthorized, 400 Bad Request |
| PATCH | /ticket/:id/assign | Sim (admin, admin-ticket, operator-ticket) | Atribui proprietário ao ticket | { owner_person_id?: number } | { id, owner_person_id? } | 401 Unauthorized, 400 Bad Request |
| PATCH | /ticket/:id/status | Sim (admin, admin-ticket, operator-ticket) | Atualiza status do ticket | { status?: string } | { id, status? } | 401 Unauthorized, 400 Bad Request |
| PATCH | /ticket/:id/priority| Sim (admin, admin-ticket, operator-ticket) | Atualiza prioridade do ticket | { priority?: string } | { id, priority? } | 401 Unauthorized, 400 Bad Request |
Ticket Channels Controller
| Método | Path | Autenticação | Descrição | Parâmetros / Body | Resposta | Erros Comuns |
|--------|--------------------|--------------|----------------------------------|------------------------------------------------|---------------------------------|-----------------------|
| GET | /ticket/channels | Sim (admin, admin-ticket) | Lista canais | - | { items: [] } | 401 Unauthorized |
| POST | /ticket/channels | Sim (admin, admin-ticket) | Cria novo canal | { code?: string, name?: string, kind?: string, status?: string } | Dados do canal criado | 401 Unauthorized, 400 Bad Request |
| PATCH | /ticket/channels/:id| Sim (admin, admin-ticket) | Atualiza canal existente | id (path), { name?: string, status?: string } | Dados atualizados | 401 Unauthorized, 400 Bad Request, 404 Not Found |
| DELETE | /ticket/channels/:id| Sim (admin, admin-ticket) | Remove canal | id (path) | { id, deleted: true } | 401 Unauthorized, 404 Not Found |
Ticket Channel Accounts Controller
| Método | Path | Autenticação | Descrição | Parâmetros / Body | Resposta | Erros Comuns |
|--------|---------------------------|--------------|----------------------------------|----------------------------------------------------------------------------------|---------------------------------|-----------------------|
| GET | /ticket/channel-accounts | Sim (admin, admin-ticket) | Lista contas de canais | - | { items: [] } | 401 Unauthorized |
| POST | /ticket/channel-accounts | Sim (admin, admin-ticket) | Cria conta de canal | { channel_id?: number, code?: string, name?: string, external_identifier?: string, status?: string, ai_enabled?: boolean, ai_model?: string } | Dados da conta criada | 401 Unauthorized, 400 Bad Request |
| PATCH | /ticket/channel-accounts/:id | Sim (admin, admin-ticket) | Atualiza conta de canal | id (path), { name?: string, external_identifier?: string, status?: string, ai_enabled?: boolean, ai_model?: string } | Dados atualizados | 401 Unauthorized, 400 Bad Request, 404 Not Found |
| DELETE | /ticket/channel-accounts/:id | Sim (admin, admin-ticket) | Remove conta de canal | id (path) | { id, deleted: true } | 401 Unauthorized, 404 Not Found |
Ticket Settings Controller
| Método | Path | Autenticação | Descrição | Parâmetros / Body | Resposta | Erros Comuns |
|--------|------------------|--------------|----------------------------------|----------------------------------------------------------------------------------|---------------------------------|-----------------------|
| GET | /ticket/settings | Sim (admin, admin-ticket) | Obtém configurações gerais | - | { items: [] } | 401 Unauthorized |
| PATCH | /ticket/settings | Sim (admin, admin-ticket) | Atualiza configurações gerais | { enabled?: boolean, code_prefix?: string, default_ai_review_mode?: string, default_visibility?: string, auto_assign_enabled?: boolean, default_owner_person_id?: number, allow_public_reply?: boolean, allow_internal_notes?: boolean, default_reopen_on_customer_reply?: boolean, default_close_after_days_without_reply?: number } | Dados atualizados | 401 Unauthorized, 400 Bad Request |
Ticket AI Review Controller
| Método | Path | Autenticação | Descrição | Parâmetros / Body | Resposta | Erros Comuns |
|--------|----------------|--------------|----------------------------------|-------------------|---------------------------|-----------------------|
| GET | /ticket/ai-review | Sim (admin, admin-ticket, operator-ticket) | Retorna fila de revisão AI | - | { items: [] } | 401 Unauthorized |
4. Regras de Autenticação e Autorização
- Todos os endpoints requerem autenticação.
- Papéis (roles) definidos para controle de acesso:
- admin-ticket: Administração completa, acesso a canais, configurações e governança.
- operator-ticket: Operação em tickets, respostas, notas internas, status e atribuições.
- analyst-ticket: Acesso somente leitura para visualização e relatórios.
- A matriz de permissões está disponível via endpoint
/ticket/rolese na interface administrativa.
5. Estruturas de Request/Response
DTOs principais
AssignTicketOwnerDto
{ owner_person_id?: number; }CreateTicketChannelAccountDto
{ channel_id?: number; code?: string; name?: string; external_identifier?: string; status?: string; ai_enabled?: boolean; ai_model?: string; }CreateTicketChannelDto
{ code?: string; name?: string; kind?: string; status?: string; }CreateTicketInternalNoteDto
{ body?: string; }CreateTicketReplyDto
{ subject?: string; body?: string; }UpdateTicketChannelAccountDto
{ name?: string; external_identifier?: string; status?: string; ai_enabled?: boolean; ai_model?: string; }UpdateTicketChannelDto
{ name?: string; status?: string; }UpdateTicketPriorityDto
{ priority?: string; }UpdateTicketSettingsDto
{ enabled?: boolean; code_prefix?: string; default_ai_review_mode?: string; default_visibility?: string; auto_assign_enabled?: boolean; default_owner_person_id?: number; allow_public_reply?: boolean; allow_internal_notes?: boolean; default_reopen_on_customer_reply?: boolean; default_close_after_days_without_reply?: number; }UpdateTicketStatusDto
{ status?: string; }
6. Erros Comuns
- 401 Unauthorized: Usuário não autenticado ou sem permissão para o recurso.
- 400 Bad Request: Dados inválidos ou incompletos no corpo da requisição.
- 404 Not Found: Recurso (ticket, canal, conta) não encontrado para o ID informado.
7. Banco de Dados (Tabelas YAML)
channel
- Finalidade: Define canais de comunicação (ex: portal, email, whatsapp).
- Colunas:
id(PK)code(varchar 64, único)name(varchar 160)kind(enum: portal, marketplace, social, form, email, whatsapp, api, other)status(enum: active, inactive, default active)created_at,updated_at
- Índices:
code(único),kind,status
channel_account
- Finalidade: Contas específicas vinculadas a canais.
- Colunas:
id(PK)channel_id(FK para channel.id, RESTRICT)code(varchar 80, único)name(varchar 180)external_identifier(varchar 255, nullable)status(enum: active, inactive, default active)settings_json(json, nullable)created_at,updated_at
- Índices:
code(único),channel_id,status,external_identifier
ticket
- Finalidade: Registro principal dos tickets de atendimento.
- Colunas:
id(PK)code(varchar 40, único)subject(varchar 255)status(enum: open, pending, waiting_customer, resolved, closed, spam; default open)priority(enum: low, normal, high, urgent; default normal)visibility(enum: private, public; default private)ai_review_mode(enum: disabled, optional, required; default optional)requester_person_id(FK para person.id, nullable, SET NULL)owner_person_id(FK para person.id, nullable, SET NULL)- Datas de mensagens e status (
first_message_at,last_message_at, etc.) created_at,updated_at
- Índices:
code(único),status,priority,visibility,ai_review_mode,requester_person_id,owner_person_id, combinações para performance
ticket_ai_draft
- Finalidade: Rascunhos e revisões AI para respostas.
- Colunas:
id(PK)ticket_id(FK para ticket.id, CASCADE)ticket_message_id(FK para ticket_message.id, nullable, SET NULL)model_name(varchar 120)status(enum: draft, pending_review, approved, rejected, sent; default draft)suggestion_html,suggestion_text,feedback(text, nullable)reviewed_by_person_id(FK para person.id, nullable, SET NULL)reviewed_at(datetime, nullable)created_at,updated_at
- Índices:
ticket_id,ticket_message_id,status,reviewed_by_person_id,created_at
ticket_attachment
- Finalidade: Anexos vinculados a mensagens de tickets.
- Colunas:
id(PK)ticket_message_id(FK para ticket_message.id, CASCADE)kind(enum: image, file, link)storage(enum: upload, external_url)file_name,mime_type,url(varchar, nullable)size_bytes(int, nullable)content(text, nullable)created_at,updated_at
- Índices:
ticket_message_id,kind,storage,created_at
ticket_category
- Finalidade: Associação de tickets a categorias.
- Colunas:
id(PK)ticket_id(FK para ticket.id, CASCADE)category_id(FK para category.id, CASCADE)created_at,updated_at
- Índices: combinação única
ticket_id, category_id, índices individuais
ticket_context
- Finalidade: Contexto externo relacionado ao ticket (curso, vídeo, página etc).
- Colunas:
id(PK)ticket_id(FK para ticket.id, CASCADE, único)channel_account_id(FK para channel_account.id, nullable, SET NULL)context_type(enum: course_lesson, course, video, page, email_thread, whatsapp_chat, contact_form, other)- Campos opcionais para nomes e URLs contextuais
created_at,updated_at
- Índices:
ticket_id(único),channel_account_id,context_type, campos de nome e label
ticket_message
- Finalidade: Mensagens trocadas em tickets.
- Colunas:
id(PK)ticket_id(FK para ticket.id, CASCADE)author_person_id(FK para person.id, nullable, SET NULL)parent_message_id(FK para ticket_message.id, nullable, SET NULL)direction(enum: inbound, outbound, internal, system)audience(enum: public, internal; default public)body_html,body_text(text, nullable)source_created_at(datetime, nullable)created_at,updated_at
- Índices:
ticket_id,author_person_id,parent_message_id,direction,audience,created_at
ticket_message_source
- Finalidade: Origem e status de entrega das mensagens.
- Colunas:
id(PK)ticket_message_id(FK para ticket_message.id, CASCADE)channel_account_id(FK para channel_account.id, nullable, SET NULL)provider_message_id,provider_thread_id(varchar, nullable)direction(enum: inbound, outbound)delivery_status(enum: pending, sent, delivered, failed, received, read; default pending)payload_json(json, nullable)sent_at,received_at(datetime, nullable)created_at,updated_at
- Índices:
ticket_message_id,channel_account_id,provider_message_id,provider_thread_id,direction,delivery_status,created_at
ticket_metadata
- Finalidade: Metadados customizados para tickets.
- Colunas:
id(PK)ticket_id(FK para ticket.id, CASCADE)key(varchar 120)value(text, nullable)created_at,updated_at
- Índices:
ticket_id,key, combinaçãoticket_id, key
ticket_participant
- Finalidade: Participantes associados a tickets com papéis.
- Colunas:
id(PK)ticket_id(FK para ticket.id, CASCADE)person_id(FK para person.id, CASCADE)role(enum: requester, agent, collaborator, watcher)created_at,updated_at
- Índices: combinação única
ticket_id, person_id, índices porticket_id, roleeperson_id, role
ticket_source
- Finalidade: Origem externa do ticket em contas de canal.
- Colunas:
id(PK)ticket_id(FK para ticket.id, CASCADE)channel_account_id(FK para channel_account.id, nullable, SET NULL)external_thread_id,external_message_id(varchar, nullable)external_url(varchar 500, nullable)status(enum: active, archived, sync_error; default active)metadata_json(json, nullable)created_at,updated_at
- Índices:
ticket_id,channel_account_id,status,external_thread_id,external_message_id
ticket_tag
- Finalidade: Associação de tags a tickets.
- Colunas:
id(PK)ticket_id(FK para ticket.id, CASCADE)tag_id(FK para tag.id, CASCADE)created_at,updated_at
- Índices: combinação única
ticket_id, tag_id, índices individuais
8. Regras de Negócio Relevantes
- Tickets possuem status, prioridade e visibilidade configuráveis.
- Tickets podem ser atribuídos a um proprietário (owner_person_id).
- Mensagens podem ser públicas ou internas, com direções inbound/outbound.
- Canais e contas de canais possuem status ativo/inativo para controle.
- Revisões AI são gerenciadas via rascunhos com status e feedback.
- Configurações globais e específicas por canal são armazenadas e gerenciadas.
- Papéis definem níveis de acesso e permissões para operações no módulo.
9. Guia Rápido de Uso (Exemplos)
Listar tickets (GET /ticket)
curl -H "Authorization: Bearer <token>" https://api.seudominio.com/ticketResposta:
{
"items": []
}Criar canal (POST /ticket/channels)
curl -X POST -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{"code":"email","name":"Email","kind":"email","status":"active"}' \
https://api.seudominio.com/ticket/channelsResposta:
{
"code": "email",
"name": "Email",
"kind": "email",
"status": "active"
}Atualizar status do ticket (PATCH /ticket/:id/status)
curl -X PATCH -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{"status":"resolved"}' \
https://api.seudominio.com/ticket/123/statusResposta:
{
"id": 123,
"status": "resolved"
}Criar resposta pública (POST /ticket/:id/reply)
curl -X POST -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{"subject":"Re: Dúvida","body":"Olá, sua dúvida foi resolvida."}' \
https://api.seudominio.com/ticket/123/replyResposta:
{
"id": 123,
"subject": "Re: Dúvida",
"body": "Olá, sua dúvida foi resolvida."
}Este módulo é parte integrante do monorepo HedHog e segue as políticas de governança, roles e configurações definidas para o ecossistema.
