| backend@8790ce70d0 | ||
| database | ||
| docs | ||
| frontend@7dc07c2a80 | ||
| .env.example | ||
| .gitignore | ||
| deploy-dev.bat | ||
| docker-compose.yml | ||
| README.md | ||
Omnichannel Sothis
Plataforma omnichannel para atendimento com foco inicial em WhatsApp, autenticação corporativa, controle de acesso por perfil, filas por especialidade, agenda de contatos, templates de mensagens e painéis operacionais para agente, supervisor e administrador.
Este repositório é a raiz do ambiente local/deploy. Ele contém o docker-compose.yml, as migrations de banco em database/ e espera os projetos frontend/ e backend/ clonados ou presentes na mesma pasta.
Estado Atual do Produto
O produto hoje permite:
- Login via Active Directory/LDAP e Microsoft OAuth.
- Redirecionamento da Home conforme perfil do usuário.
- Atendimento WhatsApp em tempo real com socket.
- Triagem automática inicial pelo Omnino.
- Fila de atendimento por especialidade.
- Assumir, liberar e transferir atendimentos.
- Controle da janela de 24 horas do WhatsApp.
- Envio e recebimento de texto, imagem, vídeo, áudio e documentos.
- Lazy loading de mídias históricas.
- Agenda geral de contatos.
- Novo atendimento ativo via templates aprovados.
- Notas pessoais do atendente.
- Administração de usuários, perfis e especialidades.
- Workflow de criação, aprovação, reprovação e exclusão de templates.
- Painel mensal do admin e painel operacional do supervisor.
Perfis e Acesso
Usuário sem perfil
Quando um usuário autentica pela primeira vez e ainda não tem perfil/especialidade definida, ele cai em uma tela vazia informando que não está atribuído a uma área/perfil.
A liberação desse usuário é feita no painel do admin em Usuários & Acessos.
Agente
O agente:
- Vê somente atendimentos das especialidades em que está vinculado.
- Pode ver chamados da especialidade enquanto estão na fila.
- Só pode responder depois de assumir o atendimento.
- Pode liberar um atendimento para voltar para a fila.
- Pode transferir atendimento somente depois de assumir.
- Pode transferir para outra especialidade ou para outro usuário elegível.
- Pode editar/salvar contato na agenda.
- Pode criar notas pessoais.
- Pode abrir novo atendimento usando template aprovado.
Supervisor
O supervisor:
- Acessa a Home operacional da supervisão.
- Vê indicadores e filas das especialidades que supervisiona.
- Pode usar templates, base de conhecimento, auditoria, atendimento, abrir atendimento, disparo em massa e contatos.
- Pode solicitar novos templates, mas eles entram primeiro em aprovação do admin.
Admin
O admin:
- Não precisa pertencer a uma especialidade.
- Vê todas as filas e todos os atendimentos já roteados/classificados.
- Não vê conversas ainda em triagem automática do Omnino (
bot_triage). - Cria e gerencia especialidades.
- Define perfis de usuários.
- Pode tornar outro usuário admin.
- Pode definir se um usuário atua como agente ou supervisor em especialidades.
- Pode aprovar, reprovar e excluir templates.
- Acessa a visão mensal administrativa.
- Também pode atender, usando o menu administrativo.
Regras de Atendimento WhatsApp
Triagem automática pelo Omnino
Toda primeira mensagem recebida no WhatsApp passa pela triagem automática do Omnino quando ainda não existe atendimento classificado.
Regras atuais:
- Mensagens vazias são registradas, mas não disparam triagem.
- Mídia sem legenda é registrada, mas não aciona o Omnino automaticamente.
- A triagem é serializada por conversa para evitar respostas duplicadas quando o WhatsApp dispara eventos quase simultâneos.
- O backend guarda
last_routed_message_idpara evitar processar a mesma mensagem mais de uma vez.
Fluxo de decisão:
- Se a mensagem já contém uma intenção clara, o Omnino roteia direto para a especialidade.
- Se a primeira mensagem é genérica, o Omnino envia a saudação completa e mantém a conversa em
bot_triage. - Se a segunda mensagem ainda não identifica intenção, o Omnino pede explicitamente: suporte, financeiro ou comercial.
- Se a terceira mensagem ainda for inválida, a conversa cai automaticamente em Suporte.
Exemplos de intenção:
- Suporte: suporte, bug, problema, técnico.
- Financeiro: boleto, dinheiro, cartão, atraso, fatura.
- Comercial: produto, novo, contratar, proposta.
Estados do atendimento
A tabela whatsapp_chat_atribuicoes representa o estado do atendimento:
bot_triage: conversa ainda está com o Omnino.queued: conversa está na fila da especialidade, sem atendente.assigned: conversa foi assumida ou atribuída diretamente a um atendente.
Regras:
- Conversas em
bot_triagenão aparecem para agentes. - Conversas em
queuedaparecem para usuários da especialidade. - Conversas em
assignedcontinuam visíveis para a especialidade, mas só o responsável responde. - Admin vê todas as conversas roteadas, exceto
bot_triage.
Assumir, liberar e transferir
Para responder um chamado, o usuário precisa assumir o atendimento.
- Ao assumir,
user_idpassa a ser o usuário atual. - Ao liberar, o atendimento volta para fila da especialidade.
- Transferência só fica disponível depois que o usuário assume.
- Transferência para a mesma especialidade pode apontar para outro usuário.
- Transferência para outra especialidade cai na fila da nova especialidade.
- A observação da transferência fica visível para o próximo atendente e é limpa depois que o atendimento é respondido.
Janela de 24 horas
O produto respeita a regra operacional do WhatsApp:
- Conversas têm uma janela de 24 horas representada por
conversation_started_ateexpires_at. - Ao abrir atendimento ativo para um cliente, o atendente deve usar template aprovado.
- Depois do primeiro contato ativo, o atendimento fica bloqueado para novas mensagens livres até o cliente responder.
- Quando o cliente responde, o bloqueio
awaiting_customer_replyé removido e o atendente pode seguir a conversa.
Mensagens e Mídias
Envio de mensagens
Mensagens enviadas por atendente são formatadas com identificação:
Atendente: Nome do Usuário
Mensagem
No WhatsApp, essa identificação é enviada usando negrito:
*Atendente: Nome do Usuário*
Mensagem
Se uma mídia for enviada sem texto, o backend não envia cabeçalho solto. A mídia segue sem legenda.
Recebimento de mídias
Tipos suportados:
- Imagens: PNG, JPG, JPEG, WEBP.
- Vídeos: MP4, WEBM.
- Áudios: MP3, OGG, WAV.
- Documentos: exibidos como card de arquivo.
Para preservar performance, o histórico de mensagens não carrega Base64 de mídia diretamente. O frontend busca a mídia sob demanda pelo endpoint:
GET /whatsapp/media/:chatId/:messageId
Limites de upload
O backend aceita JSON até 25mb por padrão, configurável via:
REQUEST_BODY_LIMIT=25mb
O frontend bloqueia anexos acima de 15 MB para evitar falhas de payload e degradação da experiência.
Chat
A tela /chat exibe somente conversas reais vindas do backend/WhatsApp. Não existe mais fallback de conversas mockadas.
Recursos atuais:
- Lista de conversas ativas com scroll.
- Chat com altura delimitada e scroll interno.
- Separador de datas nas mensagens.
- Horário por mensagem.
- Deduplicação visual de mensagens enviadas localmente e confirmadas por socket.
- Ocultação de mensagens vazias.
- Botão para assumir atendimento.
- Botão para sair do atendimento.
- Transferência de atendimento.
- Painel de contato do cliente.
- Envio de mídia.
Indicadores na lista:
- Bolinha amarela: chamado está na fila da especialidade e ainda não foi atribuído.
- Bolinha azul: chamado está atribuído ao usuário atual.
- Bolinha vermelha: chamado está atribuído a outra pessoa.
- Badge de especialidade: mostra para qual fila o chamado foi roteado.
- Ícone de contato: indica que o contato está salvo na agenda.
Home do Agente
A Home do agente usa dados reais do chat quando o WhatsApp está conectado.
Recursos atuais:
- Últimos atendimentos.
- Preview do chat com scroll automático para a última mensagem.
- Respostas sugeridas baseadas no contexto.
- Envio da resposta sugerida direto para o chat correto.
- Comunicados e notas.
- Notas pessoais persistidas por usuário.
- Relógio/data em tempo real.
- Atalhos para scripts, relatórios pessoais, disparo em massa e base de conhecimento.
Novo Atendimento
A tela /new-attendance permite iniciar contato ativo.
Regras:
- WhatsApp é o canal funcional.
- Email e SMS aparecem bloqueados como funcionalidades em construção.
- O atendente pode buscar contatos da agenda.
- Também pode digitar novo número, nome, empresa e observação.
- O telefone tem máscara e seletor de país.
- Países disponíveis atualmente: Brasil, EUA, Argentina, Chile e México.
- O primeiro contato ativo exige seleção de template aprovado.
- Ao iniciar atendimento, o sistema salva/atualiza o contato na agenda e abre o chat daquela conversa.
Agenda de Contatos
A agenda é geral, não vinculada a uma especialidade específica.
Tabela principal:
agenda_contatos
Campos funcionais:
- Nome.
- Empresa.
- Telefone.
- Observação.
- Chat ID.
- Usuário que criou/atualizou.
Na conversa, o telefone não é editável quando vem do WhatsApp, mas nome, empresa e observação podem ser atualizados.
Templates WhatsApp
Templates ficam na tabela:
whatsapp_templates
Campos relevantes:
namecontentarea_idstatusrequested_by_roleadmin_approved_atmeta_submitted_atmeta_approved_at
Status atuais:
approved: template aprovado e disponível para uso.meta_review: enviado para aprovação da Meta.admin_review: aguardando aprovação do admin.rejected: reprovado pelo admin.
Regras:
- Admin cria template e envia para aprovação.
- Supervisor cria template, mas ele entra em aprovação do admin.
- Admin pode aprovar e enviar para Meta.
- Admin pode reprovar.
- Admin pode excluir.
- A aprovação da Meta é simulada: templates em análise são aprovados automaticamente depois de um intervalo configurado no código.
- A listagem possui filtro por especialidade e scroll para não ocupar a página inteira.
Painel Admin
A Home do admin é uma visão mensal.
Recursos atuais:
- Filtro por especialidade no topo.
- KPIs mensais.
- Total de atendimentos.
- Tempo médio.
- TME.
- TMR.
- Satisfação.
- Atendentes ativos.
- Gráfico de atendimentos por dia.
- Donut de distribuição por canal.
- Ranking de atendentes.
- Painel de avisos.
- Menu administrativo lateral.
Menu atual:
- Home.
- Operação.
- Usuários & Acessos.
- Templates.
- Base de conhecimento IA.
- Auditoria.
- Canais.
- Atendimento.
- Abrir Atendimento.
- Disparo em Massa.
- Contatos.
- Configurações.
- Sair.
Usuários & Acessos
Tela administrativa para usuários, perfis e especialidades.
Regras atuais:
- Usuários vêm do banco/autenticação, não de mock.
- Admin Demo, Supervisor Demo e Atendente Demo foram removidos por migration.
- Admin pode editar um usuário em modal.
- Se o usuário for admin, não há seleção de especialidades.
- Se não for admin, é possível vincular múltiplas especialidades.
- Para cada especialidade, o usuário pode atuar como agente ou supervisor.
- A criação/edição de especialidades é feita pelo admin.
- A definição de supervisores agora ocorre no vínculo do usuário, não dentro da especialidade.
Painel Supervisor / Operação
O painel de supervisor também é usado como visão de operação no menu do admin.
Recursos atuais:
- Filtro por especialidade.
- KPIs do dia.
- Atendimentos finalizados.
- Atendimentos em aberto.
- Conversas na fila.
- Tempo médio do dia.
- Atendentes online simulados.
- Painel do time.
- Fila de espera.
- Atribuição mockada via modal.
- Gráfico do dia por hora.
Sempre que há dado real disponível, a tendência do produto é substituir mock por dado real. Indicadores sem origem real consolidada ainda usam dados simulados.
Autenticação
Endpoints principais:
GET /auth/config
POST /auth/login
GET /auth/oauth/microsoft/start
GET /auth/oauth/microsoft/callback
Providers suportados:
- LDAP/Active Directory.
- Microsoft OAuth.
Variáveis relevantes:
AUTH_PROVIDERS=ldap,microsoft
LDAP_ENABLED=true
LDAP_URL=ldaps://...
LDAP_DOMAIN=...
MICROSOFT_ENABLED=false
MICROSOFT_TENANT_ID=common
MICROSOFT_CLIENT_ID=
MICROSOFT_CLIENT_SECRET=
Endpoints Principais
GET /whatsapp/status
GET /whatsapp/chats
GET /whatsapp/messages/:chatId
GET /whatsapp/media/:chatId/:messageId
POST /whatsapp/send
POST /whatsapp/start-attendance
POST /whatsapp/assign
POST /whatsapp/transfer
DELETE /whatsapp/release/:chatId
GET /whatsapp/assignment/:chatId
Templates
GET /whatsapp/templates
POST /whatsapp/templates
POST /whatsapp/templates/update/:id
POST /whatsapp/templates/approve-admin/:id
POST /whatsapp/templates/reject-admin/:id
DELETE /whatsapp/templates/:id
Admin / Acessos
GET /admin/access/options
GET /admin/access/overview
GET /admin/access/areas
POST /admin/access/areas
PUT /admin/access/areas/:id
GET /admin/access/users
PUT /admin/access/users/:id
Banco de Dados
Migrations principais:
005_templates.sql: criação inicial de templates.006_whatsapp_assignment_queue.sql: fila e atribuição de WhatsApp.007_whatsapp_triage_state.sql: estado de triagem automática.008_agent_notes.sql: notas pessoais do atendente.009_customer_contacts.sql: primeira versão de contatos.010_agenda_contatos.sql: agenda geral consolidada.011_whatsapp_opening_templates.sql: templates de abertura ativa.012_whatsapp_awaiting_customer_reply.sql: bloqueio até resposta do cliente.013_remove_demo_access_users.sql: remoção de usuários demo.014_whatsapp_template_workflow.sql: workflow de aprovação de templates.
Estrutura do Repositório
omnichannel/
├── backend/ # API NestJS e regras de negócio
├── frontend/ # Interface React/Vite
├── database/migrations/ # Migrations SQL
├── docker-compose.yml # Orquestração local
├── .env.example # Exemplo de variáveis
└── README.md
Como Subir Localmente
Pré-requisitos:
- Node.js compatível com os projetos.
- Docker e Docker Compose.
- PostgreSQL via
docker-compose.
Na raiz:
docker compose up -d --build
Também é possível rodar frontend e backend em modo desenvolvimento:
cd backend
npm install
npm run dev
cd frontend
npm install
npm run dev
URLs locais comuns:
- Frontend:
http://localhost:5173 - Backend:
http://localhost:3001 - Status WhatsApp:
http://localhost:3001/whatsapp/status
Variáveis de Ambiente
Principais variáveis da raiz:
POSTGRES_USER=omnichannel
POSTGRES_PASSWORD=change-me
POSTGRES_DB=omnichannel
DB_HOST=postgres
DB_PORT=5432
DB_USER=omnichannel
DB_PASSWORD=change-me
DB_NAME=omnichannel
PORT=3001
FRONTEND_URL=http://localhost:3000
JWT_SECRET=change-this-long-random-secret
JWT_EXPIRES_IN=8h
REQUEST_BODY_LIMIT=25mb
No frontend, a URL da API deve vir de:
VITE_API_URL=http://localhost:3001
Limitações Conhecidas
- O WhatsApp Web carrega conversas por lazy loading. Nem sempre todo histórico aparece imediatamente após conectar o QR Code.
- O status real de presença do contato foi removido por limitação prática da biblioteca/WhatsApp Web.
- O painel de supervisor ainda possui indicadores simulados onde não há métrica real consolidada.
- Email, SMS e ligação não estão operacionais como canais de atendimento.
- A aprovação da Meta para templates é simulada.
- Mídias ainda trafegam via Base64 no JSON; para produção, o ideal é evoluir para upload/armazenamento próprio e envio por referência.
Regras Importantes Para Desenvolvimento
- Não reintroduzir mock de conversas no chat. O
/chatdeve exibir apenas conversas reais vindas do backend/WhatsApp. - Toda alteração de banco deve virar nova migration numerada.
- Não permitir resposta sem atendimento assumido.
- Não permitir transferência sem atendimento assumido.
- Conversas em
bot_triagenão devem aparecer para agentes. - Admin pode ver todas as filas e atendimentos roteados.
- Novo atendimento ativo deve usar template aprovado.
- Depois de contato ativo, bloquear novas mensagens livres até resposta do cliente.
- Mídia sem texto não deve enviar cabeçalho solto de atendente.