Skip to content

feat(juridico): notificação extrajudicial — geração de texto + envio via SendGrid#128

Merged
Warleypablo merged 24 commits intomainfrom
feature/notificacao-extrajudicial-juridico
Apr 24, 2026
Merged

feat(juridico): notificação extrajudicial — geração de texto + envio via SendGrid#128
Warleypablo merged 24 commits intomainfrom
feature/notificacao-extrajudicial-juridico

Conversation

@Warleypablo
Copy link
Copy Markdown
Owner

Resumo

Adiciona botão Gerar Notificação nos cards da coluna notificacao do kanban de negativação (/negativacao). Ao clicar, abre modal com o template da notificação extrajudicial de cobrança pré-preenchido com dados do cliente (email, endereço, CNPJ, parcelas em atraso) e permite enviar via email com auditoria completa.

Implementado em duas fases:

  • Fase 1 — Geração do texto com substituição de variáveis, preview editável, ação de copiar texto.
  • Fase 2 — Envio server-side via SendGrid, auditoria em tabela dedicada, BCC automático, confirmação obrigatória, detecção de duplicata.

Mudanças principais

Backend

  • Novo endpoint GET /api/negativacao/cliente/:clienteId/notificacao-data — busca cliente (caz_clientes) + parcelas em atraso
  • Novo endpoint GET /api/negativacao/cliente/:clienteId/notificacoes-enviadas — histórico para detectar duplicata
  • Novo endpoint POST /api/negativacao/notificacoes/enviar — envia + grava auditoria (status otimista + update com message_id)
  • Novo service server/services/sendgrid-notification.ts — wrapper puro do @sendgrid/mail
  • Nova tabela cortex_core.notificacoes_extrajudiciais_enviadas (schema Drizzle + migration SQL)
  • Dependência @sendgrid/mail@^8.1.6

Frontend

  • Novo componente NotificacaoExtrajudicialModal — form (email, endereço, nº contrato, data, serviço) + preview editável
  • Novo componente ConfirmacaoEnvioDialog — AlertDialog com aviso de duplicata quando aplicável
  • Nova lib client/src/lib/notificacao-extrajudicial.ts — funções puras: formatarMesesEmAtraso, formatarValoresDescricao, anoPorExtenso, renderizarNotificacao, renderizarNotificacaoHtml
  • Botão condicional no kanban (Negativacao.tsx) — só aparece em cards da coluna notificacao

Testes

  • 39 testes unitários passando (34 da lib de renderização + 5 do service SendGrid)
  • TDD em todas as funções puras

Requisitos pré-merge

  • Configurar env vars no ambiente de produção (.env):
    • SENDGRID_API_KEY
    • SENDGRID_FROM_EMAIL=juridico@turbopartners.com.br
    • SENDGRID_FROM_NAME=Departamento Jurídico - Turbo Partners
    • SENDGRID_BCC_EMAIL=juridico@turbopartners.com.br
  • Aplicar migration em produção:
    psql "\$DATABASE_URL_PROD" -f migrations/2026-04-23-create-notificacoes-enviadas.sql
  • Confirmar que domínio turbopartners.com.br está autenticado no SendGrid (SPF/DKIM) — necessário para emails não caírem em spam

Test plan

  • Fase 1 — modal abre, variáveis substituídas corretamente, preview editável, copiar texto funciona
  • Fase 2 — envio real validado em local: email entregue, BCC recebido, registro gravado em cortex_core.notificacoes_extrajudiciais_enviadas com status='enviado' e sendgrid_message_id
  • Duplicata — clicar "Notificar" na segunda vez para mesmo cliente: dialog mostra aviso amarelo "já foi notificado em ..."
  • Erro SendGrid — com API key inválida: toast vermelho com detalhe, registro gravado com status='erro'
  • Dark mode + light mode OK
  • Responsive mobile OK

Arquivos (resumo)

Backend:
  server/services/sendgrid-notification.ts        +82
  server/services/sendgrid-notification.test.ts   +123
  server/routes/negativacao.ts                    +189 (2 endpoints novos + 1 da fase 1)
  server/routes/juridico.ts                       +15
  server/storage.ts                               +12
  shared/schema.ts                                +19
  migrations/2026-04-23-create-notificacoes-enviadas.sql +22

Frontend:
  client/src/components/juridico/NotificacaoExtrajudicialModal.tsx +238
  client/src/components/juridico/ConfirmacaoEnvioDialog.tsx        +110
  client/src/lib/notificacao-extrajudicial.ts                      +237
  client/src/lib/notificacao-extrajudicial.test.ts                 +217
  client/src/pages/Negativacao.tsx                                 +94

Docs:
  docs/superpowers/specs/2026-04-23-notificacao-extrajudicial-juridico-design.md
  docs/superpowers/specs/2026-04-23-notificacao-extrajudicial-envio-fase2-design.md
  docs/superpowers/plans/2026-04-23-notificacao-extrajudicial-juridico.md
  docs/superpowers/plans/2026-04-23-notificacao-extrajudicial-envio-fase2.md

Config:
  package.json                                    +@sendgrid/mail
  .env.example                                    +6 linhas (documentação)

Roadmap futuro (fora desse PR)

  • Fase 3 (opcional) — UI de histórico no drawer de detalhes do kanban, webhook SendGrid para status bounced/delivered, geração de PDF anexado

🤖 Generated with Claude Code

Warleypablo and others added 24 commits April 23, 2026 10:44
Spec para botão 'Gerar Notificação' no card do funil jurídico com
substituição de variáveis e ação mailto. Envio server-side fica para
fase 2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… (fase 1)

8 tasks granulares com TDD nas funções puras, backend mínimo e
integração incremental no card do funil jurídico.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…plencia endpoint

Required for the upcoming extrajudicial notification feature in the
legal funnel. Adds both fields to the storage method query and propagates
them through the GET /api/juridico/clientes response.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Formata lista de datas de vencimento em string de meses/ano
ordenada cronologicamente, com tratamento de duplicatas e
timezone via getUTC*. Cobre parcelas em anos diferentes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Usa formato 'cada uma' quando valores iguais, senão lista detalhada
com data de vencimento de cada parcela.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ution

Função pura que monta a notificação extrajudicial com todas as
variáveis substituídas. Aceita Date injetável para testes
determinísticos. Placeholders explícitos quando dados estão ausentes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Modal com form de campos ausentes no banco, preview editável em tempo
real (com proteção contra sobrescrita após edição manual) e ações
copiar / abrir mailto.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previous Map.entries() iteration required downlevelIteration. Using forEach avoids the flag and keeps behavior identical.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…card

Botão 'Gerar Notificação' aparece apenas quando procedimentoJuridico
é 'notificacao'. Exibe modal com substituição automática de variáveis
e ações de copiar / abrir mailto.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
GET /api/negativacao/cliente/:clienteId/notificacao-data retorna os
dados necessários para gerar a notificação extrajudicial — cliente
(nome, empresa, CNPJ, email, endereço, serviços) e parcelas em atraso
(valor não pago + data de vencimento).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Botão pequeno "Mail + Notificar" nos cards da coluna notificacao do kanban.
Ao clicar: busca dados via /api/negativacao/cliente/:id/notificacao-data
e abre o NotificacaoExtrajudicialModal com substituição de variáveis.
stopPropagation evita abrir o drawer de detalhes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tification data

Modal now opens immediately with a loading skeleton while /notificacao-data
fetches. On error (401/404/500), shows a toast with HTTP status and closes
the modal instead of silently failing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The caz_clientes.empresa column stores the FATURADOR (e.g. 'Turbo Partners'),
not the client company name. The actual debtor name is in caz_clientes.nome
(mapped to nomeCliente). Flipped the fallback order so the notification
shows the real debtor, not our own company.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Design e plano de implementação da fase 2: envio efetivo via SendGrid
com auditoria (tabela notificacoes_extrajudiciais_enviadas), BCC
automático, confirmação obrigatória e detecção de duplicata. Remove
o mailto da fase 1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Preparação para Fase 2 (envio efetivo). API key, email remetente,
display name e BCC ficam em variáveis de ambiente.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tabela de auditoria com corpo completo (texto + HTML), destinatário,
usuário que enviou, status e sendgrid_message_id para rastreabilidade
jurídica.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wrapper puro com validação de env vars, formatação de payload
(from/replyTo/bcc) e tratamento de erro via SendGridError que expõe
status e body para auditoria.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
GET /api/negativacao/cliente/:id/notificacoes-enviadas retorna histórico
(10 mais recentes) para detectar duplicata. POST /api/negativacao/
notificacoes/enviar grava auditoria otimista, chama SendGrid, atualiza
status e message_id. Erros são registrados com status=erro.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Função pura que gera HTML semântico do template com inline styles
(fonte serif, larguras máximas, destacando NOTIFICANTE/NOTIFICADA em
negrito). Escapa caracteres especiais para prevenir XSS no corpo do
email.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AlertDialog que exige confirmação explícita antes do envio. Se o
cliente já foi notificado antes, exibe alerta amarelo com data/hora e
usuário do último envio, e estiliza o botão de confirmação como
destructive para forçar atenção.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Remove botão 'Abrir no email' e adiciona 'Enviar agora' que dispara
mutation POST /api/negativacao/notificacoes/enviar. Query de histórico
detecta duplicata e abre ConfirmacaoEnvioDialog com aviso quando
cliente já foi notificado antes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Template HTML agora tem:
- Header escuro (#0a0a0a) com marca 'TURBO PARTNERS' em destaque +
  tagline 'Departamento Jurídico' em caixa alta.
- Título da notificação centralizado com separador inferior.
- Blocos NOTIFICANTE/NOTIFICADA destacados em caixas com borda lateral.
- Parágrafos justificados, fonte Georgia serif.
- Aviso legal (art. 726 CPC) em caixa própria com fundo neutro.
- Assinatura (Vitória/ES, dd/mm/aaaa) alinhada à direita com separador.
- Rodapé com CNPJ e instrução de resposta.

Mantém paleta monocromática (preto/cinza/branco) para aspecto
corporativo formal sem elementos visuais distrativos.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Warleypablo Warleypablo merged commit f9e9035 into main Apr 24, 2026
2 checks passed
@Warleypablo Warleypablo deleted the feature/notificacao-extrajudicial-juridico branch April 24, 2026 20:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant