# Automatic Flows - Nexos (Exent)

> Fluxos automaticos: Cron Jobs, Queue Jobs, Webhooks, Schedulers.
> Gerado em 2026-06-18.

---

## Indice

1. [Arquitetura de Execucao](#1-arquitetura-de-execucao)
2. [Cron Jobs - Alta Frequencia](#2-cron-jobs---alta-frequencia)
3. [Cron Jobs - Diarios](#3-cron-jobs---diarios)
4. [Cron Jobs - Mensais (Recorrencia)](#4-cron-jobs---mensais-recorrencia)
5. [Cron Jobs - Semestrais (Premios)](#5-cron-jobs---semestrais-premios)
6. [Cron Jobs - Notificacoes por Email](#6-cron-jobs---notificacoes-por-email)
7. [Cron Jobs - Notificacoes Push e Slack](#7-cron-jobs---notificacoes-push-e-slack)
8. [Queue Jobs (Disparados por Acao)](#8-queue-jobs-disparados-por-acao)
9. [Webhooks Recebidos](#9-webhooks-recebidos)
10. [API de Integracao (Exent Space)](#10-api-de-integracao-exent-space)
11. [Cadeia de Dependencias entre Jobs](#11-cadeia-de-dependencias-entre-jobs)
12. [Mapa de Impacto por Tabela](#12-mapa-de-impacto-por-tabela)
13. [Riscos e Pontos de Falha](#13-riscos-e-pontos-de-falha)

---

## 1. Arquitetura de Execucao

```
┌───────────────────────────────────────────────────────────────┐
│                    SCHEDULER (console.php)                    │
│  php artisan schedule:run (cron do servidor, a cada minuto)   │
│                                                               │
│  Macro tenantJob: itera TODOS os tenants via Tenant::cursor() │
│  Para cada tenant: dispatch(clone $job) no contexto do banco  │
└──────────────────────┬────────────────────────────────────────┘
                       │
                       ▼
┌───────────────────────────────────────────────────────────────┐
│                  QUEUE WORKER (database driver)               │
│  php artisan queue:listen --tries=1                           │
│  Tabelas: jobs, failed_jobs, job_batches (landlord)           │
│  Restart automatico no deploy: php artisan queue:restart      │
└──────────────────────┬────────────────────────────────────────┘
                       │
                       ▼
┌───────────────────────────────────────────────────────────────┐
│                        JOB EXECUTION                          │
│  Cada job roda no contexto do tenant (DB isolado)             │
│  Erros: finance_logs (tenant) + failed_jobs (landlord)        │
└───────────────────────────────────────────────────────────────┘
```

**Configuracao:**
- Fila: database driver (tabela `jobs` no landlord)
- Worker: `php artisan queue:listen --tries=1`
- Timezone: America/Sao_Paulo
- Deploy: `php artisan queue:restart` no CI/CD
- Tenant isolation: macro `tenantJob` executa `$tenant->run(fn => dispatch(clone $job))`

---

## 2. Cron Jobs - Alta Frequencia

### 2.1 SendFinanceLogAlerts
| | |
|---|---|
| **Frequencia** | A cada 1 minuto |
| **Disparo** | Scheduler (tenantJob) |
| **O que faz** | Busca ate 50 registros de `finance_logs` com operation=error/critical, solved=false, alert_sent=false. Envia cada um para Slack via webhook. Marca alert_sent=true apos envio. |
| **Services** | SlackAlertService |
| **Tabelas lidas** | `finance_logs` |
| **Tabelas alteradas** | `finance_logs` (alert_sent=true) |
| **APIs externas** | Slack Webhook |
| **Impacto** | Alertas de erro chegam ao Slack em ate 1 minuto |
| **Falhas possiveis** | Slack webhook offline → alert_sent nao atualiza → retry no proximo minuto. Sem try/catch → exception pode falhar job silenciosamente. |

---

### 2.2 CheckIuguPaymentsJob
| | |
|---|---|
| **Frequencia** | A cada 2 minutos |
| **Disparo** | Scheduler (tenantJob) |
| **O que faz** | 1) Busca FinanceTransaction com provider=iugu, status in [pending, processing]. 2) Para boletos: chama IuguPaymentService::checkPaymentStatus. 3) Para TED/PIX: idem + atualiza snapshot items em caso de erro. |
| **Services** | IuguPaymentService, LogService, IntegrationCredentialService |
| **Tabelas lidas** | `finance_transactions`, `finance_transactions_bills`, `finance_transactions_transfers` |
| **Tabelas alteradas** | `finance_transactions` (status, paid_at, id_iugu, bank_receipt_url, log), `finance_transactions_transfers` (end_to_end_id), `finance_payment_collab_snapshot_items` (status, log) |
| **APIs externas** | Iugu (GET /payment_requests/{id}, GET /transfer_requests/{id}), Google Cloud Storage (upload comprovante) |
| **Impacto** | Atualiza status de pagamentos Iugu em tempo quase-real |
| **Falhas possiveis** | Iugu API offline → status nao atualiza. Credenciais inexistentes → early return silencioso. Upload comprovante falha → log notice, continua. |

---

### 2.3 CheckAsaasPaymentsJob
| | |
|---|---|
| **Frequencia** | A cada 2 minutos |
| **Disparo** | Scheduler (tenantJob) |
| **O que faz** | Chama AsaasCheckPaymentsService::asaasCheckPayments. Busca todas FinanceTransaction com id_asaas preenchido. Para cada: consulta API Asaas por tipo (BOLETO/TED/PIX/PIX_QRCODE). Mapeia status, atualiza transacao, extrai comprovante PDF, atualiza snapshot items. |
| **Services** | AsaasCheckPaymentsService, LogService |
| **Tabelas alteradas** | `finance_transactions` (status, paid_at, bank_receipt_url, log), `finance_transactions_transfers` (end_to_end_id), `finance_transactions_pix_qrcode` (end_to_end_id), `finance_payment_collab_snapshot_items` (status) |
| **APIs externas** | Asaas (getTransfer, getBillPayment, getPixTransaction), Google Cloud Storage (upload comprovante), Slack (alerta erro/rejeicao) |
| **Impacto** | Atualiza status de pagamentos Asaas em tempo quase-real. Comprovantes bancarios salvos automaticamente. |
| **Falhas possiveis** | Asaas API offline → log erro. Extracao PDF do comprovante falha → null retornado, upload ignorado. |

---

### 2.4 CheckAsaasInvoiceCancellationsJob
| | |
|---|---|
| **Frequencia** | A cada 2 minutos |
| **Disparo** | Scheduler (tenantJob) |
| **O que faz** | Busca FinanceCharge com nfs_status='processing_cancellation'. Consulta Asaas para status atualizado. Atualiza nfs_status (canceled/denied/error). |
| **Services** | AsaasCheckInvoiceService, LogService |
| **Tabelas alteradas** | `finance_charges` (nfs_status, nfs_url, log) |
| **APIs externas** | Asaas (getInvoice) |
| **Impacto** | Finaliza processo de cancelamento de NFS-e |
| **Falhas possiveis** | API offline → status permanece processing_cancellation. Status 'denied' gera log critico. |

---

### 2.5 SyncInvoiceStatus
| | |
|---|---|
| **Frequencia** | A cada 2 minutos |
| **Disparo** | Scheduler (tenantJob) |
| **O que faz** | Chama InvoiceSyncService::apply(). Consulta status de NFS-e pendentes (Spedy e Asaas). Atualiza nfs_status, nfs_number, nfs_url. Envia alerta Slack para status de erro. |
| **Services** | InvoiceSyncService, GuzzleService, SlackAlertService, IntegrationCredentialService |
| **Tabelas alteradas** | `finance_charges` (nfs_status, nfs_number, nfs_url, log) |
| **APIs externas** | Spedy (GET /service-invoices/{id}), Asaas (getInvoice), Slack (alertas) |
| **Impacto** | NFS-e com status 'authorized' recebem URL do PDF automaticamente |
| **Falhas possiveis** | Spedy/Asaas offline → status nao atualiza. Status de erro gera alerta Slack. |

---

### 2.6 CheckTestInvoices
| | |
|---|---|
| **Frequencia** | A cada 2 minutos |
| **Disparo** | Scheduler (tenantJob) |
| **O que faz** | Busca FinanceInvoiceTest com status pendente. Consulta Spedy e Asaas para status atualizado. Atualiza status, nfs_url, nfs_number. |
| **Services** | SpedyApiController, AsaasApiController (instanciados diretamente) |
| **Tabelas alteradas** | `finance_invoice_test` (status, nfs_url, nfs_number, log) |
| **APIs externas** | Spedy, Asaas |
| **Falhas possiveis** | Status desconhecido no match → exception. API offline → erro por item, continua loop. |

---

### 2.7 SendChargeGeneratedNotifications
| | |
|---|---|
| **Frequencia** | A cada 5 minutos |
| **Disparo** | Scheduler (tenantJob) |
| **O que faz** | Envia email para clientes com cobrancas recem-geradas (mail_stage=0, bill_status=Pendente). Atualiza mail_stage apos envio. Anexa boleto PDF se attached_bill=true. |
| **Services** | EmailChargeService → FinanceMailService → MailService |
| **Tabelas alteradas** | `finance_charges` (mail_stage, is_mail_sent, failed_mail), `finance_billing_mail_logs` (INSERT) |
| **APIs externas** | SMTP, Spedy/Asaas (download PDF boleto para anexo) |
| **Impacto** | Clientes recebem cobranca por email ate 5 min apos emissao |
| **Falhas possiveis** | SMTP offline → failed_mail=true → retry em 10min via ResendFailed. Download PDF falha → email sem anexo. |

---

### 2.8 SendSummaryGeneratedNotifications
| | |
|---|---|
| **Frequencia** | A cada 5 minutos |
| **Disparo** | Scheduler (tenantJob) |
| **O que faz** | Envia email de resumo de cobranca para clientes (mail_stage=0, stage=Gerado). |
| **Services** | EmailSummaryService → FinanceMailService |
| **Tabelas alteradas** | `finance_billing_summary_bills` (mail_stage, failed_mail), `finance_billing_mail_logs` |
| **APIs externas** | SMTP |

---

### 2.9 SendSummaryChargeCanceled
| | |
|---|---|
| **Frequencia** | A cada 5 minutos |
| **Disparo** | Scheduler (tenantJob) |
| **O que faz** | Notifica clientes quando cobranca de resumo e cancelada. |
| **Services** | EmailSummaryService |
| **APIs externas** | SMTP |

---

### 2.10 ResendFailedChargeNotifications
| | |
|---|---|
| **Frequencia** | A cada 10 minutos |
| **Disparo** | Scheduler (tenantJob) |
| **O que faz** | Reenvia emails de cobranca que falharam (failed_mail=true). |
| **Services** | EmailChargeService |
| **Tabelas alteradas** | `finance_charges` (failed_mail, mail_stage) |
| **APIs externas** | SMTP |

---

### 2.11 ResendFailedSummaryNotifications
| | |
|---|---|
| **Frequencia** | A cada 10 minutos |
| **Disparo** | Scheduler (tenantJob) |
| **O que faz** | Reenvia emails de resumo de cobranca que falharam. |
| **Services** | EmailSummaryService |
| **APIs externas** | SMTP |

---

## 3. Cron Jobs - Diarios

### 3.1 RunFinanceSync
| | |
|---|---|
| **Frequencia** | 2x/dia: 08:00 e 20:00 |
| **Disparo** | Scheduler (tenantJob) |
| **O que faz** | Cria FinanceSyncRun e dispatcha RunManualFinanceSync (job em background) |
| **Timeout** | 30 minutos (RunManualFinanceSync) |
| **Tries** | 1 (sem retry) |
| **Steps executados pelo RunManualFinanceSync:** | |

```
Step 1: ClientsSyncService::apply()
  → Sincroniza clientes com Asaas (cria/atualiza/pareia)
  → Tabelas: finance_clients (asaas_id, stage), finance_client_contacts

Step 2: InvoiceCreationService::apply()
  → Emite NFS-e para cobrancas com bill_stage=2 sem id_nfs
  → Tabelas: finance_charges (id_nfs, nfs_status, nfs_url)
  → APIs: Spedy (createNFS), Asaas (createInvoice, approveInvoice)

Step 3: RecurrenceSyncService::apply()
  → Reseta recorrencias (stage 2→1) + gera cobrancas do dia
  → Tabelas: finance_charges (INSERT), finance_recurrence (past_cycle, stage)
  → Logica: verifica cycle, due_on_working_days_only, duplicatas

Step 4: PendingChargesGenerationService::apply()
  → Emite boletos + NFS-e para cobrancas em bill_stage=1
  → Tabelas: finance_charges (bill_url, bill_status, nfs_url, etc.)
  → APIs: Asaas (createPayment, createInvoice), Iugu (addPayments), Spedy

Step 5: ChargesSyncService::apply()
  → Verifica status de cobrancas Pendente/Processando
  → Tabelas: finance_charges (bill_status, paid_at, fine_value)
  → APIs: Asaas (getPayment), Iugu (checkPayments)
```

| **Tabelas alteradas** | `finance_sync_runs`, `finance_config` (sync_status.last_sync), + todas as tabelas dos steps |
| **APIs externas** | Asaas, Iugu, Spedy |
| **Impacto** | Maior job do sistema. Processa todo o ciclo financeiro: clientes → NFS-e → recorrencias → emissao → verificacao |
| **Falhas possiveis** | Step individual falha → run marcado 'partial'. Timeout 30min → failed(). Lock window (07:55-08:05, 19:55-20:05) impede sync manual durante cron. |

---

### 3.2 CheckChargesStatus
| | |
|---|---|
| **Frequencia** | Diario 08:55 |
| **Disparo** | Scheduler (tenantJob) |
| **O que faz** | ChargesSyncService::apply() - verifica status de boletos pendentes via Iugu/Asaas. Atualiza bill_status, paid_at, multas, juros. Status finais (Pago, Cancelado, Reembolsado) → mail_stage=9, bill_stage=3. |
| **Tabelas alteradas** | `finance_charges` |
| **APIs externas** | Asaas, Iugu |

---

### 3.3 DispatchScheduledPaymentsJob
| | |
|---|---|
| **Frequencia** | Diario 09:00 |
| **Disparo** | Scheduler (tenantJob) |
| **O que faz** | Busca FinanceTransaction com status='scheduled', schedule_date=hoje. Revalida cada transacao. Atualiza para 'pending'. Dispatcha ProcessPaymentJob para cada. Notifica Slack com contagem. |
| **Tabelas alteradas** | `finance_transactions` (status: scheduled→pending) |
| **Jobs disparados** | ProcessPaymentJob (1 por transacao) |
| **APIs externas** | Slack (notificacao) |
| **Impacto** | Pagamentos agendados sao executados no dia correto |
| **Falhas possiveis** | Race condition (mitigada com revalidacao). Slack falha → log apenas, nao bloqueia. |

---

### 3.4 SendChargeDueSoonNotifications
| | |
|---|---|
| **Frequencia** | Diario 09:00 |
| **O que faz** | Email para clientes com cobrancas proximas do vencimento |

### 3.5 SendChargeOverdueNotifications
| | |
|---|---|
| **Frequencia** | Diario 09:00 |
| **O que faz** | Email para clientes com cobrancas vencidas. Regra: D+1, D+2, D+5, depois a cada 2 dias uteis |

### 3.6 SendSummaryNotification
| | |
|---|---|
| **Frequencia** | Diario 09:00 |
| **O que faz** | Email de notificacao de resumos pendentes |

### 3.7 SendChargesOverduePushNotification
| | |
|---|---|
| **Frequencia** | Diario 09:00 |
| **O que faz** | Push notification (Ntfy) para cobrancas vencidas |
| **APIs externas** | Ntfy.sh |

### 3.8 SendNFsAlertCollab / SendNFsAwardsAlertCollab
| | |
|---|---|
| **Frequencia** | Diario 09:30 |
| **O que faz** | Email para colaboradores sobre NFs pendentes (recorrencia e premios). Controle de estagio de notificacao. |

### 3.9 CheckCollabBirthdaysJob
| | |
|---|---|
| **Frequencia** | Diario 09:30 |
| **O que faz** | CoreBirthdayCollabService::notifyBirthdays(). Verifica aniversarios (3 dias antes + no dia). Envia mensagem Slack + email. |
| **Services** | CoreBirthdayCollabService → MailService, SlackAlertService |
| **Tabelas lidas** | `core_collaborators`, `core_email_to` |
| **APIs externas** | Slack Webhook, SMTP |
| **Impacto** | Notificacao de aniversarios no canal do Slack |

### 3.10 SendRefundsPendingNotification
| | |
|---|---|
| **Frequencia** | Diario 10:00 |
| **O que faz** | Notifica sobre reembolsos pendentes. Regra: ancora dias 2 e 17 do mes, depois a cada 2 dias uteis a partir de cada ancora. |
| **Tabelas alteradas** | `finance_refunds` (alert_sent=1) |
| **APIs externas** | SMTP |

### 3.11 CheckCertificateNF
| | |
|---|---|
| **Frequencia** | Diario 10:00 |
| **O que faz** | Verifica vencimento do certificado digital de NF. Envia alerta apenas nos marcos exatos de 60 e 40 dias antes do vencimento. |
| **Tabelas lidas** | `finance_config` (certificate_date), `finance_email_to` |
| **APIs externas** | SMTP |

### 3.12 CheckBillingSummaryBillsStatus
| | |
|---|---|
| **Frequencia** | 2x/dia: 08:10 e 20:10 |
| **O que faz** | Verifica bills de resumo com stage='Pendente'. Se todas cobrancas vinculadas estao em [Pago, Pago Externamente, Cancelado], finaliza o bill (stage='Finalizado', mail_stage=9). |
| **Tabelas alteradas** | `finance_billing_summary_bills` (stage, mail_stage, log) |

### 3.13 SyncIuguStatementsJob
| | |
|---|---|
| **Frequencia** | Diario 23:50 |
| **O que faz** | IuguStatementService::handle(). Busca extrato do dia na API Iugu. Classifica tipo (Entrada/Saida/Tarifa). Reconcilia com finance_charges e finance_transactions. Cria entradas em finance_ca_statement e finance_iugu_statements. |
| **Tabelas alteradas** | `finance_iugu_statements` (INSERT/UPDATE), `finance_ca_statement` (INSERT/UPDATE) |
| **APIs externas** | Iugu (extrato) |
| **Restricao** | Somente em ambiente PROD |

### 3.14 SyncAsaasStatementsJob
| | |
|---|---|
| **Frequencia** | Diario 23:50 |
| **O que faz** | AsaasStatementService::handle(). Busca extrato paginado da API Asaas. Classifica 18 tipos de tarifa. Auto-reconcilia com transactions e charges. |
| **Tabelas alteradas** | `finance_ca_statement` (INSERT/UPDATE, asaas_transaction_id unico) |
| **APIs externas** | Asaas (getBankStatement, paginado) |

### 3.15 CreatePendingInvoices
| | |
|---|---|
| **Frequencia** | A cada hora (HH:10) |
| **O que faz** | InvoiceCreationService::apply(). Emite NFS-e para cobrancas com bill_stage=2 e sem id_nfs. |
| **Tabelas alteradas** | `finance_charges` (id_nfs, nfs_status, nfs_url, nfs_number, log) |
| **APIs externas** | Spedy (createNFS), Asaas (createInvoice, approveInvoice) |

---

## 4. Cron Jobs - Mensais (Recorrencia)

### 4.1 GenerateRecurrenceSnapshot (Dia 25, 08:00)
| | |
|---|---|
| **O que faz** | RecurrenceSnapshotService::generate(). Cria FinancePaymentCollabSnapshot tipo 'recurrence' + itens para cada colaborador com recorrencia ativa. |
| **Tabelas alteradas** | `finance_payment_collab_snapshots` (INSERT), `finance_payment_collab_snapshot_items` (INSERT, 1 por recorrencia) |
| **Logica** | reference_date=hoje, lock_date=fim do mes, status=draft. Pre-preenche valor/descricao da recorrencia. Previne duplicatas. |
| **Impacto** | Inicia ciclo de pagamento mensal dos colaboradores |

### 4.2 SendSnapshotGeneratedReminder (Dia 25, 09:00)
| | |
|---|---|
| **O que faz** | Email para colaboradores informando que o snapshot foi gerado e precisam enviar NF. |

### 4.3 DispatchSnapshotInvoices (Dia 1, 08:00)
| | |
|---|---|
| **O que faz** | SnapshotInvoiceService::dispatchPendingItems('recurrence'). Cria FinanceInvoice (status='expected') para cada item draft do snapshot. Verifica contrato PJ/Estagio-PJ. Atualiza item para 'execution'. |
| **Tabelas alteradas** | `finance_invoices` (INSERT), `finance_payment_collab_snapshot_items` (status: draft→execution), `finance_payment_collab_snapshots` (status: draft→execution) |

### 4.4 DispatchSnapshotTransfers (Dia 1, 08:30)
| | |
|---|---|
| **O que faz** | SnapshotTransferService::dispatchPendingItems('recurrence'). Cria FinanceTransaction + FinanceTransactionTransfer (PIX) para cada item 'execution'. Agenda pagamento com offset de prioridade (1-3 dias uteis). |
| **Tabelas alteradas** | `finance_transactions` (INSERT, status=scheduled), `finance_transactions_transfers` (INSERT), `finance_payment_collab_snapshot_items` (status: execution→scheduled) |
| **Logica prioridade** | P1: dia 1, P2: dia 1 + 1 dia util, P3: dia 1 + 2 dias uteis |

### 4.5 CloseCompletedSnapshotsJob (Dias 1-5, 10:00)
| | |
|---|---|
| **O que faz** | SnapshotStatusService::closeIfCompleted('recurrence'). Fecha snapshots onde todos os itens estao em [paid, cancelled, error]. |
| **Tabelas alteradas** | `finance_payment_collab_snapshots` (status: execution→closed) |

### 4.6 NfsNotifyCollabJob (Dias 4-5, 11h/15h/18h)
| | |
|---|---|
| **O que faz** | SlackNFsCollabService::nfsNotifyCollab(). Envia DM no Slack para colaboradores com NF pendente. |
| **APIs externas** | Slack Bot API (conversations.open, chat.postMessage) |
| **Impacto** | Colaboradores recebem 6 lembretes em 2 dias para enviar NF |

### 4.7 SendNFsSummaryCollab (Dias 4-5, 10:00)
| | |
|---|---|
| **O que faz** | Email resumo com lista de NFs pendentes/recebidas para admins. |

### 4.8 CheckMeiLimitAndNotify (Dia 6, 10:00)
| | |
|---|---|
| **O que faz** | FinanceInvoiceLimitService::getCollaboratorsNearLimit(). Calcula total anual de NFs por colaborador PJ. Se >= threshold (notification_percentage * limit_value), envia email com tabela. |
| **Tabelas lidas** | `finance_invoices`, `core_collaborators`, `finance_mei_limit`, `finance_email_to` |
| **APIs externas** | SMTP |
| **Impacto** | Previne que colaboradores ultrapassem limite MEI |

---

## 5. Cron Jobs - Semestrais (Premios - Abril e Outubro)

### 5.1 GenerateAwardSnapshot (Dia 15, 08:00)
| | |
|---|---|
| **O que faz** | AwardSnapshotService::generate(). Cria snapshot tipo 'award' com itens para colaboradores elegiveis. |
| **Logica** | Abril: "Segundo Semestre" (cutoff 31/12 ano anterior). Outubro: "Primeiro Semestre" (cutoff 30/06). Exclui Estagio. |
| **Tabelas alteradas** | `finance_payment_collab_snapshots` (INSERT), `finance_payment_collab_snapshot_items` (INSERT) |

### 5.2 DispatchSnapshotInvoices award (Dia 25, 08:00)
| | |
|---|---|
| **O que faz** | Cria FinanceInvoice para itens do snapshot de premios. Somente contrato PJ. |

### 5.3 DispatchSnapshotTransfers award (Dia 25, 08:30)
| | |
|---|---|
| **O que faz** | Cria transacoes PIX para itens do snapshot de premios. |

### 5.4 CloseCompletedSnapshotsJob award (Dias 25-30, 10:00)
| | |
|---|---|
| **O que faz** | Fecha snapshots de premios completos. |

### 5.5 NfsAwardsNotifyCollabJob (Dias 29-30, 11h/15h/18h, apenas abr/out)
| | |
|---|---|
| **O que faz** | DMs Slack para colaboradores com NF de premio pendente. |

### 5.6 CheckMeiLimitAndNotify (Dia 30, 10:00, apenas abr/out)
| | |
|---|---|
| **O que faz** | Verificacao extra do limite MEI nos meses de premio. |

---

## 6. Cron Jobs - Notificacoes por Email (Resumo)

| Job | Frequencia | Tipo | Destinatario |
|-----|-----------|------|-------------|
| SendChargeGeneratedNotifications | 5 min | Cobranca gerada | Cliente |
| SendChargeDueSoonNotifications | Diario 09:00 | Cobranca proxima vencimento | Cliente |
| SendChargeOverdueNotifications | Diario 09:00 | Cobranca vencida | Cliente |
| ResendFailedChargeNotifications | 10 min | Retry emails falhos | Cliente |
| SendSummaryGeneratedNotifications | 5 min | Resumo gerado | Cliente |
| SendSummaryNotification | Diario 09:00 | Resumo pendente | Cliente |
| SendSummaryChargeCanceled | 5 min | Cobranca cancelada no resumo | Cliente |
| ResendFailedSummaryNotifications | 10 min | Retry resumos falhos | Cliente |
| SendNFsAlertCollab | Diario 09:30 | Alerta NF pendente | Colaborador |
| SendNFsAwardsAlertCollab | Diario 09:30 | Alerta NF premio | Colaborador |
| SendNFsSummaryCollab | Dias 4,5 10:00 | Resumo NFs recorrencia | Admin |
| SendNFsAwardsSummaryCollab | Dias 29,30 10:00 | Resumo NFs premios | Admin |
| SendSnapshotGeneratedReminder | Dia 25 09:00 | Snapshot gerado | Colaborador |
| SendRefundsPendingNotification | Diario 10:00 | Reembolsos pendentes | Admin |
| CheckCertificateNF | Diario 10:00 | Certificado expirando | Admin |

---

## 7. Cron Jobs - Notificacoes Push e Slack

| Job | Frequencia | Canal | Conteudo |
|-----|-----------|-------|---------|
| SendChargesOverduePushNotification | Diario 09:00 | Ntfy.sh | Cobrancas vencidas |
| SendSnapshotGeneratedPushReminder (recurrence) | Dia 25 09:10 | Ntfy.sh | Snapshot gerado |
| SendSnapshotGeneratedPushReminder (award) | Dia 15 abr/out 09:10 | Ntfy.sh | Snapshot premio gerado |
| NfsNotifyCollabJob | Dias 4-5, 3x/dia | Slack DM | Cobrar NF colaborador |
| NfsAwardsNotifyCollabJob | Dias 29-30 abr/out, 3x/dia | Slack DM | Cobrar NF premio |
| CheckCollabBirthdaysJob | Diario 09:30 | Slack + Email | Aniversarios |
| SendFinanceLogAlerts | 1 min | Slack | Erros financeiros |

---

## 8. Queue Jobs (Disparados por Acao)

### 8.1 ProcessPaymentJob
| | |
|---|---|
| **Disparo** | TransactionsController (validateBatch, addSameOwnership, addCollaboratorManual, testTransfer, retryTransaction), DispatchScheduledPaymentsJob |
| **Tries** | 1 (sem retry) |
| **O que faz** | 1) Busca FinanceTransaction por ID. 2) Verifica se ja processada (early return). 3) PaymentServiceFactory::make(provider). 4) Chama payBoleto() / transfer() / payPixQrCode(). 5) Em erro: status='error', log. |
| **Provider Asaas** | AsaasPaymentService: asaasPayBillPayment (boleto), asaasCreateTransfer (TED/PIX) |
| **Provider Iugu** | IuguPaymentService: POST /v1/payment_requests (boleto), POST /v1/transfer_requests (TED/PIX). RSA signature. File lock. PIX QR Code NAO suportado. |
| **Tabelas alteradas** | `finance_transactions` (status, id_asaas/id_iugu, log) |
| **APIs externas** | Asaas ou Iugu |
| **Impacto** | Processa pagamento real. Dinheiro sai da conta. |
| **Falhas possiveis** | API offline → status='error'. Barcode invalido (Iugu) → erro. Lock nao adquirido → falha. Single try = sem retry automatico. |

---

### 8.2 RunManualFinanceSync
| | |
|---|---|
| **Disparo** | SyncController@applySync (manual), RunFinanceSync (cron) |
| **Tries** | 1 |
| **Timeout** | 1800s (30 min) |
| **O que faz** | Executa 5 steps de sync sequencialmente (ver secao 3.1) |
| **Impacto** | Sync completo do modulo financeiro |
| **Falhas possiveis** | Step individual falha → continua proximos → status 'partial'. Timeout → failed() marca run como 'failed'. |

---

## 9. Webhooks Recebidos

### 9.1 Asaas Transaction Status
| | |
|---|---|
| **Endpoint** | `POST /api/asaas/transaction_status` |
| **Middleware** | AsaasWebhookMiddleware (valida asaas-access-token header) |
| **Autenticacao** | Header `asaas-access-token` comparado com tokens de TODOS os tenants. Tenant identificado pelo token que corresponde. |
| **O que faz** | Recebe evento de mudanca de status de transferencia/boleto. Busca FinanceTransaction (3 estrategias de busca). Mapeia status Asaas → interno. Atualiza transacao, transfer/pixQrcode (end_to_end_id), snapshot items. Alerta Slack para erros. |
| **Tabelas alteradas** | `finance_transactions` (status, id_asaas, paid_at, log), `finance_transactions_transfers` (end_to_end_id), `finance_transactions_pix_qrcode` (end_to_end_id), `finance_payment_collab_snapshot_items` (status) |
| **Mapeamento de status** | PENDING→processing, BANK_PROCESSING→processing, DONE→paid, CANCELLED→cancelled, FAILED→error, REFUNDED→rejected, SCHEDULED→scheduled |
| **Impacto** | Atualiza status de pagamentos em tempo real (nao depende de polling) |
| **Falhas possiveis** | Token invalido → 401. Transacao nao encontrada → silenciosamente ignora (retorna 200). Sempre retorna 200 para evitar retries Asaas. |
| **Seguranca** | Comparacao de token NAO e timing-safe (string ==). |

---

### 9.2 N8N Mail Notification
| | |
|---|---|
| **Endpoint** | `POST /api/n8n/mailNotification` |
| **Middleware** | N8nTokenMiddleware (Bearer token + X-Tenant-ID opcional) |
| **O que faz** | Recebe notificacao de N8N sobre emails recebidos. Formata mensagem com remetentes. Envia push via Ntfy. |
| **Tabelas alteradas** | Nenhuma |
| **APIs externas** | Ntfy.sh (push notification) |
| **Impacto** | Alertas de email em tempo real via push |
| **Falhas possiveis** | Token invalido → 401. Ntfy offline → erro retornado. |

---

### 9.3 Finance Webhook (Refunds + Invoices)
| | |
|---|---|
| **Endpoints** | `POST /api/finance/refunds/add`, `/refunds/get`, `/refunds/cancel`, `/invoices/add`, `/invoices/get` |
| **Middleware** | EnsureGoogleWorkspaceDomain, InitializeTenancyByHeader |
| **Autenticacao** | Dominio Google Workspace + X-Tenant-ID header |
| **addRefund** | Valida campos, faz upload do comprovante no GCS, cria FinanceRefund com status 'Pendente'. |
| **addInvoice** | Encontra colaborador por space_id, valida periodo (recorrencia: mes anterior, premio: mes atual em abr/out), faz upload PDF no GCS, extrai texto via OCR, valida valor via OpenAI, cria/atualiza FinanceInvoice. |
| **Tabelas alteradas** | `finance_refunds` (INSERT/UPDATE), `finance_invoices` (INSERT/UPDATE) |
| **APIs externas** | Google Cloud Storage (upload), Google Cloud Vision (OCR), OpenAI (validacao valor) |

---

## 10. API de Integracao (Exent Space)

| | |
|---|---|
| **Endpoints** | `GET /api/integration/collaborators`, `PUT .../pair`, `POST .../sync`, `POST .../refunds/*`, `POST .../invoices/*` |
| **Middleware** | IntegrationApiTokenMiddleware (Bearer token, timing-safe hash_equals), InitializeTenancyByHeader |
| **pair** | Vincula space_id ao colaborador. Verifica duplicidade. |
| **sync** | Recebe alteracoes do Exent Space. Detecta campos sensiveis (nome, CPF, docs, banco). Se sensivel: cria CoreCollabPendingChange status='pending' + notifica admin. Se nao sensivel: auto-aprova e aplica. |
| **Tabelas alteradas** | `core_collaborators`, `core_collab_pending_changes`, `finance_collaborator_bank_accounts` |
| **APIs externas** | GCS (upload docs staging), Slack (alerta admins), SMTP (notificacao) |

---

## 11. Cadeia de Dependencias entre Jobs

```
RunFinanceSync (cron 08:00/20:00)
  └→ RunManualFinanceSync (queue, timeout 30min)
       ├→ ClientsSyncService → Asaas API
       ├→ InvoiceCreationService → Spedy/Asaas API
       ├→ RecurrenceSyncService → finance_charges (INSERT)
       ├→ PendingChargesGenerationService → Asaas/Iugu/Spedy API
       └→ ChargesSyncService → Asaas/Iugu API

DispatchScheduledPaymentsJob (cron 09:00)
  └→ ProcessPaymentJob (queue, 1 por transacao)
       └→ PaymentServiceFactory → AsaasPaymentService / IuguPaymentService
            └→ Asaas/Iugu API (pagamento real)

GenerateRecurrenceSnapshot (cron dia 25)
  → DispatchSnapshotInvoices (cron dia 1)
       → FinanceInvoice::create
  → DispatchSnapshotTransfers (cron dia 1)
       → FinanceTransaction::create + FinanceTransactionTransfer::create
            → DispatchScheduledPaymentsJob (dia 1+) → ProcessPaymentJob
  → CloseCompletedSnapshotsJob (cron dias 1-5)

Asaas Webhook (externo, async)
  → Atualiza FinanceTransaction.status
  → Atualiza FinancePaymentCollabSnapshotItem.status
  → SlackAlertService (se erro)

Email Chain:
  SendChargeGeneratedNotifications (5min)
    → Se falha: ResendFailedChargeNotifications (10min)
  SendSummaryGeneratedNotifications (5min)
    → Se falha: ResendFailedSummaryNotifications (10min)
```

---

## 12. Mapa de Impacto por Tabela

| Tabela | Jobs que ALTERAM | Frequencia de alteracao |
|--------|-----------------|----------------------|
| `finance_charges` | RunManualFinanceSync (5 steps), CheckChargesStatus, SyncInvoiceStatus, CreatePendingInvoices, CheckAsaasInvoiceCancellationsJob, CheckTestInvoices, SendChargeGenerated*, SendChargeOverdue* | Constante (polling 2min + crons diarios) |
| `finance_transactions` | ProcessPaymentJob, CheckIuguPaymentsJob, CheckAsaasPaymentsJob, DispatchScheduledPaymentsJob, DispatchSnapshotTransfers, AsaasWebhook | Constante (polling 2min + webhook) |
| `finance_payment_collab_snapshot_items` | DispatchSnapshotInvoices, DispatchSnapshotTransfers, CheckIuguPaymentsJob, CheckAsaasPaymentsJob, AsaasWebhook | Mensal (pico dias 1-5) |
| `finance_payment_collab_snapshots` | GenerateRecurrenceSnapshot, GenerateAwardSnapshot, DispatchSnapshotInvoices, CloseCompletedSnapshotsJob | Mensal |
| `finance_invoices` | DispatchSnapshotInvoices, FinanceWebhook (addInvoice), CollabController (addInvoice) | Mensal + sob demanda |
| `finance_logs` | Todos os jobs (LogService), SendFinanceLogAlerts (alert_sent) | Constante |
| `finance_ca_statement` | SyncIuguStatementsJob, SyncAsaasStatementsJob | Diario 23:50 |
| `finance_iugu_statements` | SyncIuguStatementsJob | Diario 23:50 |
| `finance_sync_runs` | RunFinanceSync, RunManualFinanceSync | 2x/dia + manual |
| `finance_refunds` | FinanceWebhook (addRefund), SendRefundsPendingNotification | Sob demanda + diario |
| `finance_recurrence` | RunManualFinanceSync (RecurrenceSyncService) | 2x/dia |
| `finance_billing_summary_bills` | CheckBillingSummaryBillsStatus, SendSummaryGenerated* | 2x/dia + 5min |
| `finance_billing_mail_logs` | SendChargeGenerated*, SendSummaryGenerated* | Constante |
| `finance_config` | RunManualFinanceSync (sync_status.last_sync) | 2x/dia |
| `finance_invoice_test` | CheckTestInvoices | 2min |

---

## 13. Riscos e Pontos de Falha

### Criticos

| Risco | Impacto | Mitigacao atual | Recomendacao |
|-------|---------|-----------------|-------------|
| **ProcessPaymentJob tries=1** | Pagamento falha sem retry. Dinheiro nao sai. | Status='error' + log | Considerar retry com backoff para erros transientes |
| **RunManualFinanceSync tries=1, timeout=30min** | Sync incompleto. Cobrancas nao emitidas. | Status 'partial', failed() handler | Monitorar timeout. Steps independentes podem ser paralelizados |
| **Webhook Asaas retorna 200 sempre** | Asaas nao reenvia webhook se processamento falhou | Transacao nao encontrada → ignora | Log de eventos ignorados para auditoria |
| **AsaasWebhookMiddleware nao e timing-safe** | Potencial side-channel para descobrir token | Comparacao com == | Usar hash_equals() como IntegrationApiTokenMiddleware |

### Operacionais

| Risco | Impacto | Mitigacao |
|-------|---------|-----------|
| **Slack offline** | Alertas nao chegam (SendFinanceLogAlerts, NfsNotifyCollab) | alert_sent nao atualiza → retry proximo minuto |
| **SMTP offline** | Emails nao enviados | failed_mail=true → ResendFailed a cada 10min |
| **Asaas/Iugu API offline** | Status nao atualiza, pagamentos nao processam | Polling a cada 2min retenta automaticamente. Logs de erro. |
| **Spedy API offline** | NFS-e nao emitida | Retry via CreatePendingInvoices (hourly) e SyncInvoiceStatus (2min) |
| **Google Cloud Storage offline** | Upload de comprovantes/NFs falha | Log notice, operacao principal continua |
| **OpenAI offline** | Extracao de dados de NF/boleto falha | Campos retornam nulos, usuario completa manualmente |
| **Lock window sync (07:55-08:05)** | Sync manual bloqueada por 10 min | 429 retornado, usuario tenta depois |
| **SyncIuguStatementsJob only PROD** | Impossivel testar sync de extrato em dev | Restricao intencional |
| **Jobs sem error handling** | NfsNotifyCollabJob, NfsAwardsNotifyCollabJob, CloseCompletedSnapshotsJob, SendSnapshotGeneratedReminder | Exception sobe para queue worker → failed_jobs |
| **Queue worker single-threaded** | Jobs de 2min (polling Asaas/Iugu) podem acumular em tenant com muitas transacoes | queue:listen com tries=1 |

### Concorrencia

| Cenario | Risco | Mitigacao |
|---------|-------|-----------|
| Webhook Asaas + CheckAsaasPaymentsJob simultaneos | Dupla atualizacao da mesma transacao | Webhook verifica id_asaas ja existente (early return) |
| RunFinanceSync cron + SyncController manual | Dois syncs simultaneos | Lock window + verificacao de sync ativa (30min) |
| DispatchScheduledPaymentsJob + ProcessPaymentJob | Status race condition | Revalidacao antes de dispatch + re-fetch no ProcessPaymentJob |
| IuguPaymentService | Duplo pagamento | File lock via Cache (Laravel) |
