# ClientFlow v4928.1.5.125 — Follow-up e ciclo de vida comercial

## Objetivo

Reduzir o risco de perder oportunidades porque a primeira comunicação não chegou e impedir que oportunidades sem resposta permaneçam indefinidamente no funil ativo.

## Alterações principais

- Primeira confirmação no dia útil seguinte ao envio.
- Cadências diferentes para informação, orçamento e pagamento.
- Nova ação interna `CONFIRM_DELIVERY` para validar destinatário, documento, outbox e bounce.
- Estados operacionais: ativa, a aguardar cliente, follow-up vencido, recuperação e acompanhamento futuro.
- Fila e filtro de recuperação na página de oportunidades.
- Filtros para follow-up vencido, inativas, por valorizar e nurture.
- Cartões com valor, dias sem resposta, próximo contacto e número de tentativas.
- Atividade comercial baseada em timestamps próprios, sem usar `updated_at` técnico.
- Reabertura segura por resposta do cliente apenas para `LOST`/`NO_INTEREST` na mesma conversa.
- Motivo obrigatório ao fechar como perdida; timing futuro deve usar nurture.
- Resposta do cliente cancela follow-ups obsoletos e reativa o processo.
- Script de backfill em dry-run por defeito.

## Cadências

### Informação e orçamento

1. Dia útil seguinte: confirmar receção e entrega técnica.
2. +2 dias úteis: interesse/dúvidas.
3. +4 dias úteis: decisão/qualificação.
4. +5 dias úteis: última tentativa.
5. Recuperação.

### Pagamento

1. Dia útil seguinte: confirmar receção.
2. +2 dias úteis: pedir data prevista.
3. +3 dias úteis: lembrete.
4. +3 dias úteis: contacto direto/canal alternativo.
5. +5 dias úteis: rever intenção.
6. Recuperação.

## Base de dados

A atualização é aditiva. `ensure_opportunity_schema()` cria as colunas em falta:

- `lifecycle_state`
- `last_customer_activity_at`
- `last_operator_activity_at`
- `last_outbound_sent_at`
- `last_delivery_checked_at`
- `last_delivery_status`
- `last_commercial_activity_at`
- `next_follow_up_at`
- `follow_up_attempts`
- `nurture_until`
- `lost_reason`

## Migração segura

Simular:

```bash
python scripts/sync_opportunity_followup_lifecycle.py --limit 50
```

Aplicar depois de rever:

```bash
python scripts/sync_opportunity_followup_lifecycle.py --apply --limit 50
```

O script não envia comunicações. Cria somente tasks humanas e nunca usa `updated_at` como atividade comercial.

## Validação

```text
compileall: OK
496 testes passados
```
