Atualização das configuração de mesagens do Zap

This commit is contained in:
2026-08-24 19:05:48 -03:00
parent 568f185d8c
commit 7e093f3af8
12 changed files with 376 additions and 18 deletions

View File

@@ -2696,3 +2696,77 @@ Hoje: 7 blocos, cores fixas no renderizador, só texto.
vazia). Juntos são baixo esforço e resolvem o que mais incomoda no uso diário.
</details>
---
<details>
<summary><strong>👥 Envio para GRUPO do WhatsApp (24/08/2026)</strong></summary>
> ⚠️ **STATUS: implementado, não executado.** 1 migration nova. Sintaxe conferida em `.rb`, `.erb`,
> no JavaScript do formulário e no `server.js`.
### 🎯 O caso de uso
Informe pontual para o **grupo de motoristas** da própria empresa, com o número já dentro do grupo.
É o oposto do padrão de spam — não é mensagem para desconhecido, é aviso interno.
### ⚙️ Por que não funcionava
Grupo no WhatsApp **não é telefone**: é um identificador próprio (`120363012345678901@g.us`). Três
pontos assumiam pessoa:
1. `jidDe()` no `server.js` colava `@s.whatsapp.net` nos dígitos — id de grupo nem passava.
2. A checagem `onWhatsApp()` (que evita mandar para número inexistente, um dos sinais que a Meta usa
para marcar conta de spam) **responde sobre números** e devolveria vazio para um grupo,
derrubando um envio válido.
3. `Contato` exigia telefone brasileiro válido.
### 🆕 Como ficou
**Contato ganhou tipo**: `pessoa` ou `grupo_whatsapp`. O grupo entra como Contato de propósito —
herda grupo interno, assinatura de eventos e log de envios. Tabela separada duplicaria essa máquina
inteira.
**A lista de grupos vem da ponte** (`GET /grupos` → `groupFetchAllParticipating`). O id é opaco;
digitar na mão é pedir erro. No formulário, "Buscar grupos" traz os nomes com a contagem de
participantes.
**Grupo restrito é avisado ANTES.** Se o grupo tem "somente administradores" e o número conectado
não é admin, a opção aparece com ⚠️ na lista — senão o envio falharia e o erro só apareceria depois,
no log.
**O nome do grupo é gravado junto com o id** (`whatsapp_grupo_nome`): a tela precisa mostrar algo
legível mesmo com a ponte fora do ar.
**Twilio recusa com mensagem clara.** O Twilio não envia para grupo; em vez de erro genérico, a
resposta diz para trocar o provedor para QR.
### ⚠️ Limites, ditos na tela
- O número **precisa já ser membro** do grupo. A ponte não entra em grupo.
- Grupo com "somente admins" recusa se o número não for admin.
- `{{contato}}` num grupo é o **nome inteiro** do grupo — cortar "Motoristas SP" em "Motoristas"
só empobreceria o texto.
- Cadastro não fica meio pessoa, meio grupo: ao escolher grupo, telefone e e-mail são limpos.
Senão a mesma mensagem sairia duas vezes.
### 📂 Arquivos
```
db/migrate/20260824000008_add_grupo_whatsapp_to_contatos.rb (NOVO)
whatsapp/server.js (jidDe aceita @g.us; GET /grupos; pula onWhatsApp em grupo)
app/models/contato.rb (tipo, destino_whatsapp, validações por tipo)
app/services/notificacao/whatsapp.rb (JID passa direto; Twilio recusa)
app/services/notificacao/cliente_whatsapp.rb (#grupos)
app/services/notificacao/despachante.rb (usa destino_whatsapp)
app/controllers/admin/contatos_controller.rb + rota (JSON de grupos, sob demanda)
app/views/admin/contatos/_form.html.erb (seletor de tipo + busca de grupos)
app/views/admin/contatos/index.html.erb (marca "grupo")
spec/models/contato_spec.rb, spec/services/notificacao/whatsapp_spec.rb
```
### ⏳ Pendente
```bash
docker compose up -d --build whatsapp # o server.js mudou
docker compose exec app bin/rails db:migrate
# Depois: Notificações → Contatos → Novo contato → Tipo "Grupo do WhatsApp"
# → "Buscar grupos" → escolher → pôr num grupo interno que assine o evento.
```
</details>