name: comercialrs-whatsapp-button-bug
description: "Bug: WhatsApp button clicks updating wrong meeting in ComercialRS (2026-06-02)"
tags: ["comercialrs", "whatsapp", "meta-webhook", "bugfix"]
category: devops
Bug: WhatsApp Button Clicks Atualizavam Reunião Errada
Data
2026-06-02
Sistemas envolvidos
- -
meta_webhook_vps_service.py(porta 8083, ativo) - -
meta_webhook_vps.py(porta 8080, referência) - - Supabase Cloud: tabela
tasks - -
/var/www/comercialrs/data/meta_webhook_vps_service.py— ative (8083) - -
/var/www/comercialrs/data/meta_webhook_vps.py— referência (8080) - - PID: 1660621
- - Porta: 8083
- - Log:
/var/log/meta_webhook.log - - both files:
meta_webhook_vps_service.py(ativo) emeta_webhook_vps.py(ref) - -
message_log— usado pelo ComercialRS para linkar WhatsApp a reuniões - -
incoming_messages— usado pelo DocCorretor para upload de documentos - -
tasks— reuniões do ComercialRS - -
dispatch-automationEdge Function — ComercialRS - -
meta-webhookEdge Function — ComercialRS
Bug 1: ORDER BY due_date atualizava reunião mais antiga
Sintoma
Corretor com 3 reuniões abertas clica no botão da reunião mais recente, mas o sistema atualiza a mais antiga (due_date mais antigo).
Causa raiz
find_task_by_phone_and_status() usava ORDER BY due_date ASC — pegava a primeira pelo prazo mais antigo, não a que o usuário clicou.
Fix
Remover o ORDER BY due_date ASC — o comportamento correto é mostrar menu de desambiguação quando há múltiplas tarefas.
Bug 2: Menu mostrava 82 em vez de 27 reuniões
Diferença painel vs menu
| Fonte | Filtro | Quantidade |
| ------- | -------- | ------------ |
| Painel ComercialRS | status = 'todo' | 27 |
| Menu WhatsApp (antes) | status IN ('todo', 'in_progress') | 82 |
| Menu WhatsApp (depois) | depende do botão | varies |
Lógica de filtro por botão (após fix)
`python
if status == 'in_progress': # "Iniciada" → só A Fazer
WHERE status = 'todo'
elif status == 'completed': # "Concluída" → A Fazer + Em Atendimento
WHERE status IN ('todo', 'in_progress')
else: # remarketing → todas
WHERE status IN ('todo', 'in_progress')
`
Diagnóstico rápido
`sql
-- Ver tarefas de um responsável por status
SELECT status, COUNT(*) FROM tasks
WHERE responsible = 'a2798f3b-814e-4370-ae6c-042537a1fad3'
GROUP BY status;
-- Ver tarefas atualizadas recentemente (WhatsApp)
SELECT id, title, due_date, status, responsible, updated_at
FROM tasks
WHERE responsible = '...'
ORDER BY updated_at DESC LIMIT 5;
`
Arquivos
Restart após mudança
`bash
fuser -k 8083/tcp; sleep 2
nohup /usr/bin/python3 /var/www/comercialrs/data/meta_webhook_vps_service.py >> /var/log/meta_webhook.log 2>&1 &
`
🐛 Cadeia de Bugs — Cliques Silenciosamente Perdidos
Sintoma: Corretor clicava botão "Iniciada" várias vezes, nada acontecia, nenhuma tarefa era atualizada.
Cadeia de falhas (3 bugs encadeados):
Bug A — Vírgula trailing no SQL ('todo',)
`python
LINHA ~157 — ANTES (quebrado)
statuses = "('todo',)" # ← vírgula após tuple de 1 elemento
...
WHERE status IN {statuses}
Produz: WHERE status IN ('todo',) → ERRO PostgreSQL
DEPOIS
statuses = "('todo')" # sem vírgula
`
Impacto: Query de menu lançava exceção silenciosa → exec_sql retornava None → menu mostrava todos os 82 items (sem filtro) em vez de só os relevantes.
Bug B — String vazia '' em coluna BIGINT
`python
LINHA ~404 — ANTES (quebrado)
sql = f"""INSERT INTO incoming_messages
(message_id, from_number, timestamp, msg_type, body)
VALUES (%s, %s, %s, %s, %s)"""
cursor.execute(sql, (msg_id, msg_from, '', msg_type, body))
↑ string vazia em coluna BIGINT → ERRO
DEPOIS
sql = f"""INSERT INTO incoming_messages
(message_id, from_number, timestamp, msg_type, body)
VALUES (%s, %s, NULL, %s, %s)"""
cursor.execute(sql, (msg_id, msg_from, msg_type, body))
↑ NULL explícito
`
Impacto: TODO clique de botão gerava [db error] silencioso → incoming_messages só tinha dados até ~01/06. Todo INSERT novo falhava.
Bug C — Clique em botão limpava seleção pendente
`python
Ao clicar botão com msg_text="" e existir pending_selection:
ANTES (quebrado) — msg_text="" era tratado como resposta vazia ao menu
if pending_selection and msg_text is None:
pending_selection = None # ← limpava pendência SEM atualizar
DEPOIS — botão com texto vazio limpa pendência e segue fluxo normal
user_response = msg_text.strip() if msg_text else ''
if pending_selection and user_response: # só processa se TEM texto
...
elif pending_selection and not user_response:
# Botão clicado (msg_text="") → limpa pendência, segue fluxo de botão
pending_selection = None
`
Impacto: Quando havia menu pendente e corretor clicava botão novamente, a pendência era limpa sem nenhuma ação. Cliques subsequentes eram perdidos.
📋 Fluxo Completo do Button Handler (pós-fixes)
`
1. Parse payload → (status, task_id_from_payload)
└── Formato novo: "iniciada|TASK_ID" → task_id direto
└── Formato antigo: "iniciada" → task_id = None
2. Se task_id_from_payload válido (≥32 chars):
└── get_task_by_id_direct(task_id) → atualiza diretamente
└── Não encontrado → "Reunião não encontrada"
3. Se task_id = None (formato antigo):
└── find_tasks_by_phone_and_status(phone, status)
└── 0 tarefas → "Nenhuma tarefa encontrada"
└── 1 tarefa → atualiza direto
└── 2+ tarefas → envia menu de desambiguação (max 10 itens)
└── Usuário responde número → seleciona tarefa correta
└── TTL: 120 segundos
`
Status do serviço
Bug 3: task_id sempre NULL no message_log (2026-06-03)
Sistema
Supabase Edge Functions — dispatch-automation/index.ts (deployado via supabase functions deploy)
Sintoma
Corretor responde "Iniciada" no WhatsApp → recebe confirmação ✅ → mas Kanban NÃO atualiza. A reunião errada era atualizada (ou nenhuma).
Causa raiz
Na função sendToMetaRecipients(), o logMessageSent() era chamado com taskId = null na posição do task_id:
`typescript
// ANTES — dispatch-automation/index.ts linha ~277
logMessageSent(
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!,
result.messageId,
null, // ← task_id NULL! Não linkava mensagem à reunião
member.id,
templateName,
member.phone!
);
// DEPOIS
logMessageSent(
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!,
result.messageId,
taskId, // ← task_id real da reunião
member.id,
templateName,
member.phone!
);
`
Resultado no banco
`sql
-- ANTES: task_id null em todos os message_log de hoje
meta_message_id | task_id | template_name
wamid.xxx... | NULL | nova_reuniao_criada -- 15 registros hoje
-- DEPOIS: próximo deploy linka corretamente
meta_message_id | task_id | template_name
wamid.yyy... |
`
Fluxo que quebrou
1. Reunião criada → dispatch-automation envia template WhatsApp
2. logMessageSent salvo com task_id = null ❌
3. Corretor responde "Iniciada" → webhook busca por meta_message_id
4. get_task_by_meta_message_id retorna task com base no join com tasks → ENCONTRAVA tarefa pois LEFT JOIN retornava status da task (não null) MAS o task_id do resultado era NULL
5. update_task_status_rpc chamado com task_id = null → não atualizava nada
6. Confirmação enviada ao corretor mesmo assim (o erro era silencioso no servidor)
Verificação pós-fix
`sql
-- Agora todas as reuniões novas terão task_id linkado
SELECT id, meta_message_id, task_id, status, created_at
FROM message_log
WHERE template_name = 'nova_reuniao_criada'
ORDER BY created_at DESC LIMIT 5;
-- task_id deve estar preenchido nas próximas criações
`
Deploy
`bash
cd /var/www/comercialrs
supabase functions deploy dispatch-automation --project-ref dauftiqcvgaydddoxqhh
`
Dados antigos
Os 15 registros de hoje (antes do fix) continuam com task_id = null. As respostas WhatsApp correspondentes não vão linkar corretamente. A partir do deploy, funcionando.
⚠️ Supabase Cloud Compartilhado
PROJETO COMPARTILHADO: dauftiqcvgaydddoxqhh é usado por ComercialRS E DocCorretor.
Tables/funções envolvidas:
NÃO ALTERAR sem verificar impacto no DocCorretor.