ACCEPTANCE CRITERIA (52/52)
☑ AC1.1: Script em `apps/crm/scripts/kommo-import-leads.js` executavel via `node apps/crm/scripts/kommo-import-leads.js`
☑ AC1.2: Le token e URL do Kommo de variaveis de ambiente
☑ AC1.3: Le connection string do banco de variaveis de ambiente
☑ AC1.4: Aceita flags CLI: `--dry-run`, `--resume`, `--verbose`, `--limit N`
☑ AC1.5: Mostra help com `--help`
☑ AC1.6: Verifica se Story 9.4 foi executada (contatos existem no banco) antes de iniciar. Aborta com mensagem clara se nao.
☑ AC2.1: Puxa leads de `GET /api/v4/leads?limit=250&with=contacts` 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, leads processados)
☑ AC2.5: Processa todas as 32 paginas (7.810 leads) sem interrupcao em condicoes normais
☑ AC3.1: `status_id` do Kommo → `current_stage` conforme tabela de mapeamento do PRD (12 stages)
☑ AC3.2: `pipeline_id` 7813707 (Interno/Geral) → `pipeline_type = 'b2b'`
☑ AC3.3: `pipeline_id` 10537648 (E-commerce Tray) → `pipeline_type = 'b2c'`
☑ AC3.4: Demais pipelines → `pipeline_type = 'b2b'`
☑ AC3.5: `price` do Kommo (centavos) → `estimated_value` (reais, dividir por 100)
☑ AC3.6: `_embedded.contacts[0].id` → lookup em `customers.metadata->>'kommo_id'` → `customer_id`
☑ AC3.7: `id` do Kommo → `metadata.kommo_lead_id` (JSONB)
☑ AC3.8: `name` do Kommo → `metadata.kommo_lead_name` (JSONB)
☑ AC3.9: `source` do registro = `'import'`
☑ AC3.10: `created_at`, `updated_at` (unix timestamp) → TIMESTAMP
☑ AC3.11: Leads com `status_id = 142` (Closed Won): `closed_at` preenchido, `close_reason = 'won'`
☑ AC3.12: Leads com `status_id = 143` (Closed Lost): `closed_at` preenchido, `close_reason = 'lost'`
☑ AC4.1: Para cada deal importado, criar 1 entry em `deal_stage_log` com o stage atual
☑ AC4.2: `deal_stage_log` entry: deal_id, from_stage=NULL (import inicial), to_stage=current_stage, changed_at=created_at do lead
☑ AC4.3: Deals fechados (won/lost): criar 2 entries — stage intermediario + stage final
☑ AC5.1: Para cada lead, buscar contato associado via `_embedded.contacts[0].id`
☑ AC5.2: Lookup no banco: `SELECT id FROM customers WHERE metadata->>'kommo_id' = $1`
☑ AC5.3: Se contato encontrado: linkar `customer_id`
☑ AC5.4: Se contato NAO encontrado: registrar no log de erros, NAO importar o lead (deal requer customer_id NOT NULL)
☑ AC5.5: Se lead nao tem contato associado no Kommo: registrar no log de erros, NAO importar
☑ AC6.1: Deduplicacao por `metadata->>'kommo_lead_id'` (se ja existe, UPDATE)
☑ AC6.2: UPDATE atualiza: current_stage, estimated_value, closed_at, close_reason, updated_at
☑ AC6.3: INSERT cria registro novo com todos os campos
☑ AC6.4: Script idempotente — executar 2x produz o mesmo resultado
☑ AC7.1: Com `--dry-run`, script NAO escreve no banco
☑ AC7.2: Dry-run mostra: total leads, com contato vs sem contato, por pipeline, por stage, novos vs updates
☑ AC7.3: Dry-run gera relatorio em `apps/crm/data/kommo-import-leads-dryrun-{timestamp}.md`
☑ AC8.1: A cada 250 leads processados, salva checkpoint na tabela `crm_sync_state` (sync_type = 'kommo_leads')
☑ AC8.2: Com `--resume`, retoma do ultimo checkpoint salvo
☑ AC8.3: Ao completar 100%, marca sync como concluido em `crm_sync_state`
☑ AC9.1: Log estruturado em stdout: `[TIMESTAMP] [LEVEL] mensagem`
☑ AC9.2: Erros incluem contexto: kommo_lead_id, campo, motivo
☑ AC9.3: Relatorio final em `apps/crm/data/kommo-import-leads-report-{timestamp}.md`
☑ AC9.4: Relatorio inclui: total processado, novos, atualizados, erros, por pipeline, por stage, valor total importado
☑ AC9.5: Leads sem contato listados individualmente (para correcao manual)
☑ AC10.1: Usa parameterized queries ($1, $2) — NUNCA interpolacao SQL
☑ AC10.2: Usa `crm_user` para conexao ao banco
☑ AC10.3: Bot WhatsApp continua operando durante importacao
☑ AC10.4: Zero dependencias externas alem de Node.js stdlib + pg
☑ AC10.5: CHECK constraints da tabela deals respeitados (pipeline_type, current_stage, source, close_reason)
☑ AC10.6: Token do Kommo NUNCA logado ou exibido