diff --git a/README.md b/README.md index 7417b7e..50103bf 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,544 @@ -# Omnichannel Sothis - Deploy +# Omnichannel Sothis -Este repositorio e o **deploy** do ecossistema. Ele **nao** contem o codigo do frontend nem do backend em producao. Esses dois sao repositorios separados e devem ser clonados ao lado deste deploy para subir o ambiente completo. +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. -## Estrutura esperada (3 repositorios) +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. -- `deploy/` (este repo): `docker-compose.yml`, `database/`, `.gitignore`, `README.md` -- `frontend/`: interface do produto -- `backend/`: API e regras de negocio +## Estado Atual do Produto -## Como subir tudo localmente +O produto hoje permite: -Passo a passo (na mesma pasta raiz): +- 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. -1. Clonar o repo de deploy na raiz (.) -2. Clonar o repo de frontend na pasta `frontend` -3. Clonar o repo de backend na pasta `backend` -4. Subir tudo: +## 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 ``` -Isso sobe `frontend`, `backend` e `database` em uma unica operacao. +Também é possível rodar frontend e backend em modo desenvolvimento: -## Observacoes +```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. -- O `docker-compose.yml` deste repo espera `frontend/` e `backend/` presentes na mesma raiz. -- Em producao, o fluxo pode mudar para imagens pre-buildadas, mas para desenvolvimento local esta estrutura funciona bem.