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

View file

@ -145,6 +145,11 @@ model User {
reports User[] @relation("UserManager")
company Company? @relation(fields: [companyId], references: [id])
// Relações do sistema de notificações
ticketRatings TicketRating[]
ticketAccessTokens TicketAccessToken[]
notificationPreferences NotificationPreferences?
@@index([tenantId, role])
@@index([tenantId, companyId])
@@index([tenantId, managerId])
@ -202,6 +207,10 @@ model Ticket {
events TicketEvent[]
comments TicketComment[]
// Relações do sistema de notificações
rating TicketRating?
accessTokens TicketAccessToken[]
@@index([tenantId, status])
@@index([tenantId, queueId])
@@index([tenantId, assigneeId])
@ -398,3 +407,71 @@ model AuthVerification {
@@index([identifier])
}
// ============================================
// Sistema de Notificações por E-mail
// ============================================
model TicketRating {
id String @id @default(cuid())
tenantId String
ticketId String @unique
userId String
rating Int // 1-5 estrelas
comment String? // Feedback opcional do usuário
createdAt DateTime @default(now())
ticket Ticket @relation(fields: [ticketId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id])
@@index([tenantId, rating])
@@index([tenantId, createdAt])
}
model TicketAccessToken {
id String @id @default(cuid())
tenantId String
token String @unique
ticketId String
userId String
machineId String? // Máquina esperada (opcional)
scope String @default("view") // view, interact, rate
expiresAt DateTime
usedAt DateTime?
createdAt DateTime @default(now())
ticket Ticket @relation(fields: [ticketId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id])
@@index([tenantId, ticketId])
@@index([tenantId, userId])
@@index([expiresAt])
}
model NotificationPreferences {
id String @id @default(cuid())
tenantId String
userId String @unique
// Preferências globais
emailEnabled Boolean @default(true)
quietHoursStart String? // "22:00"
quietHoursEnd String? // "08:00"
timezone String @default("America/Sao_Paulo")
digestFrequency String @default("immediate") // immediate, daily, weekly
// Preferências por tipo de notificação (JSON)
// Ex: { "ticket_created": true, "ticket_resolved": true, "comment_public": false }
typePreferences Json @default("{}")
// Preferências por categoria de ticket (JSON)
// Ex: { "category_id_1": true, "category_id_2": false }
categoryPreferences Json @default("{}")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([tenantId])
}