From f55e823e61a79d828254632be25160877282cbfc Mon Sep 17 00:00:00 2001 From: Rafael Lopes Date: Wed, 27 May 2026 15:28:06 -0300 Subject: [PATCH] =?UTF-8?q?DOCS:=20Atualizado=20a=20documenta=C3=A7=C3=A3o?= =?UTF-8?q?=20do=20Omnichannel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 38 ++- README.md | 598 ++++++++---------------------------------- docker-compose.yml | 22 -- docs/chat-whatsapp.md | 78 ------ 4 files changed, 130 insertions(+), 606 deletions(-) delete mode 100644 docs/chat-whatsapp.md diff --git a/.env.example b/.env.example index 5f7d33b..41e33ea 100644 --- a/.env.example +++ b/.env.example @@ -1,40 +1,38 @@ # Deploy (docker-compose) environment variables - -# Postgres (used by postgres service) -POSTGRES_USER=omnichannel -POSTGRES_PASSWORD=change-me -POSTGRES_DB=omnichannel +# +# Docker Compose sobe somente frontend e backend. +# O PostgreSQL deve existir fora do compose, em uma instancia local, VM, RDS, +# container separado ou banco corporativo. # App database connection (used by backend) -DB_HOST=postgres +DB_HOST=db.empresa.local DB_PORT=5432 DB_USER=omnichannel DB_PASSWORD=change-me DB_NAME=omnichannel -# Ports (optional, if you want to reference in compose later) -FRONTEND_PORT=3000 -BACKEND_PORT=3001 - # Backend HTTP/JWT +NODE_ENV=development PORT=3001 -FRONTEND_URL=http://localhost:3000 +FRONTEND_URL=http://localhost:4000 JWT_SECRET=change-this-long-random-secret JWT_EXPIRES_IN=8h +REQUEST_BODY_LIMIT=25mb # Auth providers: ldap,microsoft or only one of them AUTH_PROVIDERS=ldap,microsoft # LDAP / Active Directory LDAP_ENABLED=true -LDAP_URL=ldaps://kratos.sothistelecom.com:636 -LDAP_DOMAIN=sothis.com.br -# Alternative when the bind user is not username@domain: -LDAP_USER_DN_TEMPLATE={{username}}@sothis.com.br -# Optional search to enrich the authenticated profile: -LDAP_SEARCH_BASE=DC=sothistelecom,DC=com +LDAP_URL=ldaps://servidor-ad:636 +LDAP_DOMAIN=empresa.com.br +LDAP_USER_DN_TEMPLATE={{username}}@empresa.com.br +LDAP_SEARCH_BASE=DC=empresa,DC=com LDAP_SEARCH_FILTER=(&(objectClass=user)(sAMAccountName={{username}})) -# LDAP_BIND_DN=CN=ldap-reader,OU=Users,DC=example,DC=com +LDAP_TIMEOUT_MS=5000 + +# Optional LDAP bind account when search requires service credentials +# LDAP_BIND_DN=CN=ldap-reader,OU=Users,DC=empresa,DC=com # LDAP_BIND_PASSWORD=change-me # Microsoft Entra ID OAuth @@ -42,5 +40,5 @@ MICROSOFT_ENABLED=false MICROSOFT_TENANT_ID=common MICROSOFT_CLIENT_ID= MICROSOFT_CLIENT_SECRET= -MICROSOFT_REDIRECT_URI=http://localhost:3001/auth/oauth/microsoft/callback -MICROSOFT_SUCCESS_REDIRECT_URL=http://localhost:3000/login +MICROSOFT_REDIRECT_URI=http://localhost:4001/auth/oauth/microsoft/callback +MICROSOFT_SUCCESS_REDIRECT_URL=http://localhost:4000/login diff --git a/README.md b/README.md index 74d016d..bf52214 100644 --- a/README.md +++ b/README.md @@ -1,478 +1,99 @@ # 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. +Plataforma omnichannel para atendimento com foco inicial em WhatsApp. O sistema combina atendimento em tempo real, Agente Virtual para triagem, filas por especialidade, abertura ativa por template, agenda de contatos, painéis operacionais e administração de usuários/perfis. -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. +O projeto foi construído para validar e evoluir um MVP de atendimento corporativo, com perfis de agente, supervisor e administrador. -## Estado Atual do Produto +## Principais Recursos -O produto hoje permite: +- Login corporativo via LDAP/Active Directory. +- Estrutura para Microsoft OAuth / Entra ID. +- JWT próprio da aplicação com perfis e especialidades. +- Atendimento WhatsApp em tempo real via `whatsapp-web.js`. +- Socket.IO para atualização de chats/mensagens. +- Agente Virtual Sothis para triagem e roteamento. +- Fila por especialidade. +- Assumir, liberar, transferir e fechar atendimento. +- Abertura ativa com templates aprovados. +- Agenda de contatos com WhatsApp, telefone/SMS, email, etiqueta e observação. +- Painel do agente. +- Painel operacional do supervisor. +- Painel administrativo com usuários, acessos, templates, IA, canais e configurações. +- Conteúdos da IA e regras/travas. +- Migrations SQL versionadas. -- 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 Agente Virtual Sothis. -- 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. +## Stack Técnica -## Perfis e Acesso +### Backend -### Usuário sem perfil +- Node.js 20+ recomendado. +- NestJS `^11.1`. +- TypeScript `^6.0`. +- PostgreSQL via `pg`. +- Socket.IO `^4.8`. +- `whatsapp-web.js` `^1.34`. +- LDAP via `ldapts`. +- JWT via `jsonwebtoken`. +- Logs com `winston`. -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. +### Frontend -A liberação desse usuário é feita no painel do admin em `Usuários & Acessos`. +- React `^18.3`. +- Vite `^5.4`. +- React Router `^6.30`. +- Socket.IO Client `^4.8`. -### Agente +### Banco -O agente: +- PostgreSQL 16 recomendado. +- O banco não é gerenciado pelo `docker-compose.yml` deste repositório. +- As migrations ficam em `database/migrations`. -- 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. +### Docker -### Supervisor +O Docker Compose da raiz sobe somente: -O supervisor: +- `backend` +- `frontend` -- 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 Agente Virtual Sothis (`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 Agente Virtual Sothis - -Toda primeira mensagem recebida no WhatsApp passa pela triagem automática do Agente Virtual Sothis 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 Agente Virtual Sothis 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 Agente Virtual Sothis roteia direto para a especialidade. -2. Se a primeira mensagem é genérica, o Agente Virtual Sothis 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 Agente Virtual Sothis 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 Agente Virtual Sothis. -- `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 fallback local de conversas. - -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. -- 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 via modal. -- Gráfico do dia por hora. - -Sempre que há dado operacional disponível, os painéis usam a origem real consolidada. Indicadores sem origem consolidada ainda usam dados de apoio para compor a visão. - -## 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. +O banco deve ser externo ao compose: VM, banco corporativo, RDS, container separado ou PostgreSQL local gerenciado fora deste projeto. ## Estrutura do Repositório -```text +```txt 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 +├── docs/ # Wiki operacional e arquitetura +├── docker-compose.yml # Sobe backend e frontend └── README.md ``` -## Como Subir Localmente +## Como Subir com Docker Compose -Pré-requisitos: - -- Node.js compatível com os projetos. -- Docker e Docker Compose. -- PostgreSQL via `docker-compose`. - -Na raiz: +1. Configure `.env.development` na raiz com os dados do banco externo. +2. Garanta que o PostgreSQL externo esteja acessível a partir do container backend. +3. Suba backend e frontend: ```bash docker compose up -d --build ``` -Também é possível rodar frontend e backend em modo desenvolvimento: +URLs padrão: + +- Frontend: `http://localhost:4000` +- Backend: `http://localhost:4001` + +Health: + +```bash +curl http://localhost:4001/health +``` + +## Como Rodar em Desenvolvimento + +Backend: ```bash cd backend @@ -480,66 +101,71 @@ npm install npm run dev ``` +Frontend: + ```bash cd frontend npm install npm run dev ``` -URLs locais comuns: +URLs comuns: -- Frontend: `http://localhost:5173` +- Frontend Vite: `http://localhost:5173` - Backend: `http://localhost:3001` -- Status WhatsApp: `http://localhost:3001/whatsapp/status` -## Variáveis de Ambiente +## Banco e Migrations -Principais variáveis da raiz: +As migrations SQL estão em: -```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 +```txt +database/migrations ``` -No frontend, a URL da API deve vir de: +Elas representam a intenção de schema final/evolutivo do produto, mas o projeto ainda precisa de um runner formal para aplicar tudo em ordem em ambientes novos. -```env -VITE_API_URL=http://localhost:3001 -``` +Para ambiente novo, antes de subir backend para uso real: -## Limitações Conhecidas +1. criar o banco PostgreSQL; +2. aplicar as migrations em ordem; +3. validar tabelas principais; +4. criar/atribuir usuário admin; +5. subir backend e frontend. -- 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. +Detalhes em: -## Regras Importantes Para Desenvolvimento +- [Deploy e operação](./docs/deploy.md) +- [Database](./backend/docs/database.md) -- Não reintroduzir fallback local 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. +## Documentação +Wiki raiz: +- [docs/README.md](./docs/README.md) +- [Deploy e operação](./docs/deploy.md) +- [Arquitetura geral](./docs/arquitetura.md) +- [Fluxos end-to-end](./docs/fluxos-end-to-end.md) +- [Regras de negócio](./docs/regras-negocio.md) +- [ADRs](./docs/adrs.md) +- [Ambientes](./docs/ambientes.md) +- [Runbook](./docs/runbook.md) + +Backend: + +- [backend/docs/README.md](./backend/docs/README.md) +- [Auth](./backend/docs/auth.md) +- [WhatsApp](./backend/docs/whatsapp.md) +- [Admin](./backend/docs/admin.md) +- [Swagger/OpenAPI](./backend/docs/swagger.md) + +## Estado Atual e Próximos Passos + +O produto já foi validado em demo com cliente final. Antes de produção real, os principais fechamentos são: + +- implementar guards JWT no backend; +- validar autorização por perfil no backend; +- formalizar runner de migrations; +- configurar backup/restore do banco externo; +- persistir sessão WhatsApp em volume; +- criar Swagger com DTOs; +- adicionar testes nos fluxos críticos. diff --git a/docker-compose.yml b/docker-compose.yml index 52bfe12..79b36fa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,25 +14,3 @@ services: - "4001:3001" env_file: - .env.development - depends_on: - postgres: - condition: service_healthy - - postgres: - image: postgres:16-alpine - restart: always - env_file: - - .env.development - ports: - - "5434:5432" - volumes: - - pgdata:/var/lib/postgresql/data - - ./database/init:/docker-entrypoint-initdb.d - healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"] - interval: 5s - timeout: 5s - retries: 5 - -volumes: - pgdata: diff --git a/docs/chat-whatsapp.md b/docs/chat-whatsapp.md deleted file mode 100644 index be60961..0000000 --- a/docs/chat-whatsapp.md +++ /dev/null @@ -1,78 +0,0 @@ -# Arquitetura e Integracao do Modulo WhatsApp (Omnichannel) - -## Visao Geral do Sistema - -Este documento descreve a arquitetura de alto nivel do modulo de **WhatsApp** integrado ao ecossistema **Sothis Omnichannel**. A solucao une uma interface web moderna de atendimento, uma API NestJS robusta e o controle nativo do WhatsApp Web via automacao e WebSockets em tempo real. - ---- - -## Diagrama de Fluxo e Integracao - -O fluxo de comunicacao entre os diferentes componentes do ecossistema e estruturado conforme o diagrama a seguir: - -```mermaid -graph TD - %% Componentes - FE[Frontend - React/Vite] - BE[Backend - NestJS] - DB[(Banco PostgreSQL)] - PERSIST[(Persistencia JSON Local)] - PUPP[Puppeteer Client - WhatsApp Web] - WPP[Servidores do WhatsApp] - - %% Relacionamentos do Frontend - FE <-->|WebSockets: Socket.io| BE - FE -->|HTTP: Enviar Mensagem / Atribuir / Liberar| BE - - %% Relacionamentos do Backend - BE <-->|Transacoes SQL| DB - BE <-->|Leitura/Escrita Cache| PERSIST - BE <-->|Automacao de Headless Chrome| PUPP - - %% WhatsApp Web - PUPP <-->|Sincronizacao Nativa| WPP -``` - ---- - -## Divisao de Responsabilidades - -### 1. Frontend (Interface Operacional) -* **Visualizacao**: Renderiza o historico de bolhas de mensagens e arquivos de midia (imagens, audios, anexos). -* **Posse de Chat (Ownership)**: Permite ao operador assumir chats livres (`takeChat`) ou libera-los (`releaseChat`), aplicando travas visuais se a conversa estiver sob a posse de outro colaborador. -* **UX Ininterrupta**: Aplica de-duplicação temporal em milissegundos e cria bolhas locais com ID temporario antes do disparo de rede para garantir experiencia livre de lag. - -### 2. Backend (Orquestracao e Integracao) -* **Automacao (whatsapp-web.js)**: Carrega o headless Chrome (via Puppeteer), autentica a sessao por QR Code, inicializa o cliente e gerencia reconexoes. -* **Transmissao em Tempo Real**: Escuta eventos de mensagem (`message_create`) do Puppeteer, formata o payload (com suporte a midias baixadas e resolucao inteligente de nomes) e distribui via Socket.io Gateway para a interface do atendente. -* **Processamento Pesado**: Aceita payloads de midia em Base64 de ate 50MB no canal de entrada para evitar falhas de upload. - -### 3. Banco de Dados PostgreSQL (Persistencia Transacional) -* **Controle de Atribuicoes**: A tabela `whatsapp_chat_atribuicoes` atua como fonte unica da verdade (*Single Source of Truth*) para posse de atendimento. -* **Chaves Estrangeiras**: Vincula transacionalmente o ID do chat (`chat_id`) com chaves numericas de usuarios (`user_id`) e setores operacionais (`area_id`). - -### 4. Cache JSON Local (whatsapp-chats-persist.json) -* **Performance de Listagem**: Evita multiplas consultas a servidores de rede locais ou API do WhatsApp na listagem inicial de chats operacionais. -* **Historico e previews**: Armazena carimbos de tempo (timestamps), contadores de nao lidas e previews de midia de forma otimizada. - ---- - -## Casos de Uso Principais - -### A. Assumir Chat Automaticamente ao Enviar Mensagem -1. O operador envia uma mensagem em uma conversa livre. -2. O frontend verifica se o chat esta sem dono e faz um POST para `/whatsapp/assign`. -3. O backend insere na tabela `whatsapp_chat_atribuicoes` o ID do atendente e o ID numerico de sua respectiva area de trabalho. -4. A transacao e confirmada. O frontend atualiza a UI marcando o operador como dono e libera o canal de conversacao. - -### B. Envio e Recebimento de Midias -1. O cliente envia uma imagem pelo WhatsApp. -2. O Puppeteer no backend detecta a mensagem com midia e baixa seus bytes em tempo real. -3. O backend emite via socket os metadados e os bytes brutos (`mimetype`, `data` em base64, `filename`). -4. O frontend identifica a presenca da midia e renderiza o player de audio, imagem ou link de download de forma nativa e estetica. - ---- - -## Politicas de Segurança e Versionamento -* As pastas de sessoes (`/whatsapp-session`), arquivos locais de persistencia JSON e logs de desenvolvimento estao estritamente declarados nos arquivos `.gitignore` para nao serem expostos nos repositorios Git. -* Credenciais de banco residem exclusivamente em arquivos `.env.*` mantidos fora do controle de versao.