feat: sistema completo de notificacoes por e-mail
Implementa sistema de notificacoes por e-mail com: - Notificacoes de ciclo de vida (abertura, resolucao, atribuicao, status) - Sistema de avaliacao de chamados com estrelas (1-5) - Deep linking via protocolo raven:// para abrir chamados no desktop - Tokens de acesso seguro para visualizacao sem login - Preferencias de notificacao configuraveis por usuario - Templates HTML responsivos com design tokens da plataforma - API completa para preferencias, tokens e avaliacoes Modelos Prisma: - TicketRating: avaliacoes de chamados - TicketAccessToken: tokens de acesso direto - NotificationPreferences: preferencias por usuario Turbopack como bundler padrao (Next.js 16) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
cb6add1a4a
commit
f2c0298285
23 changed files with 4387 additions and 9 deletions
476
docs/EMAIL-NOTIFICATIONS.md
Normal file
476
docs/EMAIL-NOTIFICATIONS.md
Normal file
|
|
@ -0,0 +1,476 @@
|
|||
# Sistema de Notificacoes por E-mail
|
||||
|
||||
Este documento descreve o sistema completo de notificacoes por e-mail implementado na plataforma Raven.
|
||||
|
||||
## Visao Geral
|
||||
|
||||
O sistema de notificacoes por e-mail permite que usuarios sejam informados sobre eventos importantes relacionados aos seus chamados, alem de notificacoes de seguranca e autenticacao.
|
||||
|
||||
### Principais Funcionalidades
|
||||
|
||||
- Notificacoes de ciclo de vida do chamado (abertura, resolucao, atribuicao)
|
||||
- Notificacoes de comunicacao (comentarios publicos, respostas)
|
||||
- Sistema de avaliacao de chamados (estrelas 1-5)
|
||||
- Acesso direto ao chamado via protocolo `raven://`
|
||||
- Templates HTML responsivos
|
||||
- Sistema de preferencias configuravel
|
||||
- Alertas de SLA para staff
|
||||
- Notificacoes de seguranca (reset de senha, novo login)
|
||||
|
||||
---
|
||||
|
||||
## Tipos de Notificacoes
|
||||
|
||||
### Ciclo de Vida do Chamado
|
||||
|
||||
| Tipo | Codigo | Destinatario | Pode Desativar? |
|
||||
|------|--------|-------------|-----------------|
|
||||
| Abertura de chamado | `ticket_created` | Solicitante | Nao (obrigatorio) |
|
||||
| Atribuicao de chamado | `ticket_assigned` | Solicitante + Agente | Sim |
|
||||
| Resolucao de chamado | `ticket_resolved` | Solicitante | Nao (obrigatorio) |
|
||||
| Reabertura de chamado | `ticket_reopened` | Solicitante + Agente | Sim |
|
||||
| Mudanca de status | `ticket_status_changed` | Solicitante | Sim |
|
||||
| Mudanca de prioridade | `ticket_priority_changed` | Agente atribuido | Sim |
|
||||
|
||||
**Descricoes detalhadas:**
|
||||
|
||||
- **Abertura de chamado**: Enviado ao solicitante quando um novo chamado e criado, confirmando o numero de referencia e detalhes do chamado.
|
||||
|
||||
- **Atribuicao de chamado**: Notifica tanto o solicitante quanto o agente atribuido quando um chamado e designado para atendimento.
|
||||
|
||||
- **Resolucao de chamado**: Enviado ao solicitante quando o chamado e marcado como resolvido. Inclui link para avaliacao com estrelas (1-5).
|
||||
|
||||
- **Reabertura de chamado**: Notifica todas as partes quando um chamado fechado e reaberto.
|
||||
|
||||
- **Mudanca de status**: Informa o solicitante sobre alteracoes de status (Em andamento, Pausado, etc).
|
||||
|
||||
- **Mudanca de prioridade**: Notifica o agente atribuido quando a prioridade do chamado e alterada.
|
||||
|
||||
### Comunicacao
|
||||
|
||||
| Tipo | Codigo | Destinatario | Pode Desativar? |
|
||||
|------|--------|-------------|-----------------|
|
||||
| Comentario publico | `comment_public` | Solicitante | Sim (apenas solicitante) |
|
||||
| Resposta do solicitante | `comment_response` | Agente atribuido | Sim |
|
||||
| Mencao em comentario | `comment_mention` | Usuario mencionado | Sim |
|
||||
|
||||
**Descricoes detalhadas:**
|
||||
|
||||
- **Comentario publico**: Enviado ao solicitante quando um agente adiciona um comentario publico ao chamado.
|
||||
|
||||
- **Resposta do solicitante**: Notifica o agente atribuido quando o solicitante responde ao chamado.
|
||||
|
||||
- **Mencao em comentario**: Notifica um usuario quando ele e mencionado (@usuario) em um comentario.
|
||||
|
||||
### SLA e Alertas (Apenas Staff)
|
||||
|
||||
| Tipo | Codigo | Destinatario | Pode Desativar? |
|
||||
|------|--------|-------------|-----------------|
|
||||
| SLA em risco | `sla_at_risk` | Agente + Supervisor | Sim |
|
||||
| SLA violado | `sla_breached` | Agente + Admin | Sim |
|
||||
| Resumo diario de SLA | `sla_daily_digest` | Admin | Sim |
|
||||
|
||||
**Descricoes detalhadas:**
|
||||
|
||||
- **SLA em risco**: Enviado quando o chamado atinge 80% do tempo limite de resposta/resolucao.
|
||||
|
||||
- **SLA violado**: Notificacao urgente quando o SLA e excedido.
|
||||
|
||||
- **Resumo diario de SLA**: Relatorio enviado diariamente com metricas de SLA do dia anterior.
|
||||
|
||||
### Seguranca e Autenticacao
|
||||
|
||||
| Tipo | Codigo | Destinatario | Pode Desativar? |
|
||||
|------|--------|-------------|-----------------|
|
||||
| Reset de senha | `security_password_reset` | Usuario | Nao (obrigatorio) |
|
||||
| Verificacao de e-mail | `security_email_verify` | Usuario | Nao (obrigatorio) |
|
||||
| Alteracao de e-mail | `security_email_change` | E-mail antigo | Nao (obrigatorio) |
|
||||
| Novo login detectado | `security_new_login` | Usuario | Sim |
|
||||
| Convite de usuario | `security_invite` | Novo usuario | Nao (obrigatorio) |
|
||||
|
||||
**Descricoes detalhadas:**
|
||||
|
||||
- **Reset de senha**: Link para redefinicao de senha. Expira em 1 hora.
|
||||
|
||||
- **Verificacao de e-mail**: Link para confirmar novo endereco de e-mail.
|
||||
|
||||
- **Alteracao de e-mail**: Notifica o e-mail antigo quando o endereco e alterado.
|
||||
|
||||
- **Novo login detectado**: Alerta quando um login e realizado de um novo dispositivo ou localizacao.
|
||||
|
||||
- **Convite de usuario**: Convite para novos usuarios criarem conta na plataforma.
|
||||
|
||||
---
|
||||
|
||||
## Sistema de Avaliacao de Chamados
|
||||
|
||||
Quando um chamado e resolvido, o solicitante recebe um e-mail com opcao de avaliar o atendimento usando estrelas de 1 a 5.
|
||||
|
||||
### Fluxo de Avaliacao
|
||||
|
||||
1. Chamado e marcado como resolvido
|
||||
2. Solicitante recebe e-mail com 5 estrelas clicaveis
|
||||
3. Ao clicar em uma estrela, usuario e redirecionado para pagina de avaliacao
|
||||
4. Na pagina, pode adicionar um comentario opcional
|
||||
5. Avaliacao e registrada e associada ao chamado
|
||||
|
||||
### Endpoints
|
||||
|
||||
- `GET /api/tickets/rate?token={token}&rating={1-5}` - Registra avaliacao via link do e-mail
|
||||
- `POST /api/tickets/rate` - Registra avaliacao com comentario
|
||||
|
||||
### Modelo de Dados
|
||||
|
||||
```prisma
|
||||
model TicketRating {
|
||||
id String @id @default(cuid())
|
||||
tenantId String
|
||||
ticketId String @unique
|
||||
userId String
|
||||
rating Int // 1-5 estrelas
|
||||
comment String? // Feedback opcional
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Acesso Direto ao Chamado (Deep Linking)
|
||||
|
||||
### Protocolo raven://
|
||||
|
||||
O sistema suporta o protocolo `raven://` para abrir chamados diretamente no aplicativo desktop Raven.
|
||||
|
||||
**Formatos suportados:**
|
||||
|
||||
```
|
||||
raven://ticket/{ticketId}?token={accessToken}
|
||||
raven://chat/{ticketId}?token={accessToken}
|
||||
raven://rate/{ticketId}?rating={1-5}&token={accessToken}
|
||||
```
|
||||
|
||||
### Fluxo de Acesso
|
||||
|
||||
1. Usuario clica no link do e-mail (ex: `/ticket-view/{token}`)
|
||||
2. Pagina web tenta abrir o protocolo `raven://`
|
||||
3. Se o Raven estiver instalado, abre diretamente no app
|
||||
4. Se nao estiver instalado (timeout de 3s), exibe o chamado na web
|
||||
|
||||
### Tokens de Acesso
|
||||
|
||||
Tokens sao gerados para permitir acesso seguro sem necessidade de login.
|
||||
|
||||
```typescript
|
||||
interface TicketAccessToken {
|
||||
token: string // Token unico
|
||||
ticketId: string // Chamado associado
|
||||
userId: string // Usuario autorizado
|
||||
machineId?: string // Maquina esperada (opcional)
|
||||
scope: string // 'view', 'interact', 'rate'
|
||||
expiresAt: Date // Expira em 7 dias
|
||||
}
|
||||
```
|
||||
|
||||
### Endpoints
|
||||
|
||||
- `GET /api/ticket-access/{token}` - Valida token e retorna informacoes
|
||||
- `POST /api/ticket-access/{token}` - Marca token como usado
|
||||
|
||||
---
|
||||
|
||||
## Preferencias de Notificacao
|
||||
|
||||
### Para Staff (Admin, Manager, Agent)
|
||||
|
||||
Staff tem controle total sobre suas preferencias:
|
||||
|
||||
- Ativar/desativar e-mails globalmente
|
||||
- Configurar horario de silencio
|
||||
- Escolher frequencia de resumo (imediato, diario, semanal)
|
||||
- Ativar/desativar cada tipo de notificacao individualmente
|
||||
- Configurar preferencias por categoria
|
||||
|
||||
**Acesso:** `/settings/notifications`
|
||||
|
||||
### Para Solicitantes (Collaborators)
|
||||
|
||||
Solicitantes tem opcoes limitadas:
|
||||
|
||||
**Podem desativar:**
|
||||
- Comentarios publicos
|
||||
- Mudancas de status
|
||||
- Mudancas de prioridade
|
||||
- Novo login detectado
|
||||
|
||||
**NAO podem desativar (obrigatorios):**
|
||||
- Abertura de chamado
|
||||
- Resolucao de chamado
|
||||
- Reset de senha
|
||||
- Verificacao/alteracao de e-mail
|
||||
- Convites
|
||||
|
||||
**Acesso:** `/portal/profile/notifications`
|
||||
|
||||
### Modelo de Dados
|
||||
|
||||
```prisma
|
||||
model NotificationPreferences {
|
||||
id String @id @default(cuid())
|
||||
userId String @unique
|
||||
tenantId String
|
||||
emailEnabled Boolean @default(true)
|
||||
quietHoursStart String? // "22:00"
|
||||
quietHoursEnd String? // "08:00"
|
||||
timezone String @default("America/Sao_Paulo")
|
||||
digestFrequency String @default("immediate")
|
||||
typePreferences Json @default("{}")
|
||||
categoryPreferences Json @default("{}")
|
||||
}
|
||||
```
|
||||
|
||||
### API de Preferencias
|
||||
|
||||
- `GET /api/notifications/preferences` - Retorna preferencias do usuario
|
||||
- `PUT /api/notifications/preferences` - Atualiza preferencias
|
||||
|
||||
---
|
||||
|
||||
## Templates de E-mail
|
||||
|
||||
Todos os e-mails utilizam templates HTML responsivos com design consistente com a plataforma.
|
||||
|
||||
### Templates Disponiveis
|
||||
|
||||
| Template | Arquivo | Descricao |
|
||||
|----------|---------|-----------|
|
||||
| Teste | `test` | Template para testes de envio |
|
||||
| Abertura | `ticket_created` | Confirmacao de abertura de chamado |
|
||||
| Resolucao | `ticket_resolved` | Notificacao de resolucao com avaliacao |
|
||||
| Atribuicao | `ticket_assigned` | Notificacao de atribuicao |
|
||||
| Status | `ticket_status` | Mudanca de status |
|
||||
| Comentario | `ticket_comment` | Novo comentario publico |
|
||||
| Reset de senha | `password_reset` | Link para redefinir senha |
|
||||
| Verificar e-mail | `email_verify` | Confirmacao de e-mail |
|
||||
| Convite | `invite` | Convite para nova conta |
|
||||
| Novo login | `new_login` | Alerta de novo dispositivo |
|
||||
| SLA em risco | `sla_warning` | Alerta de SLA proximo do limite |
|
||||
| SLA violado | `sla_breached` | Alerta de SLA excedido |
|
||||
|
||||
### Tokens de Design
|
||||
|
||||
Os templates utilizam os mesmos tokens de design da plataforma:
|
||||
|
||||
```css
|
||||
/* Cores principais */
|
||||
--primary: #00e8ff
|
||||
--primary-dark: #00c4d6
|
||||
--background: #f7f8fb
|
||||
|
||||
/* Status */
|
||||
--status-pending: #64748b
|
||||
--status-progress: #0ea5e9
|
||||
--status-paused: #f59e0b
|
||||
--status-resolved: #10b981
|
||||
|
||||
/* Prioridade */
|
||||
--priority-low: #64748b
|
||||
--priority-medium: #0ea5e9
|
||||
--priority-high: #f97316
|
||||
--priority-urgent: #ef4444
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Arquitetura
|
||||
|
||||
### Estrutura de Arquivos
|
||||
|
||||
```
|
||||
src/
|
||||
├── server/
|
||||
│ ├── email/
|
||||
│ │ ├── email-service.ts # Servico principal de envio
|
||||
│ │ ├── email-templates.ts # Renderizacao de templates
|
||||
│ │ └── index.ts # Exports
|
||||
│ └── notification/
|
||||
│ ├── notification-service.ts # Orquestrador de notificacoes
|
||||
│ └── token-service.ts # Gerenciamento de tokens
|
||||
├── app/
|
||||
│ ├── api/
|
||||
│ │ ├── notifications/
|
||||
│ │ │ └── preferences/
|
||||
│ │ │ └── route.ts # API de preferencias
|
||||
│ │ ├── ticket-access/
|
||||
│ │ │ └── [token]/
|
||||
│ │ │ └── route.ts # API de tokens de acesso
|
||||
│ │ └── tickets/
|
||||
│ │ └── rate/
|
||||
│ │ └── route.ts # API de avaliacao
|
||||
│ ├── ticket-view/
|
||||
│ │ └── [token]/
|
||||
│ │ └── page.tsx # Pagina de visualizacao
|
||||
│ ├── rate/
|
||||
│ │ └── [token]/
|
||||
│ │ └── page.tsx # Pagina de avaliacao
|
||||
│ ├── settings/
|
||||
│ │ └── notifications/
|
||||
│ │ └── page.tsx # Preferencias (staff)
|
||||
│ └── portal/
|
||||
│ └── profile/
|
||||
│ └── notifications/
|
||||
│ └── page.tsx # Preferencias (colaboradores)
|
||||
└── components/
|
||||
└── settings/
|
||||
└── notification-preferences-form.tsx
|
||||
```
|
||||
|
||||
### Servicos Principais
|
||||
|
||||
#### EmailService (`email-service.ts`)
|
||||
|
||||
Responsavel pelo envio de e-mails:
|
||||
|
||||
```typescript
|
||||
await sendEmail({
|
||||
to: 'usuario@email.com',
|
||||
subject: 'Assunto do e-mail',
|
||||
html: '<html>...</html>',
|
||||
text: 'Versao texto',
|
||||
})
|
||||
```
|
||||
|
||||
#### NotificationService (`notification-service.ts`)
|
||||
|
||||
Orquestra o envio de notificacoes:
|
||||
|
||||
```typescript
|
||||
// Notifica abertura de chamado
|
||||
await notifyTicketCreated(ticket)
|
||||
|
||||
// Notifica resolucao
|
||||
await notifyTicketResolved(ticket, resolutionSummary)
|
||||
|
||||
// Notifica comentario
|
||||
await notifyPublicComment(ticket, comment)
|
||||
```
|
||||
|
||||
#### TokenService (`token-service.ts`)
|
||||
|
||||
Gerencia tokens de acesso:
|
||||
|
||||
```typescript
|
||||
// Gera token
|
||||
const token = await generateAccessToken({
|
||||
ticketId: 'xxx',
|
||||
userId: 'xxx',
|
||||
scope: 'view',
|
||||
expiresInDays: 7,
|
||||
})
|
||||
|
||||
// Valida token
|
||||
const validated = await validateAccessToken(token)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuracao SMTP
|
||||
|
||||
O sistema utiliza SMTP para envio de e-mails. Consulte `docs/SMTP.md` para configuracao detalhada.
|
||||
|
||||
### Variaveis de Ambiente
|
||||
|
||||
```env
|
||||
SMTP_HOST=smtp.exemplo.com
|
||||
SMTP_PORT=587
|
||||
SMTP_USER=usuario
|
||||
SMTP_PASS=senha
|
||||
SMTP_FROM=noreply@exemplo.com
|
||||
SMTP_FROM_NAME=Raven
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Seguranca
|
||||
|
||||
### Protecoes Implementadas
|
||||
|
||||
1. **Tokens expiraveis**: Tokens de acesso expiram em 7 dias
|
||||
2. **Uso unico para acoes**: Tokens de avaliacao sao invalidados apos uso
|
||||
3. **Rate limiting**: Limite de envios por usuario/minuto
|
||||
4. **Sanitizacao HTML**: Todo conteudo dinamico e escapado
|
||||
5. **Links HTTPS**: Todos os links utilizam HTTPS
|
||||
6. **Preferencias obrigatorias**: Notificacoes de seguranca nao podem ser desativadas
|
||||
|
||||
### Validacao de Tokens
|
||||
|
||||
```typescript
|
||||
// Verifica escopo do token
|
||||
if (!hasScope(token.scope, 'rate')) {
|
||||
return { error: 'Permissao insuficiente' }
|
||||
}
|
||||
|
||||
// Verifica expiracao
|
||||
if (new Date() > token.expiresAt) {
|
||||
return { error: 'Token expirado' }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testes
|
||||
|
||||
### E-mail de Teste
|
||||
|
||||
Para testar o sistema, utilize o endpoint de teste:
|
||||
|
||||
```typescript
|
||||
POST /api/email/test
|
||||
{
|
||||
"to": "email@teste.com"
|
||||
}
|
||||
```
|
||||
|
||||
### Variaveis de Teste
|
||||
|
||||
```env
|
||||
TEST_EMAIL_RECIPIENT=monkeyesdras@gmail.com
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Compatibilidade
|
||||
|
||||
### Clientes de E-mail Suportados
|
||||
|
||||
- Gmail (web + app)
|
||||
- Outlook (web + desktop + app)
|
||||
- Apple Mail (macOS + iOS)
|
||||
- Yahoo Mail
|
||||
- Thunderbird
|
||||
|
||||
### Tecnicas de Compatibilidade
|
||||
|
||||
- Layout com tabelas (nao flexbox/grid)
|
||||
- CSS inline (nao blocos `<style>`)
|
||||
- Imagens com atributo `alt`
|
||||
- Fallback para fontes do sistema
|
||||
- Max-width com media queries
|
||||
|
||||
---
|
||||
|
||||
## Proximos Passos
|
||||
|
||||
### Funcionalidades Planejadas
|
||||
|
||||
- [ ] Resumos digest (diario/semanal)
|
||||
- [ ] Preferencias por categoria
|
||||
- [ ] Relatorios semanais para admins
|
||||
- [ ] Notificacoes de backup
|
||||
- [ ] Fila de envio com retry
|
||||
|
||||
### Melhorias
|
||||
|
||||
- [ ] Testes automatizados para templates
|
||||
- [ ] Preview de e-mail na interface
|
||||
- [ ] Metricas de entrega
|
||||
- [ ] Integracao com servicos de e-mail marketing
|
||||
Loading…
Add table
Add a link
Reference in a new issue