# 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_id` para evitar processar a mesma mensagem mais de uma vez. Fluxo de decisão: 1. Se a mensagem já contém uma intenção clara, o Omnino roteia direto para a especialidade. 2. Se a primeira mensagem é genérica, o Omnino envia a saudação completa e mantém a conversa em `bot_triage`. 3. Se a segunda mensagem ainda não identifica intenção, o Omnino pede explicitamente: suporte, financeiro ou comercial. 4. 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_triage` não aparecem para agentes. - Conversas em `queued` aparecem para usuários da especialidade. - Conversas em `assigned` continuam 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_id` passa 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_at` e `expires_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: ```text Atendente: Nome do Usuário Mensagem ``` No WhatsApp, essa identificação é enviada usando negrito: ```text *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: ```http GET /whatsapp/media/:chatId/:messageId ``` ### Limites de upload O backend aceita JSON até `25mb` por padrão, configurável via: ```env 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: ```text 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: ```text whatsapp_templates ``` Campos relevantes: - `name` - `content` - `area_id` - `status` - `requested_by_role` - `admin_approved_at` - `meta_submitted_at` - `meta_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: ```http 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: ```env 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 ### WhatsApp ```http 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 ```http 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 ```http 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 ```text 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: ```bash docker compose up -d --build ``` Também é possível rodar frontend e backend em modo desenvolvimento: ```bash cd backend npm install npm run dev ``` ```bash 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: ```env 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: ```env 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 `/chat` deve 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_triage` nã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.