Implementar os 4 triggers de eventos do bot que criam/movem deals automaticamente no CRM, e os 2 cron jobs que mantêm follow-ups atualizados, fazendo o pipeline se auto-popular sem intervencao manual do atendente.
ACCEPTANCE CRITERIA (0/27)
☐ AC1: Funcao `onLeadScored()` implementada e chamada apos INSERT em `lead_scores` quando classification IN ('A', 'B', 'hot') E customer.customer_type contém 'b2b' (case-insensitive)
☐ AC2: `onLeadScored()` verifica se ja existe deal aberto para o customer antes de criar novo (idempotencia — nao cria deal duplicado)
☐ AC3: Se nao existe deal aberto: INSERT em `deals` (pipeline_type='b2b', current_stage='lead_qualificado', source='bot') + INSERT em `deal_stage_log` (from_stage=NULL, to_stage='lead_qualificado', changed_by='bot')
☐ AC4: Cria `follow_up_crm` tipo 'lead_contact' com due_at = NOW() + 2 horas para o novo deal
☐ AC5: Round-robin: atribui `assigned_to` ao atendente com MENOS deals abertos no momento (query COUNT por assigned_to WHERE closed_at IS NULL)
☐ AC6: Funcao `onOrderCreated()` implementada e chamada apos INSERT em `orders`
☐ AC7: Verifica se ja existe deal para o order_id antes de criar (idempotencia via `WHERE order_id = $1`)
☐ AC8: Detecta se cliente e B2B ou B2C via `customers.customer_type`
☐ AC9: Cria deal com pipeline_type e stage corretos: B2B → stage='confirmado', B2C → stage='pedido'; `estimated_value` = `order.total_amount`
☐ AC10: INSERT em `deal_stage_log` (from_stage=NULL, to_stage adequado, changed_by='bot')
☐ AC11: Funcao `onShipmentCreated()` implementada e chamada quando shipment recebe tracking_code
☐ AC12: Busca deal vinculado via `WHERE order_id = $1 AND closed_at IS NULL`
☐ AC13: Nao move se deal ja esta em stage >= 'enviado' (guard clause: nao regride stages)
☐ AC14: UPDATE deals SET current_stage='enviado' + INSERT deal_stage_log (changed_by='webhook')
☐ AC15: Funcao `onShipmentDelivered()` implementada e chamada quando shipment.status = 'delivered'
☐ AC16: UPDATE deals SET current_stage='entregue' + INSERT deal_stage_log (changed_by='webhook')
☐ AC17: Cria follow_up_crm tipo 'nps' com due_at = NOW() + 48 horas, assigned_to = deal.assigned_to
☐ AC18: Cria 3 follow-ups da sequencia Ezra: 'ezra_d3' (NOW()+3d), 'ezra_d7' (NOW()+7d), 'ezra_d14' (NOW()+14d), todos com assigned_to = deal.assigned_to
☐ AC19: Cron registrado no `cron.handler.ts` do bot para executar a cada 15 minutos
☐ AC20: UPDATE follow_ups_crm SET status='overdue', updated_at=NOW() WHERE status='pending' AND due_at < NOW()
☐ AC21: Loga a quantidade de follow-ups atualizados para overdue com `logger.info`
☐ AC22: Cron registrado para executar diariamente as 08:00 (usando sintaxe cron '0 8 \* \* \*')
☐ AC23: Query detecta clientes B2B que: (a) fizeram pelo menos um pedido, (b) nao fizeram pedido nos ultimos 60 dias, (c) nao tem follow_up_crm tipo 'recompra' com status 'pending' ou 'overdue' ja existente (idempotencia)
☐ AC24: Para cada cliente at-risk: INSERT follow_ups_crm (follow_up_type='recompra', due_at = NOW()+3 dias) — sem deal_id (follow-up de cliente, nao de deal)
☐ AC25: Loga quantidade de clientes at-risk detectados com `logger.info`
☐ AC26: Todos os triggers sao fire-and-forget — erros nao devem propagar para o fluxo principal do bot (try/catch com log do erro, nunca throw)
☐ AC27: Logger do bot usado em todos os eventos para rastreabilidade (formato: `logger.info({ dealId, customerId }, 'CRM: ...')`)