Atualização do READ.me

This commit is contained in:
2026-08-25 01:06:19 -03:00
parent 985e2e3b55
commit e272b96d0c

175
README.md
View File

@@ -2770,3 +2770,178 @@ docker compose exec app bin/rails db:migrate
```
</details>
---
<details>
<summary><strong>🎨 Ponte desatualizada, nome do Baileys fora da tela e padronização visual (25/08/2026)</strong></summary>
> ⚠️ **STATUS: implementado, não executado.** Sem migration. Sintaxe conferida nos 16 `.erb`
> tocados e nos 2 `.rb`. **Testes não rodados** — não há bundler na máquina de desenvolvimento,
> só no container.
### 1. `rota desconhecida` ao buscar os grupos
O botão "Buscar grupos" do cadastro de contato respondia **`rota desconhecida`**. Não era bug do
Rails: é o 404 da própria ponte (`whatsapp/server.js`, fallback de rota inexistente) repassado cru
para a tela.
A rota `GET /grupos` existe no código desde o commit `568f185`, mas **o container `whatsapp` do
ambiente de teste rodava uma imagem construída antes dele**. O deploy subiu o `app` e reaproveitou
a imagem em cache da ponte.
**Correção no servidor:**
```bash
docker compose up -d --build whatsapp
# se o cache ainda entregar a imagem velha:
docker compose build --no-cache whatsapp && docker compose up -d whatsapp
```
O volume `whatsapp_auth` é preservado — **não precisa ler o QR de novo**.
> 🔁 **A armadilha que volta:** toda vez que `whatsapp/server.js` ganha rota nova, a ponte precisa
> de rebuild próprio. `docker compose up -d --build` sem nomear o serviço pode reaproveitar a
> camada em cache, e o sintoma é sempre este: a tela nova chama uma rota que a ponte em pé não
> conhece. Vale conferir também que o `whatsapp/server.js` foi junto no merge para a `main` — o
> recurso de grupos ainda **não está lá**.
**Correção no código:** o 404 da ponte deixou de aparecer cru. `ClienteWhatsapp#mensagem_de_erro`
agora traduz para *"Ponte do WhatsApp desatualizada (não conhece esta rota) — refaça o build do
container `whatsapp`"*. É cosmético e **não substitui o rebuild**; serve para a próxima vez o erro
dizer o que fazer.
### 2. O nome "Baileys" saiu da interface
Nenhum texto que o usuário lê cita mais a biblioteca. A env var mostrada na tela de configuração
virou **`WHATSAPP_URL`**, e `baileys_url_efetiva` lê nesta ordem:
```
banco → ENV['WHATSAPP_URL'] → ENV['BAILEYS_URL'] → 'http://whatsapp:3001'
```
O nome antigo continua sendo lido de propósito: **nenhum `.env` já em produção quebra**.
> **Ficou de fora, de propósito:** as colunas `baileys_url` / `baileys_token` e os métodos
> `baileys?`, `baileys_pronto?`, `BAILEYS_URL_PADRAO` mantêm o nome no banco e no código.
> Renomear exigiria migration + model + controller + service + specs, e **nada disso aparece na
> tela** — os rótulos que o usuário lê já eram "Endereço da ponte" e "Token da ponte". O valor
> `'baileys'` do seletor de provedor também continua: é chave interna, o rótulo visível é
> "QR code (grátis, não oficial)".
### 3. Padronização visual das telas de notificação
As 9 telas do módulo nasceram com um dialeto próprio e destoavam do resto do admin. O padrão de
referência é **Usuários** — a tela mais madura. O que mudou:
| Antes (telas de notificação) | Agora (padrão do admin) |
|---|---|
| Botão `bg-orange-500 text-black`, `py-2.5` | `bg-[#f97316] text-white` com ícone, `min-h-[48px]` |
| `thead` com `bg-white/5`, `py-3`, `font-medium` | `border-b border-white/10`, `py-4`, `font-semibold` |
| Ações "Editar"/"Excluir" em texto | Ícones com `opacity-0 group-hover:opacity-100` |
| Vazio: `<p>` solto fora da tabela | Linha na tabela, ícone `:vazio`, `py-16` |
| Situação em texto colorido | `badge_status_usuario` / `badge_com_icone` |
| Inputs `bg-[#1a1a1a]`, `py-2.5` | `bg-[#0a0a0a]`, `py-3`, `focus:ring` laranja |
| Checkbox de ativo/inativo | Toggle switch, igual ao de Usuários |
| Formulário solto na página | Card `rounded-2xl border` com seções divididas |
**Correções de comportamento que vieram junto:**
- **`render 'shared/flash'` nas telas que não tinham.** Mensagens de sucesso e erro simplesmente
**não apareciam** em Contatos, Grupos, Eventos e Envios — a ação dava certo e a tela ficava muda.
- **O aviso do "Buscar grupos" ganhou cor semântica** — verde no sucesso, vermelho no erro. Antes
toda resposta saía em cinza, então "5 grupos encontrados" e "não foi possível falar com a ponte"
tinham exatamente o mesmo peso visual.
- O rótulo do botão de busca virou um `<span>` próprio: trocar o `textContent` do botão inteiro
apagava o ícone junto.
**Ganhos de leitura:** avatar distingue pessoa de grupo em Contatos; os filtros de Envios ficaram
agrupados por "Situação" e "Canal" com pílulas; o ponto verde de "Conectado" pulsa; evento
desativado fica esmaecido na lista.
### 📂 Arquivos
```
app/models/configuracao_notificacao.rb (WHATSAPP_URL com fallback p/ BAILEYS_URL)
app/services/notificacao/cliente_whatsapp.rb (404 da ponte vira mensagem acionável)
.env.example (WHATSAPP_URL; nome antigo documentado)
app/views/admin/configuracao_notificacoes/show.html.erb (nome da lib fora da tela)
app/views/admin/contatos/{index,_form,new,edit}.html.erb
app/views/admin/grupos_contato/{index,_form,new,edit}.html.erb
app/views/admin/eventos_notificacao/{index,_form,new,edit}.html.erb
app/views/admin/notificacao_envios/index.html.erb
app/views/admin/whatsapp_sessoes/show.html.erb
app/views/admin/mensagem_templates/edit.html.erb
```
### ⏳ Pendente
```bash
docker compose up -d --build whatsapp # ⚠️ o que resolve o "rota desconhecida"
docker compose restart app # views mudaram → cache de views do Puma
docker compose exec app bundle exec rspec
# Conferir na tela: Notificações → Contatos → Novo contato
# → Tipo "Grupo do WhatsApp" → "Buscar grupos" → a lista deve vir com nome,
# nº de participantes e ⚠️ nos grupos restritos a admin.
```
### 🐛 Achado não corrigido
`app/views/admin/mensagem_templates/edit.html.erb` carrega o **SortableJS de
`cdn.jsdelivr.net`**. Se a CSP passar de `report_only` para enforcing (pendência já registrada
neste README), o **arrastar-e-soltar dos blocos morre** — o clique na paleta sobrevive, porque o
código tem `if (window.Sortable)`. O conserto é baixar o arquivo para `public/`. Não foi feito por
estar fora do escopo pedido.
</details>
---
<details>
<summary><strong>🧭 O que falta: gatilhos pela tela e blocos ricos na mensagem — backlog</strong></summary>
Complementa o backlog do editor já registrado acima. **Nada aqui está implementado.**
### A. Criação de gatilhos pela tela
**Como é hoje:** o ADM cria quantos **eventos** quiser, mas o **gatilho** sai de uma lista fixa de
seis — `manual`, `consolidacao_finalizada`, `pagamento_efetuado`, `valor_alterado`,
`operacao_alterada`, `agendado`. A tela diz isso ao usuário: *"o gatilho sai de uma lista fixa,
porque gatilho é código"*. E é verdade — cada gatilho tem uma chamada correspondente no código de
negócio (`Notificacao::Gatilhos`, `NotificacaoService`, controllers).
**O que "criar gatilho pela tela" realmente significa** — três níveis, do barato ao caro:
| # | Ideia | Esforço | Observação |
|---|---|---|---|
| A1 | **Gatilho agendado com filtro** — "todo dia 08h **se houver consolidação pendente**". Não é gatilho novo: é o `agendado` com uma condição escolhida numa lista. | baixo | Cobre boa parte do que se pede como "gatilho novo". |
| A2 | **Gatilho por limiar** — "quando o valor alterado passar de R$ X" ou "quando as notas fora da operação passarem de N". Campos: métrica (lista), operador, valor. | médio | Reusa `Analytics::ResumoOperacao` e `OperacaoSnapshot`, que já calculam as métricas. |
| A3 | **Gatilhos que faltam no domínio** — consolidação **arquivada**, contato **sem grupo** há X dias, envio **falhado** (avisar o ADM que o WhatsApp caiu). | médio | São gatilhos de código mesmo: uma constante + a chamada no ponto certo. O caminho já está pavimentado por `disparar_gatilho`. |
| A4 | **Condição livre por regra** (construtor de expressão na tela) | **alto** | Vira uma mini-linguagem: precisa de parser, sandbox e validação. **Não recomendado** — A1+A2 entregam quase tudo por uma fração do custo. |
> ⚠️ **A armadilha aqui:** gatilho cadastrado na tela que **não tem chamada no código** fica mudo
> para sempre, sem erro nenhum — exatamente o bug nº 4 do deploy de 24/08. Qualquer caminho
> escolhido precisa de uma trava: ou a lista continua vindo do código, ou a tela avisa que o
> gatilho ainda não está ligado.
### B. Mais opções na criação da mensagem
**Como é hoje:** 7 blocos (`cabecalho`, `texto`, `tabela`, `aviso`, `botao`, `divisor`, `rodape`),
todos **só texto**, com cores fixas no renderizador.
| # | Ideia | Esforço | Observação |
|---|---|---|---|
| B1 | **Seletor de emoji** nos campos de texto — hoje só colando do sistema. Emoji é o que dá cara de WhatsApp à mensagem. | baixo | Um picker pequeno, sem dependência externa (a CSP é restritiva). Inserir no cursor: a mecânica já existe, é a mesma dos chips de variável. |
| B2 | **Bloco de imagem no e-mail** — `<img>` com URL ou upload. | médio | Cliente de e-mail bloqueia imagem remota por padrão → precisa de URL absoluta pública ou base64. |
| B3 | **Bloco de imagem no WhatsApp** | **alto** | A ponte hoje só faz `sendMessage` de **texto**. Exige `sendMessage(jid, { image })` no `server.js`, endpoint novo, envio multipart no `ClienteWhatsapp`, storage do arquivo e uma coluna no log de envios. **É o item mais caro da lista** — vale só se a demanda for real. |
| B4 | **Formatação do WhatsApp** (`*negrito*`, `_itálico_`, `~riscado~`, ``` `mono` ```) com botões — hoje o ADM precisa saber a sintaxe de cor. | baixo | No e-mail cada marca vira a tag equivalente. |
| B5 | **Bloco de lista com bullets** — hoje só existe tabela rótulo/valor. | baixo | Já estava listado como B7 no backlog anterior. |
| B6 | **Ocultar bloco com variável vazia** — resolve o `"⚠️ Alterações: "` sem nada depois. | baixo | Já listado como B1 antes; **continua sendo o melhor valor ÷ esforço do módulo inteiro**. |
| B7 | **Cor de destaque configurável** — o laranja está fixo no `Renderizador`. | baixo | |
| B8 | **Contador de caracteres no WhatsApp** — mensagem longa vira "ler mais", e o começo é o que decide se abrem. | baixo | |
| B9 | **Bloco de menção** (`@membro`) em grupo do WhatsApp | médio | Baileys exige passar os JIDs em `mentions` além do texto — não basta escrever `@`. |
### Se fosse escolher três
**B6** (mensagem sem buraco quando a variável vem vazia), **B1** (emoji) e **B4** (formatação do
WhatsApp por botão). Os três são de esforço baixo e atacam o que mais se sente escrevendo mensagem
no dia a dia. **B3 (imagem no WhatsApp) fica por último** — é o único que mexe na ponte, no cliente
Ruby e no schema ao mesmo tempo.
</details>