# Liquidacao

Ciclos de liquidacao, netting, reconciliacao, gestao de taxas e integracao com o cronograma BACEN.

## Pre-requisitos

- Backend PIX com Settlement Service operacional (porta 4003)
- Banco de dados com schema `monetarie_settlement` migrado
- NATS JetStream com stream `MONETARIE_SETTLEMENT` criado
- Workers de liquidacao ativos (`NATS_ENABLED=true`)
- Acesso ao portal admin com permissao `settlement`

## Visao Geral

O processo de liquidacao do PIX consolida transacoes individuais em posicoes liquidas entre participantes (netting), realiza a reconciliacao com os dados do BACEN e gera os lancamentos contabeis correspondentes.

```mermaid
flowchart TB
    subgraph Entrada["Entrada"]
        TX["Transacoes SPI<br/>(pacs.008, pacs.004)"]
        BA["Arquivo BACEN<br/>(posicoes bilaterais)"]
    end

    subgraph Liquidacao["Motor de Liquidacao"]
        SC["Scheduler<br/>(ciclos)"]
        NT["Netting<br/>(compensacao)"]
        RC["Reconciliacao<br/>(comparacao)"]
        FE["Gestao de Taxas"]
    end

    subgraph Saida["Saida"]
        AE["Eventos Contabeis"]
        QR["QR Codes"]
        EV["Eventos NATS<br/>monetarie.settlement.*"]
        WS["WebSocket<br/>settlement:status"]
    end

    TX --> SC
    BA --> SC
    SC --> NT
    NT --> RC
    RC --> FE
    FE --> AE & QR & EV & WS
```

## Ciclos de Liquidacao

### Cronograma BACEN

O PIX opera com ciclos de liquidacao definidos pelo BACEN:

| Ciclo | Horario | Tipo | Descricao |
|-------|---------|------|-----------|
| Intradiario | 08:00 - 18:00 (dias uteis) | Tempo real | Liquidacao continua no STR |
| Noturno | 18:00 - 08:00 | Batch | Consolidacao noturna |
| Final de semana | 24h | Batch | Liquidacao acumulada |
| Feriado | 24h | Batch | Igual ao final de semana |

### Scheduler Worker

O `SettlementService.Workers.Scheduler` gerencia os ciclos:

```mermaid
stateDiagram-v2
    [*] --> Aguardando
    Aguardando --> Coletando: Inicio do ciclo
    Coletando --> Calculando: Transacoes coletadas
    Calculando --> Conciliando: Netting calculado
    Conciliando --> Contabilizando: Reconciliacao OK
    Contabilizando --> Finalizado: Lancamentos criados
    Finalizado --> Aguardando: Proximo ciclo

    Calculando --> Erro: Discrepancia encontrada
    Erro --> Aguardando: Intervencao manual
```

| Parametro | Valor | Descricao |
|-----------|-------|-----------|
| Stream | MONETARIE_SETTLEMENT | Stream JetStream |
| Consumer | `settlement-sched` | Consumer duravel |
| AckWait | 60s | Timeout de processamento |
| MaxDeliver | 3 | Tentativas maximas |
| Query LIMIT | 500.000 | Limite de transacoes por ciclo |
| Query Timeout | 30s | Timeout da query de transacoes |

::: warning LIMITE DE TRANSACOES
O Scheduler possui um `LIMIT 500000` + `timeout 30s` nas queries de transacoes para prevenir OOM (Out of Memory) em ciclos com volume muito alto. Se o ciclo possuir mais de 500K transacoes, sera processado em multiplos batches.
:::

## Netting (Compensacao)

O processo de netting calcula a posicao liquida de cada participante:

### Exemplo

```mermaid
flowchart LR
    subgraph Transacoes["Transacoes do Ciclo"]
        T1["MONETARIE -> MW: R$ 1.000"]
        T2["MW -> MONETARIE: R$ 700"]
        T3["MONETARIE -> MW: R$ 500"]
        T4["MW -> MONETARIE: R$ 300"]
    end

    subgraph Netting["Posicao Liquida"]
        N1["MONETARIE deve: R$ 1.500"]
        N2["MONETARIE recebe: R$ 1.000"]
        N3["Posicao: MONETARIE deve<br/>R$ 500 para MW"]
    end

    T1 & T2 & T3 & T4 --> N1 & N2 --> N3
```

### Tabela de Netting

| Campo | Tipo | Descricao |
|-------|------|-----------|
| `id` | UUID | ID do registro de netting |
| `cycle_id` | UUID | ID do ciclo de liquidacao |
| `participant_ispb` | CHAR(8) | ISPB do participante |
| `counterparty_ispb` | CHAR(8) | ISPB da contraparte |
| `debit_total` | Decimal(18,2) | Total de debitos no ciclo |
| `credit_total` | Decimal(18,2) | Total de creditos no ciclo |
| `net_position` | Decimal(18,2) | Posicao liquida |
| `transaction_count` | Integer | Numero de transacoes |
| `status` | String | pending, calculated, settled |

## Reconciliacao

A reconciliacao compara os dados internos com as posicoes reportadas pelo BACEN:

```mermaid
flowchart TB
    subgraph Interno["Dados Internos"]
        TXI["Transacoes SPI<br/>(monetarie_spi.messages)"]
        NTI["Netting Calculado"]
    end

    subgraph BACEN["Dados BACEN"]
        POS["Posicoes Bilaterais<br/>(arquivo LBTR)"]
        STL["Registro de Liquidacao"]
    end

    subgraph Reconciliacao
        CMP["Comparar posicoes"]
        DSC["Identificar discrepancias"]
        RPT["Gerar relatorio"]
    end

    TXI --> NTI --> CMP
    POS --> CMP
    STL --> CMP
    CMP --> DSC --> RPT
```

### Tipos de Discrepancia

| Tipo | Descricao | Severidade |
|------|-----------|------------|
| `amount_mismatch` | Valor difere entre interno e BACEN | Alta |
| `missing_internal` | Transacao no BACEN sem correspondente interno | Critica |
| `missing_external` | Transacao interna sem correspondente no BACEN | Alta |
| `status_mismatch` | Status divergente | Media |
| `timing_mismatch` | Timestamp fora da tolerancia | Baixa |

::: warning LIMITE DE QUERIES
A funcao `identify_discrepancies` possui um `LIMIT 10000` para evitar queries sem limite em tabelas grandes. O mesmo se aplica a `list_runs` e `perform_reconciliation`.
:::

### FileImporter Worker

O `SettlementService.Workers.FileImporter` importa arquivos de posicao do BACEN:

| Parametro | Valor |
|-----------|-------|
| Stream | MONETARIE_SETTLEMENT |
| Consumer | `settlement-files` |
| Filter | `monetarie.settlement.files.>` |
| AckWait | 60s |
| MaxDeliver | 3 |

## Gestao de Taxas

### Tabela de Taxas

| Campo | Tipo | Descricao |
|-------|------|-----------|
| `id` | UUID | ID da taxa |
| `fee_type` | String | Tipo: transaction, settlement, monthly |
| `participant_ispb` | CHAR(8) | ISPB do participante |
| `amount` | Decimal(18,2) | Valor da taxa |
| `percentage` | Decimal(5,4) | Percentual (se aplicavel) |
| `effective_date` | Date | Data de vigencia |
| `status` | String | active, inactive |

### Tipos de Taxa

| Tipo | Descricao | Cobranca |
|------|-----------|----------|
| `transaction` | Taxa por transacao PIX | Por transacao |
| `settlement` | Taxa de liquidacao | Por ciclo |
| `monthly` | Taxa mensal de participacao | Mensal |
| `qr_code` | Taxa de geracao de QR Code | Por QR gerado |

## QR Codes

O Settlement Service gerencia a geracao de QR Codes PIX:

| Tipo | Descricao |
|------|-----------|
| QR Code Estatico | Valor fixo ou aberto, reutilizavel |
| QR Code Dinamico | Valor e referencia unicos, uso unico |
| QR Code Dinamico com vencimento | Inclui data de vencimento |

### Tabela QR Codes

| Campo | Tipo | Descricao |
|-------|------|-----------|
| `id` | UUID | ID do QR Code |
| `type` | String | static, dynamic, dynamic_due_date |
| `pix_key` | String | Chave PIX associada |
| `amount` | Integer | Valor em centavos (null para estatico aberto) |
| `description` | String | Descricao do pagamento |
| `expiration` | DateTime | Data de expiracao (dinamicos) |
| `emv_payload` | Text | Payload EMV completo |

## Status de Liquidacao via WebSocket

O canal `settlement:status` transmite atualizacoes em tempo real:

```json
{
  "cycle": {
    "id": "uuid",
    "status": "calculating",
    "started_at": "2026-02-13T14:00:00Z",
    "transaction_count": 15420,
    "total_amount": 45678900
  },
  "netting": {
    "participants": 45,
    "positions_calculated": 38,
    "total_positions": 45
  },
  "reconciliation": {
    "status": "pending",
    "discrepancies": 0
  }
}
```

## Circuit Breaker (Chamadas Internas)

O Settlement Service usa circuit breaker para chamadas internas ao DICT e SPI:

```mermaid
stateDiagram-v2
    [*] --> Closed: Normal
    Closed --> Open: 5 falhas consecutivas
    Open --> HalfOpen: 30s cooldown
    HalfOpen --> Closed: Probe OK
    HalfOpen --> Open: Probe falha
```

| Parametro | Valor |
|-----------|-------|
| Threshold | 5 falhas |
| Cooldown | 30 segundos |
| Probe | 1 requisicao de teste em half-open |
| Storage | ETS (`:circuit_breaker_state`) |
| Concorrencia | `:ets.update_counter/4` (atomico) |
| Telemetria | `pix_circuit_breaker_state_change_total` |

::: info APENAS ERROS 5XX
O circuit breaker so e ativado por erros 5xx e erros de transporte (timeout, conexao recusada). Erros 4xx sao considerados erros do cliente e nao afetam o estado do circuit breaker.
:::

## Eventos NATS de Liquidacao

| Subject | Descricao |
|---------|-----------|
| `monetarie.settlement.cycle.started` | Ciclo de liquidacao iniciado |
| `monetarie.settlement.cycle.completed` | Ciclo concluido |
| `monetarie.settlement.netting.calculated` | Netting calculado |
| `monetarie.settlement.reconciliation.completed` | Reconciliacao concluida |
| `monetarie.settlement.reconciliation.discrepancy` | Discrepancia encontrada |

## Resultado Esperado

Apos configurar a liquidacao:

- O Scheduler executa ciclos de liquidacao conforme cronograma BACEN
- O netting calcula posicoes liquidas entre participantes corretamente
- A reconciliacao identifica e reporta discrepancias
- As taxas sao aplicadas e contabilizadas automaticamente
- O canal WebSocket `settlement:status` transmite atualizacoes em tempo real
- O circuit breaker protege chamadas internas contra cascata de falhas
- Eventos NATS sao publicados para cada etapa do processo
- Queries de reconciliacao possuem LIMIT para prevenir OOM
