305 lines
4.9 KiB
Markdown
305 lines
4.9 KiB
Markdown
PROJETO: CRM COMPLETO DE GERENCIAMENTO DE SORTEIOS COM PREÇO DINÂMICO, SORTEIO AUTOMÁTICO E NOTIFICAÇÕES
|
|
|
|
OBJETIVO:
|
|
Construir um sistema completo (backend + frontend) para gerenciamento de sorteios com:
|
|
- Venda de números
|
|
- Preço dinâmico por horário/período
|
|
- Preço fixo padrão
|
|
- Execução automática de sorteios
|
|
- Sistema de notificações (in-app + WhatsApp + email)
|
|
- Área do ganhador (resgate de prêmio)
|
|
- Auditoria completa e rastreabilidade
|
|
|
|
STACK:
|
|
- Frontend: React + Next.js (App Router)
|
|
- Backend: Next.js API Routes ou Node.js
|
|
- Banco: PostgreSQL
|
|
- ORM: Prisma
|
|
- Redis (recomendado para lock e reservas)
|
|
- Worker: BullMQ ou node-cron
|
|
|
|
---
|
|
|
|
MODELAGEM DO BANCO:
|
|
|
|
Tabela: raffles
|
|
- id
|
|
- title
|
|
- description
|
|
- total_numbers
|
|
- price_default
|
|
- status (draft, active, finished)
|
|
- start_at
|
|
- end_at
|
|
- created_at
|
|
|
|
Tabela: raffle_price_rules
|
|
- id
|
|
- raffle_id
|
|
- type (fixed, time_range)
|
|
- price
|
|
- start_time (nullable)
|
|
- end_time (nullable)
|
|
- priority
|
|
- created_at
|
|
|
|
Tabela: raffle_numbers
|
|
- id
|
|
- raffle_id
|
|
- number
|
|
- status (available, reserved, sold)
|
|
- reserved_until
|
|
- user_id
|
|
- order_id
|
|
|
|
Tabela: orders
|
|
- id
|
|
- user_id
|
|
- raffle_id
|
|
- total_amount
|
|
- status (pending, paid, canceled)
|
|
- payment_method
|
|
- created_at
|
|
|
|
Tabela: order_items
|
|
- id
|
|
- order_id
|
|
- raffle_number_id
|
|
- price_paid
|
|
|
|
Tabela: price_logs
|
|
- id
|
|
- raffle_id
|
|
- applied_price
|
|
- rule_id
|
|
- applied_at
|
|
|
|
Tabela: raffle_results
|
|
- id
|
|
- raffle_id
|
|
- winner_number_id
|
|
- seed
|
|
- algorithm_version
|
|
- drawn_at
|
|
- created_at
|
|
|
|
Tabela: raffle_claims
|
|
- id
|
|
- raffle_id
|
|
- user_id
|
|
- status (pending, approved, delivered)
|
|
- delivery_type (pickup, shipping)
|
|
- notes
|
|
- updated_at
|
|
|
|
Tabela: notifications
|
|
- id
|
|
- user_id
|
|
- type (winner, purchase, reminder)
|
|
- title
|
|
- message
|
|
- read (boolean)
|
|
- metadata (json)
|
|
- created_at
|
|
|
|
Tabela: raffle_draw_logs
|
|
- id
|
|
- raffle_id
|
|
- seed
|
|
- result_number
|
|
- executed_at
|
|
- ip
|
|
- created_at
|
|
|
|
---
|
|
|
|
ENGINE DE PREÇO:
|
|
|
|
Criar função getCurrentPrice(raffleId):
|
|
|
|
1. Buscar regras do sorteio
|
|
2. Filtrar regras válidas:
|
|
- fixed → sempre válido
|
|
- time_range → validar horário atual
|
|
3. Ordenar por prioridade DESC
|
|
4. Retornar preço da regra mais prioritária
|
|
5. Fallback → price_default
|
|
|
|
IMPORTANTE:
|
|
- Salvar preço aplicado em order_items.price_paid
|
|
- Não recalcular após venda
|
|
|
|
---
|
|
|
|
REGRAS DE NEGÓCIO:
|
|
|
|
1. Reserva de número:
|
|
- status = reserved
|
|
- expira em 5 minutos (Redis recomendado)
|
|
|
|
2. Compra:
|
|
- validar disponibilidade
|
|
- criar order + order_items
|
|
- atualizar número → sold
|
|
|
|
3. Concorrência:
|
|
- lock via Redis ou transação DB
|
|
|
|
4. Auditoria:
|
|
- registrar preço aplicado (price_logs)
|
|
|
|
---
|
|
|
|
MOTOR DE SORTEIO AUTOMÁTICO:
|
|
|
|
TRIGGERS:
|
|
- por horário (end_at)
|
|
- por lotação (todos vendidos)
|
|
- manual (admin)
|
|
|
|
ALGORITMO:
|
|
|
|
seed = SHA256(
|
|
raffle.id +
|
|
raffle.end_at +
|
|
total_sold +
|
|
last_order_id
|
|
)
|
|
|
|
winnerIndex = seed % total_sold_numbers
|
|
|
|
PROCESSO:
|
|
|
|
1. calcular seed
|
|
2. selecionar número vencedor
|
|
3. salvar em raffle_results
|
|
4. atualizar raffle.status = finished
|
|
5. salvar log em raffle_draw_logs
|
|
6. disparar notificações
|
|
|
|
IMPORTANTE:
|
|
- resultado deve ser auditável
|
|
- seed deve ser exibido para transparência
|
|
- impedir alterações após sorteio
|
|
|
|
---
|
|
|
|
SISTEMA DE NOTIFICAÇÕES:
|
|
|
|
TIPOS:
|
|
- winner (ganhador)
|
|
- purchase (compra confirmada)
|
|
- reminder (lembrete)
|
|
|
|
EXEMPLO:
|
|
|
|
{
|
|
"type": "winner",
|
|
"title": "Parabéns! Você ganhou",
|
|
"message": "Você ganhou com o número 072",
|
|
"raffle_id": 1
|
|
}
|
|
|
|
CANAIS:
|
|
- In-app (obrigatório)
|
|
- WhatsApp (API externa)
|
|
- Email (fallback)
|
|
|
|
---
|
|
|
|
FLUXO DE NOTIFICAÇÃO:
|
|
|
|
Ao finalizar sorteio:
|
|
|
|
1. identificar ganhador
|
|
2. criar notification (winner)
|
|
3. enviar WhatsApp
|
|
4. enviar email
|
|
|
|
---
|
|
|
|
ÁREA DO GANHADOR:
|
|
|
|
Tela: Meus Prêmios
|
|
|
|
- listar sorteios ganhos
|
|
- número vencedor
|
|
- status:
|
|
- pending
|
|
- approved
|
|
- delivered
|
|
|
|
Tela: Detalhe do prêmio
|
|
|
|
- dados do sorteio
|
|
- botão:
|
|
- confirmar dados
|
|
- solicitar retirada
|
|
|
|
---
|
|
|
|
TELAS DO CRM:
|
|
|
|
1. Gestão de Sorteios
|
|
2. Regras de Preço
|
|
3. Mapa de Números (grid interativo)
|
|
4. Pedidos
|
|
5. Financeiro
|
|
6. Resultados de sorteio
|
|
7. Notificações
|
|
8. Gestão de prêmios (claims)
|
|
|
|
---
|
|
|
|
RELATÓRIOS:
|
|
|
|
1. Vendas por dia
|
|
2. Vendas por hora
|
|
3. Preço aplicado
|
|
4. Números vendidos
|
|
5. Receita total
|
|
6. Taxa de conversão
|
|
7. Performance por faixa de horário
|
|
|
|
---
|
|
|
|
ENDPOINTS:
|
|
|
|
POST /raffles
|
|
GET /raffles
|
|
POST /raffles/:id/price-rules
|
|
GET /raffles/:id/current-price
|
|
POST /orders
|
|
GET /orders
|
|
POST /raffles/:id/draw
|
|
GET /raffles/:id/result
|
|
POST /notifications
|
|
GET /notifications
|
|
|
|
---
|
|
|
|
WORKER / CRON:
|
|
|
|
- verificar sorteios vencidos
|
|
- executar draw automático
|
|
- disparar notificações
|
|
|
|
---
|
|
|
|
REGRAS CRÍTICAS:
|
|
|
|
- snapshot de preço no momento da compra
|
|
- bloquear alterações após sorteio
|
|
- logs completos de execução
|
|
- sistema auditável
|
|
- prevenção de fraude
|
|
|
|
---
|
|
|
|
DIFERENCIAIS:
|
|
|
|
- transparência (seed + algoritmo)
|
|
- preço dinâmico inteligente
|
|
- notificações automáticas multicanal
|
|
- sistema preparado para escala
|
|
- base pronta para IA futura (precificação e comportamento) |