383 lines
14 KiB
Markdown
383 lines
14 KiB
Markdown
# Inbox Interna — Arquitetura & Roadmap
|
|
|
|
**Data:** 2026-04-23
|
|
**Status:** v1 (Escalações + Human API) ✅ | v2.1 (DM entre Colaboradores) ✅ | v2.2 (Planejado: Group Chat + Broadcast)
|
|
|
|
---
|
|
|
|
## 📋 O que é?
|
|
|
|
**Inbox Interna** = Centro de comunicação interna da equipe para gerenciar escalações de clientes, pedidos de ajuda da IA e colaboração entre setores.
|
|
|
|
É onde:
|
|
- 🎯 **Escalações chegam** quando cliente pede falar com humano no WhatsApp
|
|
- 🤖 **IA pede ajuda** quando não consegue resolver algo (Human API)
|
|
- 💬 **Equipe colabora** deixando mensagens de contexto sobre protocolos
|
|
|
|
---
|
|
|
|
## 🏗️ Arquitetura Atual (v1)
|
|
|
|
### Tipos de Threads
|
|
|
|
| Tipo | Trigger | Origem | Exemplo |
|
|
|------|---------|--------|---------|
|
|
| **escalation** | Cliente escala no WhatsApp | Motor NewWhats | Protocolo #123: cliente reclamando |
|
|
| **human_api** | IA não consegue responder | Motor NewWhats | "Qual é a política de devolução?" |
|
|
| **ajuda** | Colaborador solicita suporte | UI "Preciso de ajuda" | Dúvida sobre procedimento |
|
|
| **mensagem** | Anotação de contexto | Colaboradores | "Cliente quer falar com gerente" |
|
|
| **sistema** | Avisos automáticos | Sistema | "Handoff expirou" |
|
|
|
|
### Estrutura de Dados
|
|
|
|
```sql
|
|
internal_messages {
|
|
id UUID
|
|
tenant_id INT (isolamento multi-tenant)
|
|
thread_id UUID (agrupa msgs da mesma conversa)
|
|
from_account INT (FK → accounts.id)
|
|
type VARCHAR (escalation|human_api|ajuda|mensagem|sistema)
|
|
content TEXT
|
|
ref_id VARCHAR (protocolo ou human_api_request.id)
|
|
chat_id VARCHAR (vinculado ao chat do WhatsApp)
|
|
lida BOOLEAN (marca como lida)
|
|
created_at TIMESTAMP
|
|
}
|
|
|
|
sector_brain_nodes {
|
|
id UUID
|
|
sector_id INT
|
|
type VARCHAR (knowledge|rules|escalation|persona)
|
|
title VARCHAR
|
|
content TEXT
|
|
active BOOLEAN
|
|
sort_order INT
|
|
}
|
|
```
|
|
|
|
### Fluxo Atual
|
|
|
|
```
|
|
┌─ WhatsApp ─────┐
|
|
│ Cliente fala │
|
|
│ com IA │
|
|
└────────┬────────┘
|
|
│
|
|
┌────▼──────────┐
|
|
│ Motor NewWhats│
|
|
│ (porta 8008) │
|
|
└────────┬──────┘
|
|
│
|
|
┌──────▼────────────────┐
|
|
│ Precisa de ajuda? ────┼─→ Cria Human API request
|
|
│ Cliente quer humano? ─┼─→ Cria Escalação + Protocolo
|
|
└──────┬────────────────┘
|
|
│
|
|
┌──────▼──────────────┐
|
|
│ Inbox Interna │
|
|
│ (internal_messages)│
|
|
│ │
|
|
│ Colaborador lê ←──┤── Thread
|
|
│ Responde ──→┤── Mensagem
|
|
│ Encerra ←──┤── Reset handoff
|
|
└──────┬──────────────┘
|
|
│
|
|
┌──────▼────────────────┐
|
|
│ Resposta volta à IA │
|
|
│ IA continua conversa │
|
|
│ com cliente │
|
|
└───────────────────────┘
|
|
```
|
|
|
|
### Filtros (Abas)
|
|
|
|
- **Todos** — todas as threads abertas
|
|
- **Human API** — apenas pedidos de ajuda da IA
|
|
- **Escalação** — clientes que escalaram
|
|
- **Ajuda** — colaboradores pedindo suporte interno
|
|
- **Mensagem** — anotações de contexto
|
|
- **Sistema** — avisos automáticos
|
|
|
|
---
|
|
|
|
## 🔴 Lacunas Atuais (v1)
|
|
|
|
### ❌ Falta: Comunicação Livre entre Colaboradores
|
|
|
|
**Situação atual:**
|
|
- Só há threads de CONTEXTO (vinculadas a escalações/human API)
|
|
- Colaboradores não conseguem falar entre si sem um protocolo
|
|
- Sem forma de fazer DM privada, group chat por setor, ou broadcast
|
|
|
|
**Exemplos de uso que FALTAM:**
|
|
```
|
|
João: "Maria, qual é o status do pedido #456?"
|
|
(não há como enviar DM privada)
|
|
|
|
Secretária (broadcast): "Servidor em manutenção em 5 min!"
|
|
(não há como mandar aviso para todos)
|
|
|
|
Setor Financeiro: "Pessoal, cliente quer falar sobre boleto..."
|
|
(não há como falar só com o time do setor)
|
|
```
|
|
|
|
---
|
|
|
|
## 💡 Sugestão: Coluna de Colaboradores (v2)
|
|
|
|
### Análise da Sugestão ✅
|
|
|
|
**Layout proposto:**
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Abas: Todos | Human API | Escalação | Ajuda | ... │
|
|
├──────────────────┬──────────────────────────────────┐
|
|
│ COLABORADORES │ THREADS / CONTEXTO │
|
|
│ (Coluna) │ │
|
|
│ │ Protocolo #123 │
|
|
│ • João (online) │ ├─ Cliente: Fulano │
|
|
│ • Maria (busy) │ ├─ Setor: Secretária │
|
|
│ • Pedro (away) │ ├─ Última msg: há 2min │
|
|
│ • Carla (offline)│ └─ [Responder] [Encerrar] │
|
|
│ │ │
|
|
│ [+] Novo │ Protocolo #122 │
|
|
│ │ ├─ Tipo: Human API │
|
|
│ │ ├─ Pergunta: "Política..?" │
|
|
│ │ └─ [Responder] │
|
|
└──────────────────┴──────────────────────────────────┘
|
|
```
|
|
|
|
### Vantagens ✅
|
|
|
|
| Aspecto | Ganho |
|
|
|---------|-------|
|
|
| **Navegação rápida** | Clique em colaborador = DM privada |
|
|
| **Presença visual** | Cor indica online/busy/offline |
|
|
| **Unread badges** | Quantas DMs não lidas por pessoa |
|
|
| **Busca** | Filtrar colaboradores por nome |
|
|
| **Contexto duplo** | Ver threads E falar com pessoas |
|
|
| **Similar a Slack/WhatsApp** | UX familiar para usuários |
|
|
| **Iniciar conversa** | Botão [+] abre nova DM |
|
|
| **Gestão de setores** | Filter "mostrar só meu setor" |
|
|
|
|
### Desvantagens ⚠️
|
|
|
|
| Risco | Mitigation |
|
|
|-------|------------|
|
|
| **Coluna muitas pessoas** | Busca + virtualization se >50 pessoas |
|
|
| **Clutter na UI** | Coluna colapsável (toggle) |
|
|
| **Sem histórico persistente** | Arquitetar tabela `direct_messages` |
|
|
| **Sem notificações SSE** | Adicionar evento SSE `direct_message.new` |
|
|
|
|
---
|
|
|
|
## 🎯 Proposta de Implementação (v2)
|
|
|
|
### Fase 1: Estrutura de Dados
|
|
|
|
```sql
|
|
-- Threads de chat direto (novo tipo)
|
|
direct_messages {
|
|
id UUID PRIMARY KEY
|
|
tenant_id INT NOT NULL
|
|
from_account INT NOT NULL (FK → accounts.id)
|
|
to_account INT NOT NULL (FK → accounts.id) -- NULL = group chat
|
|
content TEXT NOT NULL
|
|
lida BOOLEAN DEFAULT false
|
|
created_at TIMESTAMP DEFAULT now()
|
|
}
|
|
|
|
-- Group chats por setor
|
|
group_chats {
|
|
id UUID PRIMARY KEY
|
|
tenant_id INT NOT NULL
|
|
sector_id INT NOT NULL (FK → sectors.id)
|
|
name VARCHAR NOT NULL
|
|
topic TEXT
|
|
created_at TIMESTAMP DEFAULT now()
|
|
}
|
|
|
|
group_chat_members {
|
|
id UUID PRIMARY KEY
|
|
group_chat_id UUID (FK → group_chats.id)
|
|
account_id INT (FK → accounts.id)
|
|
joined_at TIMESTAMP DEFAULT now()
|
|
}
|
|
```
|
|
|
|
### Fase 2: UI Layout
|
|
|
|
**Nova estrutura:**
|
|
```
|
|
├── Sidebar esquerdo
|
|
│ └─ COLABORADORES (coluna conversável)
|
|
│ ├─ [🔍 Buscar...]
|
|
│ ├─ 🟢 João (2 DMs não lidas)
|
|
│ ├─ 🟡 Maria (online)
|
|
│ ├─ ⚪ Pedro (away)
|
|
│ ├─ ⚫ Carla (offline)
|
|
│ └─ [+] Iniciar DM
|
|
│
|
|
└── Conteúdo principal
|
|
├─ Abas: Todos | Human API | Escalação | Ajuda | Mensagem | Sistema
|
|
└─ Threads de contexto (atuais)
|
|
```
|
|
|
|
### Fase 3: Funcionalidades
|
|
|
|
```
|
|
📌 DM Privada
|
|
- Clique em colaborador → abre chat
|
|
- Histórico persistente
|
|
- Marca como lido
|
|
|
|
👥 Group Chat por Setor
|
|
- Secretária, Financeiro, etc.
|
|
- Mensagens visíveis para todo o setor
|
|
- Notificação de @menção
|
|
|
|
📢 Broadcast
|
|
- Só owner/manager
|
|
- Aviso para TODOS os colaboradores
|
|
- "Sistema está em manutenção em 5 min"
|
|
|
|
🔔 Notificações SSE
|
|
- `direct_message.new` → atualiza badge
|
|
- `group_message.new` → notifica setor
|
|
- `broadcast.sent` → notifica todos
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Comparação: Atual vs Proposto
|
|
|
|
### Inbox Interna v1 (Atual)
|
|
|
|
```
|
|
Uso: Gerenciar escalações + ajuda da IA
|
|
Threads: Escalação, Human API, Ajuda, Sistema
|
|
Colaboradores: Implícitos (apenas quem responde)
|
|
Chat: Não há comunicação livre
|
|
Comunicação: Apenas REATIVA (resposta a eventos)
|
|
```
|
|
|
|
### Inbox Interna v2 (Proposto)
|
|
|
|
```
|
|
Uso: Escalações + IA + Chat interno + Broadcasts
|
|
Threads: Escalação, Human API, Ajuda, Sistema, DM, Group, Broadcast
|
|
Colaboradores: Listados na coluna, clickable
|
|
Chat: DMs privadas + Group por setor
|
|
Comunicação: Reativa + Proativa (falar entre si)
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 Priorização
|
|
|
|
| # | Feature | Complexidade | Impacto | Prioridade |
|
|
|---|---------|--------------|--------|-----------|
|
|
| 1 | **Coluna Colaboradores** | 🟡 Média | Alto | 🔴 **ALTA** |
|
|
| 2 | **DM Privada** | 🟢 Baixa | Muito Alto | 🔴 **ALTA** |
|
|
| 3 | **Group Chat por Setor** | 🟡 Média | Alto | 🟡 **MÉDIA** |
|
|
| 4 | **Broadcast** | 🟢 Baixa | Médio | 🟡 **MÉDIA** |
|
|
| 5 | **Notificações SSE** | 🟡 Média | Alto | 🔴 **ALTA** |
|
|
| 6 | **Busca/Filter** | 🟢 Baixa | Médio | 🟢 **BAIXA** |
|
|
|
|
---
|
|
|
|
## 📝 Implementação Concluída (Fase 1)
|
|
|
|
### ✅ Completados (2026-04-23)
|
|
|
|
Backend:
|
|
- [x] Tabela `direct_messages` criada com indexes
|
|
- [x] Endpoint: `POST /api/admin/inbox/direct-message` ← enviar DM
|
|
- [x] Endpoint: `GET /api/admin/inbox/direct/:otherAccountId` ← histórico
|
|
- [x] Endpoint: `GET /api/admin/inbox/direct-messages` ← últimas DMs
|
|
- [x] Endpoint: `GET /api/admin/inbox/colleagues` ← listar colaboradores
|
|
- [x] Endpoint: `PATCH /api/admin/inbox/direct/:messageId/read` ← marcar como lida
|
|
- [x] DirectMessage model com 6 métodos (send, getConversation, getLastMessages, getUnreadCount, markAsRead, getUnreadCountByContact)
|
|
- [x] DirectMessageService exportado em admin-app/src/services/api.ts
|
|
|
|
Frontend:
|
|
- [x] CollaboratorsPanel.tsx: coluna com busca, status, badges de não lida
|
|
- [x] DMConversationView.tsx: chat bubbles, input, auto-scroll
|
|
- [x] InboxInternaTab.tsx: integração two-column (Inbox + Colaboradores tabs)
|
|
- [x] Auto-load conversation quando abrir chat
|
|
- [x] Auto-mark-as-read ao abrir conversa
|
|
- [x] 30-segundo auto-refresh de colaboradores
|
|
|
|
Database:
|
|
```sql
|
|
direct_messages {
|
|
id SERIAL PRIMARY KEY,
|
|
tenant_id INT,
|
|
from_account INT,
|
|
to_account INT,
|
|
content TEXT,
|
|
read_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
}
|
|
-- Indexes: (tenant_id, from_to pairs, read_status, created_at DESC)
|
|
```
|
|
|
|
### 🔄 Próximos Passos
|
|
|
|
- [ ] SSE: adicionar evento `direct_message.new` para notificação real-time
|
|
- [ ] Group Chat por Setor (Fase 2)
|
|
- [ ] Broadcast para todos (Fase 2)
|
|
- [ ] Busca em conversas
|
|
- [ ] Pinning/Marking de mensagens importantes
|
|
|
|
---
|
|
|
|
## 🎨 Mockup
|
|
|
|
```
|
|
Inbox Interna v2 (esboço)
|
|
|
|
┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
┃ COLABORADORES ┃ [Todos] [Human API] [Escalação]... ┃
|
|
┣━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
┃ [🔍 Buscar...] ┃ ┃
|
|
┃ ┃ ┌────────────────────────────────┐ ┃
|
|
┃ 🟢 João 2 ┃ │ Protocolo #123 │ ┃
|
|
┃ 🟡 Maria 0 ┃ │ ├─ Cliente: Fulano Silva │ ┃
|
|
┃ ⚪ Pedro 1 ┃ │ ├─ Setor: Secretária │ ┃
|
|
┃ ⚫ Carla 0 ┃ │ ├─ Criado: há 15 min │ ┃
|
|
┃ ┃ │ ├─ Status: Aberto │ ┃
|
|
┃ [+] Iniciar DM ┃ │ └─ [Responder] [Encerrar] │ ┃
|
|
┃ ┃ └────────────────────────────────┘ ┃
|
|
┃ ┃ ┃
|
|
┃ ┃ ┌────────────────────────────────┐ ┃
|
|
┃ ┃ │ Human API Request │ ┃
|
|
┃ ┃ │ ├─ Pergunta: "Qual política..."│ ┃
|
|
┃ ┃ │ ├─ Setor: Financeiro │ ┃
|
|
┃ ┃ │ └─ [Responder] │ ┃
|
|
┃ ┃ └────────────────────────────────┘ ┃
|
|
┗━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
```
|
|
|
|
---
|
|
|
|
## ✅ Conclusão
|
|
|
|
**A sugestão da coluna de colaboradores é excelente** porque:
|
|
|
|
1. ✅ Resolve a lacuna de comunicação entre colaboradores
|
|
2. ✅ UX familiar (similar a Slack/WhatsApp)
|
|
3. ✅ Melhora discoverabilidade (ver quem está online)
|
|
4. ✅ Simples de implementar (coluna + nova tabela)
|
|
5. ✅ Impacto alto na experiência de colaboração
|
|
|
|
**Recomendação:** Implementar em **duas fases**:
|
|
- **Fase 1 (rápida)**: Coluna + DM privada + SSE
|
|
- **Fase 2 (depois)**: Group chat + broadcast
|
|
|
|
---
|
|
|
|
**Autor:** Claude
|
|
**Revisor:** Necessário
|
|
**Status:** Draft para aprovação
|