Fase 7: CDR/métricas/relatórios, reconciliação, dashboard e compliance
- Reconciliação de tentativas órfãs após restart (reconciliation.ts), rodando a cada 60s. - Vínculo real agente<->chamada (agent-call-binding.ts): claim atômico de agente disponível via FOR UPDATE SKIP LOCKED, DialAttempt.agentId populado no connect, ciclo AVAILABLE -> IN_CALL -> WRAP_UP -> AVAILABLE. - Corrige abandonRate (EWMA) nunca atualizado pelo campaign-worker real — agora o fluxo QUEUED -> connect-or-abandon atualiza as estatísticas de fato usadas pelo predictive engine. - Novo módulo de relatórios: /api/reports/calls (+export CSV), /metrics (TME/TMA/abandono), /agents/:id. - Novo módulo de dashboard: /api/dashboard, /calls-by-hour, /campaigns/:id (Postgres + snapshot EWMA do Redis). - Novo módulo de compliance: ComplianceSettings configurável + /api/compliance/settings e /indicators com contadores reais. - Validado end-to-end contra containers reais (campanha de teste em modo simulação): agentId no connect, ciclo de estado do agente e abandonRate todos confirmados corrigidos com dados reais, não só no harness isolado. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QoVkLx1KsvtT1C88dRS3QW
This commit is contained in:
@@ -159,23 +159,26 @@ chamadas em andamento (seção 76).
|
||||
- **AMD**: campo `Campaign.amdEnabled` existe no schema/DTO, mas a
|
||||
detecção de secretária eletrônica em si (app `AMD()` do Asterisk ou
|
||||
ARI) ainda não está integrada ao fluxo de originação real. Pendente.
|
||||
- **Wrap-up automático**: `Campaign.wrapUpTimeSeconds` existe, mas a
|
||||
transição automática do agente para o estado `WRAP_UP` ao final de uma
|
||||
chamada real (via eventos `AgentComplete` do Asterisk) ainda não está
|
||||
implementada em `apps/asterisk-events` — hoje o agente só muda de estado
|
||||
manualmente pela tela do agente (Fase 5). Isso significa que, em uma
|
||||
campanha com chamadas REAIS (não simuladas), a contagem de
|
||||
`availableAgents`/`agentsLikelyToFreeSoon` não reflete automaticamente
|
||||
agentes que entraram em uma chamada real — só funciona corretamente hoje
|
||||
no modo de simulação (que modela isso internamente) e para as
|
||||
transições manuais já cobertas pela Fase 5 (login/disponível/pausa/
|
||||
logout). Wiring de `AgentConnect`/`AgentComplete` -> transição de estado
|
||||
fica para consolidação junto da Fase 7 (reconciliação de estados).
|
||||
- **Wrap-up automático (simulação)**: desde a Fase 7, `claimAvailableAgent`/
|
||||
`releaseAgentAfterCall` (`agent-call-binding.ts`) implementam o ciclo
|
||||
completo `AVAILABLE → IN_CALL → WRAP_UP → AVAILABLE` (usando
|
||||
`Campaign.wrapUpTimeSeconds`) e `DialAttempt.agentId` é populado
|
||||
corretamente ao conectar — validado end-to-end em modo simulação (ver
|
||||
TODO.md Fase 7). **Isso ainda só é acionado pelo fluxo simulado
|
||||
(`tryConnectOrAbandon`/`connect` em `campaign-worker.ts`).** Para
|
||||
campanhas com chamadas REAIS (`DIALER_SIMULATION=false`), a transição via
|
||||
eventos `AgentConnect`/`AgentComplete` do Asterisk ainda não está
|
||||
implementada em `apps/asterisk-events` — hoje o agente em chamada real só
|
||||
muda de estado manualmente pela tela do agente (Fase 5). Pendente para
|
||||
quando houver troncos/chamadas reais para testar (Fase 9/10).
|
||||
- **Correlação de eventos reais**: quando `DIALER_SIMULATION=false`, a
|
||||
chamada é originada de verdade via AMI, mas a resolução fina
|
||||
(atendida/ocupada/sem resposta) depende de reconciliação com
|
||||
CDR/CEL/queue_log — planejada explicitamente para a Fase 7 (seção 51).
|
||||
Por ora, uma chamada real sem eventos correlacionados expira em
|
||||
(atendida/ocupada/sem resposta) ainda depende de reconciliação fina com
|
||||
CDR/CEL/queue_log, que não está implementada — a Fase 7 entregou apenas a
|
||||
reconciliação de *estados órfãos* (`reconciliation.ts`, tentativas presas
|
||||
por >10min são forçadas a `FAILED`/`RECONCILED_ORPHAN`), não a
|
||||
correlação de eventos AMI em tempo real para o resultado exato da
|
||||
chamada. Por ora, uma chamada real sem eventos correlacionados expira em
|
||||
`FAILED` após o timeout de segurança, o que é seguro (nunca fica presa
|
||||
para sempre) mas não tão preciso quanto a resolução via simulação.
|
||||
- **Disposições/Callback**: adiados para consolidar junto da tela do
|
||||
|
||||
Reference in New Issue
Block a user