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:
esdrasrenan 2025-12-07 20:45:37 -03:00
parent cb6add1a4a
commit f2c0298285
23 changed files with 4387 additions and 9 deletions

476
docs/EMAIL-NOTIFICATIONS.md Normal file
View 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