Skip to content

Regras de Caixas (Inboxes)

Caixas são os canais de atendimento no Chatwoot. Cada loja ativa no WhatsApp tem uma caixa associada.

Estrutura

Organização
  └─ Lojas
      └─ StoreWhatsappNumber (chatwootInboxId)
          └─ Chatwoot Inbox (canal de atendimento)
              └─ Agentes (vendedores)

Roteamento de mensagem inbound para caixa

Quando o cliente manda uma mensagem, o WhatsappRouterService decide qual caixa usar:

Modo Evolution

  1. Busca loja preferida do cliente (preferredStoreId)
  2. Verifica se a loja tem instância Evolution conectada
  3. Se sim: roteia para a caixa Chatwoot dessa loja
  4. Se não: tenta loja e-commerce como fallback

Modo WABA Oficial

  1. Busca conversa aberta no Chatwoot para o cliente nessa caixa
  2. Se existe: continua na mesma conversa
  3. Se não existe: cria nova conversa na caixa da loja preferida ou e-commerce

Atribuição de agente

Quando uma conversa é criada em uma caixa, o sistema atribui automaticamente um agente:

Prioridade:

  1. Vendedor preferido do cliente (preferredSellerId) — se for agente da caixa
    • Match: nome do agente Chatwoot começa com "preferredSeller -" + nome do vendedor, OU nome igual (case-insensitive)
  2. Distribuição por hash do telefone do cliente entre os agentes disponíveis da caixa

Fallback para e-commerce: Se a caixa da loja preferida não tem agentes, tenta a caixa da loja e-commerce. Se ainda assim não tem agentes, a conversa fica sem atribuição.

Business hours e controle de sessão de agentes

O BusinessHoursCronService executa 3 fases ao fechar a loja:

Fase 0 — No fechamento

  • Registra Redis flag bh:closed:{storeId} (TTL 20h)
  • Serve para detectar quando a loja reabre

Fase 2 — 30 min após fechamento

  • Bloqueia novos logins de agentes (blockAgentLogins)
  • Envia aviso de encerramento de sessão no Chatwoot
  • Inclui horário de encerramento = closeTime + 1h
  • Condição: Só bloqueia agentes cujas todas as lojas estão fechadas (proteção OR — agente com múltiplas lojas continua se alguma estiver aberta)

Fase 3 — 60 min após fechamento

  • Rotaciona tokens de autenticação dos agentes (rotateAgentsTokens)
  • Broadcast de user:logout via Redis pubsub (ActionCable Chatwoot)
  • Encerramento imediato de sessão (sem esperar 401)

Reabertura

  • Cron a cada minuto detecta flag bh:closed:{storeId} que sumiu (TTL expirou)
  • Desbloqueia logins (unblockAgentLogins)
  • Notifica clientes em espera (queue BusinessHoursWaiting)
  • Cria/atualiza conversa no Chatwoot para cada cliente em espera
  • Atribui agente e envia saudação

Expiração de conversa (janela 24h Meta)

Cron a cada 30 min: busca conversas com mensagem de boas-vindas enviada há 23h30 ou mais.

  1. Aplica label conversa_expirada
  2. Resolve a conversa no Chatwoot (status = resolved)
  3. Registra em WindowExpiry
  4. Evita reprocessar via Redis flag bh:expiry:{conversationId}

Grace period: Conversas com flag bh:grace:{conversationId} (TTL 2h) não são expiradas ainda — foram criadas quando a loja reabriu.

Mensagens configuráveis por caixa

Todas as mensagens enviadas pelo sistema são configuráveis em ChatwootConfig por organização:

MensagemQuando enviadaVariáveis
menuMessageCliente entra sem loja preferida
handoffMessageCliente é transferido para número de loja,
storeGreetingMessageLoja saúda o cliente (Evolution)
activeConversationMessageCliente já tem conversa aberta em outra loja,
connectingMessageModo WABA, conectando ao agente
closedMessageLoja fechada, cliente contacta fora do horário

Quando o cliente não tem loja preferida, o sistema exibe um menu:

  • ≤ 3 lojas: Botões de resposta rápida (WhatsApp buttons)
  • > 3 lojas: Menu de lista (WhatsApp list message)
  • Máximo: 10 lojas no menu (limite do sistema)

Ao selecionar a loja:

  • A loja é salva como preferredStoreId do cliente
  • Conversa é criada na caixa da loja selecionada

Trocar de loja

Se o cliente enviar a mensagem "trocar de loja", o menu é exibido novamente, independente de ter loja preferida. Essa verificação tem prioridade máxima no roteamento.