← story.propek
STORY 9.4
Kommo Import: Contatos
Epic: Epic 9 — CRM Database Foundation
DONE
ACCEPTANCE CRITERIA (44/44)
AC1.1: Script em `apps/crm/scripts/kommo-import-contacts.js` executavel via `node apps/crm/scripts/kommo-import-contacts.js`
AC1.2: Le token e URL do Kommo de variaveis de ambiente (`KOMMO_ACCESS_TOKEN`, `KOMMO_BASE_URL`)
AC1.3: Le connection string do banco de variaveis de ambiente (`DATABASE_URL` ou parametros individuais)
AC1.4: Aceita flags CLI: `--dry-run` (obrigatorio na primeira execucao), `--resume`, `--verbose`, `--limit N`
AC1.5: Mostra help com `--help`
AC2.1: Puxa contatos de `GET /api/v4/contacts?limit=250&with=leads,companies` com paginacao automatica
AC2.2: Respeita rate limit de 7 req/s (minimo 200ms entre requests)
AC2.3: Retry automatico com backoff exponencial (3 tentativas) em caso de erro 429/5xx
AC2.4: Exibe progresso no terminal (pagina X de Y, contatos processados)
AC2.5: Processa todas as 18 paginas (4.255 contatos) sem interrupcao em condicoes normais
AC3.1: `name` do Kommo → `contact_name` na tabela customers
AC3.2: Campo PHONE dos `custom_fields_values` → `phone_number` (normalizado para formato brasileiro)
AC3.3: Campo EMAIL dos `custom_fields_values` → `email`
AC3.4: `company.name` (se existir) → `business_name`
AC3.5: Campo CNPJ dos `custom_fields_values` → `cnpj` (normalizado XX.XXX.XXX/XXXX-XX)
AC3.6: Campo CPF dos `custom_fields_values` → `cpf`
AC3.7: `id` do Kommo → `metadata.kommo_id` (JSONB)
AC3.8: `created_at` (unix timestamp) → `created_at` (TIMESTAMP)
AC3.9: Custom fields nao mapeados → `metadata.kommo_fields` (JSONB)
AC3.10: Se tem empresa ou CNPJ: `customer_type = 'b2b'`, senao: `customer_type = 'b2c'`
AC4.1: Deduplicacao primaria por `phone_number` (UNIQUE constraint na tabela)
AC4.2: Se telefone ja existe: UPDATE campos vazios do registro existente, NAO sobrescrever campos preenchidos
AC4.3: Se telefone nao existe: INSERT novo registro
AC4.4: Sempre gravar `metadata.kommo_id` (mesmo em updates)
AC4.5: Contatos sem telefone: registrar no log de erros, nao importar (phone_number e NOT NULL)
AC4.6: `source` do registro marcado como `'import'` nos metadados
AC5.1: Com `--dry-run`, script NAO escreve no banco
AC5.2: Dry-run mostra no terminal: total a importar, novos vs updates, erros de validacao
AC5.3: Dry-run gera relatorio em `apps/crm/data/kommo-import-contacts-dryrun-{timestamp}.md`
AC5.4: Primeira execucao DEVE ser com `--dry-run` (script avisa se for a primeira vez sem dry-run)
AC6.1: A cada 250 contatos processados, salva checkpoint na tabela `crm_sync_state` (sync_type = 'kommo_contacts')
AC6.2: Com `--resume`, retoma do ultimo checkpoint salvo
AC6.3: Checkpoint armazena: ultima pagina processada, total processado, timestamp
AC6.4: Ao completar 100%, marca sync como concluido em `crm_sync_state`
AC7.1: Log estruturado em stdout: `[TIMESTAMP] [LEVEL] mensagem` (INFO, WARN, ERROR)
AC7.2: Erros incluem contexto: kommo_id, campo, valor esperado vs obtido
AC7.3: Relatorio final salvo em `apps/crm/data/kommo-import-contacts-report-{timestamp}.md`
AC7.4: Relatorio inclui: total processado, novos, atualizados, erros, tempo total
AC7.5: Contatos sem telefone listados individualmente no relatorio (para correcao manual)
AC8.1: Usa parameterized queries ($1, $2) — NUNCA interpolacao de strings SQL
AC8.2: Usa `crm_user` para conexao ao banco (NAO propek_user)
AC8.3: Bot WhatsApp continua operando normalmente durante a importacao
AC8.4: Zero dependencias externas alem do Node.js stdlib + pg (ja no projeto)
AC8.5: Token do Kommo NUNCA logado ou exibido no terminal
TIMELINE
25/03/2026
feat: Kommo Import Phase 2 — contacts + leads CLI scripts [Story 9.4, 9.5] [Story 6.1-sales-intelligence-bot]
c0e8bf2
ARQUIVOS (3)
apps/crm/scripts/kommo-import-contacts.js CREATE
apps/crm/data/kommo-import-contacts-report-*.md CREATE
docs/stories/active/story-9.4-kommo-import-contatos.md UPDATE
RETROSPECTIVA
Qualidade: ★★★☆☆
Incluir @qa no proximo ciclo
Rodar @cyber-chief antes do push