RelatoriosRS — DECISIONS
> Decisões técnicas tomadas durante o desenvolvimento.
2026-06-26
D1: Não usar Supabase Cloud (bloqueado por exceed_egress_quota)
Decisão: Usar o banco local deploy-vps-db-1 (Supabase self-hosted Docker) em vez do Supabase Cloud.
Contexto: Supabase Cloud dauftiqcvgaydddoxqhh está bloqueado. ComercialRS migrou para self-hosted. Hermes Insights deve usar o mesmo banco local.
Alternativas consideradas:
- - Tentar desbloqueio do Supabase Cloud → não viável
- - Conectar generate_reports.py ao banco local → feito
- - Acesso direto a todas as tabelas (messages, conversations, contacts, users)
- - Muito mais rápido para bulk data
- - Dados completos (timestamps, sender_id, etc.)
- - Acoplamento com schema do Chatwoot
- - Precisamos manter mapeamento de IDs
- - [ ] sync_messages_v9.py — capturar mensagens novas (se houver)
- - [ ] Frontend RelatoriosRS
- - [ ] Cron job
Impacto: generate_reports.py precisa apontar para deploy-vps-db-1 em vez do Supabase Cloud.
D2: Conectar no Chatwoot via PostgreSQL direto (não via API)
Decisão: Acessar dados do Chatwoot diretamente pelo PostgreSQL do VPS (root-postgres-1) em vez de usar API REST.
Contexto: Chatwoot está no mesmo VPS. API REST seria mais lenta e tem rate limits.
Vantagens:
Desvantagens:
D3: Usar stdin pipe para psql (sem shell quoting)
Decisão: Todas as queries PostgreSQL usam subprocess.Popen com stdin pipe, sem shell=True.
Problema que motivou: Com shell=True, caracteres como $, \t, ' causavam interpretação errada.
Padrão adotado:
`python
proc = subprocess.Popen(
["docker", "exec", "-i", "root-postgres-1",
"psql", "-U", "postgres", "-d", "chatwoot_production",
"-At", "-F", "\t", "--no-align"],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
out, err = proc.communicate(input=sql.encode("utf-8"))
`
Nota: "\t" em array-form passa literalmente \ + t (NÃO tab). Por isso usamos stdin pipe com -F flag separadamente.
D4: Tab delimiter (-F "\t") em vez de pipe (|)
Decisão: Usar tab como delimiter para dados do Chatwoot.
Problema: Pipe (|) aparece em nomes de contato (ex: "Maria | Silva"). Split por pipe quebra.
Solução: psql -At -F "\t" --no-align — tab não aparece em dados.
D5: Batch de 50 rows (não 200) com INSERT único
Decisão: BATCH_SIZE = 50, cada batch = 1 transação.
Problema: 200 rows num único INSERT = 1 transação. Se qualquer row tiver erro, todas revertem.
Solução: 50 rows por INSERT, transação independente por batch.
D6: Sync sem filtro de agente (todas as conversas)
Decisão: Sync sync_full_clean.py não filtra por assignee_id.
Problema: O sync anterior (sync_v7.py) só sincronizava conversas com agente. 1.973 conversas sem agente ficavam de fora.
Resultado: 4.115 conversas syncadas (vs ~2.829 antes).
Nota: 2.051 conversas não têm agente (sem atribuicao no Chatwoot).
D7: Constraint UNIQUE em chatwoot_id
Decisão: Adicionar UNIQUE (chatwoot_id) em insights.conversations.
Motivo: Evitar duplicatas em re-runs do sync. Sem constraint, INSERT duplicado insere outra row.
Implementação:
`sql
ALTER TABLE insights.conversations
ADD CONSTRAINT conversations_chatwoot_id_key UNIQUE (chatwoot_id);
`
D8: RelatoriosRS como neurônio separado
Decisão: Criar NEURONS/RelatoriosRS/ como neurônio próprio.
Contexto: RelatoriosRS é um projeto diferente de ComercialRS. Tem seu próprio banco, próprios scripts, próprio frontend. Justifica neurônio separado.
Estrutura:
`
NEURONS/RelatoriosRS/
├── neuron.md
├── MEMORY.md
├── DECISIONS.md
├── LOGS/
├── TOOLS/
└── DOCUMENTATION/
`
2026-06-26 — Continuação
D9: Mensagens re-linkadas com sucesso
Ação: 63.230 mensagens existentes re-linkadas às conversas corretas via UPDATE.
Método:
`sql
UPDATE insights.messages m
SET conversation_id = c.id
FROM insights.conversations c
WHERE c.chatwoot_id = m.chatwoot_conversation_id
AND m.conversation_id IS DISTINCT FROM c.id;
`
Resultado: 63.230 mensagens linkadas, 3.349 conversas com mensagens.
D10: Constraint UNIQUE em messages.chatwoot_id
Implementação:
`sql
ALTER TABLE insights.messages
ADD CONSTRAINT messages_chatwoot_id_key UNIQUE (chatwoot_id);
`
Motivo: Evitar duplicatas em re-runs. ON CONFLICT (chatwoot_id) DO NOTHING agora funciona.
Pendentes
Decisões registradas: 2026-06-26