← story.propek
STORY 9.11
CRM Customer Management
Epic: Epic 9 — CRM Database Foundation
DONE
ACCEPTANCE CRITERIA (0/26)
AC1.1: Botao "Novo Cliente" visivel no topo da pagina de listagem de clientes (`/clientes`), ao lado do campo de busca ou em posicao de destaque similar.
AC1.2: Ao clicar no botao, abrir um modal ou drawer inline com formulario de criacao.
AC1.3: Formulario contem EXATAMENTE os campos: **Nome** (contact_name, obrigatorio) e **Telefone** (phone_number, obrigatorio). Nenhum outro campo e obrigatorio na criacao.
AC1.4: Validacao minima no frontend: nome nao pode ser vazio; telefone deve ter pelo menos 10 digitos numericos.
AC1.5: Submit chama `POST /api/crm/customers` no backend com `{ contact_name, phone_number }`.
AC1.6: Backend cria o registro na tabela `customers` com os campos obrigatorios. Campos nao informados ficam NULL. `status` default = `'active'`, `customer_type` default = `'b2c'` (pode ser ajustado pelo atendente depois).
AC1.7: Apos criacao com sucesso, o frontend redireciona automaticamente para a Ficha 360 do cliente recen-criado: `/clientes/{new_id}`.
AC1.8: Se erro de criacao (ex: telefone duplicado), exibir mensagem de erro clara para o atendente. Nao redirecionar.
AC1.9: Backend retorna `{ customer }` com o objeto completo do cliente criado (incluindo o `id` gerado pelo banco).
AC2.1: Na Ficha 360, adicionar um botao/icone "Abrir Conversa" visivel no cabecalho da ficha (proximo ao nome do cliente ou na area de acoes).
AC2.2: **Se o cliente tem conversa existente** (`last_conversation_id` nao nulo no objeto `customer`): ao clicar, navegar para `/conversas?customer_id={id}`. A pagina de Conversas ja auto-seleciona a conversa (comportamento implementado em AC9 da Story 9.10).
AC2.3: **Se o cliente NAO tem conversa** (`last_conversation_id` e nulo): ao clicar, navegar para `/conversas?new_customer_id={id}`. A pagina de Conversas deve exibir o estado "Iniciar novo atendimento para {nome do cliente}" com campo de texto para o atendente iniciar a conversa.
AC2.4: O botao deve ter tooltip ou label descritiva: "Ver Conversa" (se tem conversa) ou "Iniciar Conversa" (se nao tem).
AC2.5: A pagina de Conversas (`conversas/page.tsx`) deve aceitar o query param `new_customer_id` e, quando presente, exibir o painel direito com os dados do cliente e o campo de input de mensagem ativo para iniciar atendimento — sem selecionar conversa existente.
AC3.1: A listagem normal de clientes (`/clientes` sem filtro especifico) exibe APENAS clientes com `status = 'active'`. Clientes `'inactive'` NAO aparecem por default.
AC3.2: Os botoes de filtro na listagem (implementados em FIX-12 da Story 9.10) passam a ser: **"Todos" (ativos)**, **"B2B"**, **"B2C"**, **"Desativados"**. O filtro "Desativados" exibe apenas clientes `'inactive'`.
AC3.3: Quando o atendente busca por nome no campo de busca, a busca inclui APENAS clientes ativos — a menos que o filtro "Desativados" esteja selecionado.
AC3.4: O card de um cliente desativado, quando exibido (via filtro "Desativados"), tem visual diferenciado: opacidade reduzida (0.5–0.6), avatar cinza em vez de vermelho, e badge ou texto "Inativo" visivel.
AC3.5: Backend: a rota `GET /api/crm/customers` deve aceitar o query param `status` (ex: `?status=inactive`). Quando nao informado, default = `'active'` (filtra apenas ativos). Quando `status=inactive`, retorna apenas inativos.
AC3.6: A contagem "Mostrando X de Y clientes" (implementada em FIX-12) reflete o conjunto filtrado.
AC4.1: Criar helper `isFichaCompleta(customer: Customer): boolean` em `apps/crm/src/lib/api.ts`. Retorna `false` se qualquer campo obrigatorio (conforme tabela acima, baseado em `customer_type`) estiver `null` ou string vazia.
AC4.2: Criar helper `camposFaltando(customer: Customer): string[]` em `apps/crm/src/lib/api.ts`. Retorna lista de nomes amigaveis dos campos faltantes (ex: `['Email', 'CEP', 'Endereco']`).
AC4.3: No **card do cliente** (`ClientCard` em `clientes/page.tsx`): exibir badge pequena "Faltando Info" (cor amarela/laranja, texto 10px) quando `!isFichaCompleta(customer)`. A badge fica no canto superior direito do card ou abaixo do nome.
AC4.4: Na **Ficha 360** (`clientes/[id]/page.tsx`): exibir banner ou badge destacada "Ficha Incompleta — faltam: {lista de campos}" quando `!isFichaCompleta(customer)`. O banner deve ser visivel mas nao invasivo (ex: barra amarela abaixo do cabecalho).
AC4.5: O badge/banner some automaticamente se o atendente preencher os campos faltantes e salvar (sem precisar recarregar a pagina — atualizar o estado local apos save bem-sucedido).
AC4.6: Para a listagem de clientes, o dado de completude e calculado client-side a partir do objeto `Customer` ja disponivel. Nao requer chamada adicional ao backend.
TIMELINE
01/04/2026
chore: session cleanup — 10 stories Done, security+QA gates, MCC setup, V4 audit [Stories 6.3, 7.2, 9.9, 9.10, 9.11, 9.12, 19.4, 20.1, 20.2, 21.3]
550daa2
26/03/2026
chore: update Story 9.11 status + guia fundador CRM tracker + QA gates [Story 9.11]
9272ce7
26/03/2026
feat: CRM customer management — create, conversation link, inactive filter, completeness badge [Story 9.11]
e54dabf
ARQUIVOS (6)
apps/crm/src/app/clientes/page.tsx MODIFY
apps/crm/src/app/clientes/[id]/page.tsx MODIFY
apps/crm/src/app/conversas/page.tsx MODIFY
apps/crm/src/lib/api.ts MODIFY
propek-whatsapp-bot/src/api/crm/customers.ts MODIFY
docs/stories/active/story-9.11-crm-customer-management.md UPDATE
RETROSPECTIVA
Qualidade: ★☆☆☆☆
Incluir @qa no proximo ciclo
Rodar @cyber-chief antes do push