# API do AgendAI (leitura) — Comissões

Guia de uso (login, convenções, erros): https://api-docs.agendai.pro/md/guia.md


Comissões de venda por vendedor e seu ciclo de liberação.

- `GET /comissoes` — Lista paginada de comissões de venda
- `GET /comissoes/resumo` — Totais de comissões por etapa do fluxo
- `GET /comissoes/filter-options` — Opções para os filtros de comissões
- `GET /comissoes/{id}` — Detalhe de uma comissão

### GET /comissoes

**Lista paginada de comissões de venda** · operationId `listarComissoes`

Autenticação: `Authorization: Bearer <token>`.

Lista as comissões de venda (padrão e especiais, misturadas) visíveis ao usuário, com paginação feita em memória sobre o resultado filtrado.

**Ordenação:** só comissões padrão: `dataElegibilidade` decrescente (as ainda sem data, isto é, pendentes, vêm primeiro) e depois criação decrescente. Com comissões especiais no resultado, tudo é reordenado por data decrescente usando `dataElegibilidade`, senão `dataVendaConclusao`, senão criação.
**Paginação:** `page` e `pageSize` fora do intervalo não geram erro: são ajustados (page mínimo 1; pageSize entre 1 e 500; valor não numérico vale o padrão).
Resposta: `{ data: [...], pagination: { page, pageSize, total, totalPages } }`. Cada item é do formato padrão ou especial (`tipoComissao`).

Valores monetários em **reais** (número JSON), percentuais de 0 a 100, datas ISO 8601 (UTC).

**Sem efeito colateral:** é só leitura. Comissões `PENDENTE_REGRA` passam a `PENDENTE_CONFERENCIA` quando uma regra de comissão vigente é criada ou alterada, não numa consulta.

**Permissão:** capacidade `LER_COMISSOES`. Sem ela, 403 ("Usuário sem permissão para acessar o módulo de comissões."). Em geral: usuário de tipo `ADMIN` ou `COMERCIAL`; com acesso por setor ligado, administrador pleno ou membro/gestor do setor Comercial.
**Escopo de registros:** modo legado: `type ADMIN` ou usuário com `is_admin` vê todas as comissões da organização; usuário `COMERCIAL` sem `is_admin` vê só as do vendedor vinculado ao seu usuário. Com acesso por setor ligado: Dono/Admin e gestor do Comercial veem todas; membro do Comercial vê só as do vendedor vinculado. Sem o interruptor `ESCOPO_COMERCIAL`, um membro do Comercial que também pertence a outro setor pode ver todas. Sem vínculo de vendedor, ou com mais de um, **não há erro: lista vazia / zeros** (404 no detalhe).

### Ciclo de status da comissão padrão

1. `PENDENTE_REGRA`: o vendedor é comissionado, mas não há regra de comissão ativa e vigente (vendedor + produto + tipo de projeto) na data da venda. Vira `PENDENTE_CONFERENCIA` assim que a regra existe.
2. `PENDENTE_CONFERENCIA`: regra resolvida; percentuais congelados (`percentualPrimeiraParcelaSnapshot`, `percentualServicoSnapshot`); aguardando a **conferência da venda**, feita manualmente por gestão ou automaticamente na aprovação do formulário.
3. `PENDENTE_ELEGIBILIDADE`: venda conferida (`conferidaEm` preenchido); aguarda a **primeira OS paga**.
4. `ELEGIVEL`: liberada para pagamento. Acontece quando a **primeira OS do projeto/contrato muda para `PAGO` no Omie** (`primeiraOsPagaId` e `dataElegibilidade` são gravados e os valores calculados). Atalhos: sem projeto (importada, ou formulário que não gera projeto) ou projeto não faturável pelo financeiro, a conferência já libera a comissão sem depender de OS; o mesmo vale para venda sem comissão de serviço cujo SaaS foi conferido. Se a OS foi paga antes da conferência, a conferência já a encontra. Se a OS vinculada for cancelada/excluída e outra OS for paga, a comissão é revinculada à nova.
5. `FECHADA`: congelada em um fechamento de período (`fechamentoId`); continua apta a pagamento.
6. `PAGA_PARCIAL`: um componente pago (`SERVICO` ou `PRIMEIRA_PARCELA`) e o outro não.
7. `PAGA`: todos os componentes aplicáveis pagos (`pagaEm` = o pagamento mais recente).
8. `CANCELADA`: a OS ligada à comissão foi cancelada ou excluída no Omie antes da elegibilidade. Se uma OS for paga depois, a comissão é revivida ao estágio em que estava. Não há cancelamento manual.

O pagamento exige conferência final registrada (feita por administrador); esses passos são escritas e não fazem parte desta documentação de leitura.

**Componentes:** `SERVICO` (comissão sobre o serviço/implantação) e `PRIMEIRA_PARCELA` (comissão sobre a primeira parcela do SaaS/mensalidade). Cada um tem conferência e pagamento próprios em `componentes`. `valorComissao` é a soma dos dois; percentuais são de 0 a 100; valores em **reais**, números JSON (a API converte os decimais do banco para número).

**Comissões especiais** (`tipoComissao = ESPECIAL`) são comissões adicionais para outro vendedor beneficiário, derivadas de uma comissão padrão por uma regra especial. Têm ciclo próprio: `ABERTA` -> `CONFERIDA` -> `PAGA` (ou `CANCELADA`), um único componente cada, e não pertencem a fechamento.

**Campos expostos:** a resposta tem forma explícita. Não saem colunas internas (organização, arquivo de importação, conferência final) nem o e-mail do vendedor. Os campos `*PorId` são ids (UUID) de usuários do AgendAI.

#### Parâmetros

| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| `page` | query | integer; padrão `1`; mín. 1 | não | Página, base 1. Não numérico ou menor que 1 vira 1; valor fracionário não é arredondado (envie inteiro). Ex.: `1` |
| `pageSize` | query | integer; padrão `20`; mín. 1; máx. 500 | não | Itens por página; limitado a 1-500. Não numérico ou 0 vale 20. Ex.: `20` |
| `status` | query | lista de string — um de: `PENDENTE_REGRA`, `PENDENTE_CONFERENCIA`, `PENDENTE_ELEGIBILIDADE`, `ELEGIVEL`, `FECHADA`, `PAGA_PARCIAL`, `PAGA`, `CANCELADA`, `ABERTA`, `CONFERIDA` | não | Filtra por status. Aceita parâmetro repetido ou lista separada por vírgula. Valores de comissão padrão: `PENDENTE_REGRA`, `PENDENTE_CONFERENCIA`, `PENDENTE_ELEGIBILIDADE`, `ELEGIVEL`, `FECHADA`, `PAGA_PARCIAL`, `PAGA`, `CANCELADA`; de comissão especial: `ABERTA`, `CONFERIDA`, `PAGA`, `CANCELADA`. Valores desconhecidos são **ignorados sem erro**; cada tipo de comissão só é filtrado pelos valores que reconhece (se nenhum valor da lista é válido para um tipo, esse tipo some do resultado). Ex.: `["ELEGIVEL","PAGA_PARCIAL"]` |
| `vendedorId` | query | string (uuid) | não | Id (UUID) do vendedor; para comissão especial, o beneficiário. UUID inválido (inclusive texto vazio) responde 400. Ex.: `2d4f6a80-1b3c-4e5f-8a7b-9c0d1e2f3a4b` |
| `fechamentoId` | query | string (uuid) | não | Id (UUID) de um fechamento. Comissões especiais não pertencem a fechamento: com este filtro elas são excluídas. |
| `dataVendaInicio` | query | string (date) | não | Início do período, inclusivo. Prefira `YYYY-MM-DD` (vira 00:00:00.000Z do dia, UTC); qualquer texto que `new Date()` entenda é aceito, e texto não interpretável responde 400 ("Data inválida para o domínio de comissões."). **Sem `componente`**, compara com a data da venda/conclusão (`dataVendaConclusao`; nas especiais, `dataReferenciaVenda`). **Com `componente`**, comissões de formulário passam a ser comparadas com a data de assinatura do contrato do componente (serviço ou SaaS) do formulário, e as sem formulário (`formularioId` nulo) com a data da venda. Ex.: `2026-10-01` |
| `dataVendaFim` | query | string (date) | não | Fim do período, inclusivo até 23:59:59.999Z do dia. Mesmas regras de `dataVendaInicio`. Ex.: `2026-10-31` |
| `componente` | query | string — um de: `SERVICO`, `PRIMEIRA_PARCELA` | não | Mostra só comissões em que o componente é aplicável (valor > 0): `SERVICO` ou `PRIMEIRA_PARCELA` (SaaS/mensalidade). Comissões ligadas a formulário só entram se o formulário tiver a data de assinatura do contrato desse componente (`contratoDataAssinaturaServico` / `contratoDataAssinaturaSaas`), mesmo sem filtro de data; comissões sem formulário entram sempre. Entre as que passam por esse corte, as `PENDENTE_REGRA` aparecem mesmo sem valor. Nas especiais, filtra pelo `componente` da especial. Texto vazio é ignorado; outro valor responde 400. Também muda a base do filtro de data (ver `dataVendaInicio`). Ex.: `SERVICO` |
| `produtoId` | query | string (uuid) | não | Id (UUID) do produto. UUID inválido responde 400. |
| `classe` | query | string — um de: `NOVO`, `ADITIVO` | não | `ADITIVO` quando o tipo de projeto se chama "Aditivo" (sem diferenciar acento/caixa); `NOVO` para todos os demais. Outro valor responde 400. Ex.: `NOVO` |

#### Resposta 200

Página de comissões.

Tipo da raiz: object

| Campo | Tipo | Sempre presente | Descrição |
|---|---|---|---|
| `data` | lista de ComissoesComissaoPadrao \| ComissoesComissaoEspecial | sim |  |
| `pagination` | object | sim |  |
| `pagination.page` | integer | sim | Página atual. |
| `pagination.pageSize` | integer | sim | Itens por página (após ajuste). |
| `pagination.total` | integer | sim | Total de comissões (padrão + especiais) que passam nos filtros. |
| `pagination.totalPages` | integer | sim | Total de páginas (`0` quando `total = 0`). |

Exemplo (dados fictícios):

```json
{
  "data": [
    {
      "id": "c1a2b3c4-d5e6-4f70-8a91-b2c3d4e5f607",
      "tipoComissao": "PADRAO",
      "origem": "FORMULARIO",
      "formularioId": "f0e1d2c3-b4a5-4968-8776-5a4b3c2d1e0f",
      "projetoId": "7e3d1c20-9a54-4d3b-8f21-0c6b5a4d3e22",
      "vendedorId": "2d4f6a80-1b3c-4e5f-8a7b-9c0d1e2f3a4b",
      "produtoId": "5f0c1e7a-8d2b-4a39-b0c4-1e2d3c4b5a69",
      "tipoProjetoId": "a1b2c3d4-0000-4000-8000-000000000001",
      "regraId": "d9c8b7a6-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
      "importacaoReferenciaExterna": null,
      "clienteSnapshot": null,
      "projetoSnapshot": null,
      "vendedorNomeSnapshot": null,
      "produtoSnapshot": null,
      "tipoProjetoSnapshot": null,
      "contratoId": 912,
      "primeiraOsPagaId": 48213,
      "fechamentoId": null,
      "status": "ELEGIVEL",
      "dataVendaConclusao": "2026-09-28T00:00:00.000Z",
      "dataBaseRegra": "2026-09-28T00:00:00.000Z",
      "percentualPrimeiraParcelaSnapshot": 50,
      "percentualServicoSnapshot": 5,
      "regraVigenciaInicio": "2026-01-01T00:00:00.000Z",
      "regraVigenciaFim": null,
      "baseCalculoPrimeiraParcela": 1200,
      "valorComissaoPrimeiraParcela": 600,
      "baseCalculoServico": 10000,
      "valorComissaoServico": 500,
      "baseCalculo": 11200,
      "valorComissao": 1100,
      "dataElegibilidade": "2026-10-20T13:05:00.000Z",
      "conferidaEm": "2026-10-05T14:20:00.000Z",
      "conferidaPorId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
      "observacaoConferencia": null,
      "primeiraParcelaConferidaEm": "2026-10-05T14:20:00.000Z",
      "primeiraParcelaConferidaPorId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
      "observacaoConferenciaPrimeiraParcela": null,
      "primeiraParcelaPagaEm": null,
      "primeiraParcelaPagaPorId": null,
      "servicoPagoEm": null,
      "servicoPagoPorId": null,
      "observacaoPagamentoServico": null,
      "observacaoPagamentoPrimeiraParcela": null,
      "pagaEm": null,
      "pagaPorId": null,
      "observacaoOperacional": "Comissão elegível pela primeira OS paga confirmada no Omie.",
      "createdAt": "2026-09-28T17:00:00.000Z",
      "updatedAt": "2026-10-20T13:05:00.000Z",
      "vendedor": {
        "id": "2d4f6a80-1b3c-4e5f-8a7b-9c0d1e2f3a4b",
        "nome": "Vendedor Exemplo"
      },
      "produto": {
        "id": "5f0c1e7a-8d2b-4a39-b0c4-1e2d3c4b5a69",
        "produto": "Plataforma Exemplo"
      },
      "tipoProjeto": {
        "id": "a1b2c3d4-0000-4000-8000-000000000001",
        "tipoProjeto": "Implantação",
        "status": true
      },
      "fechamento": null,
      "cliente": {
        "id": "0b6a1d52-3f0e-4c6a-9d0e-5a1f2f6d7a11",
        "nomeEmpresa": "Empresa Alfa Ltda"
      },
      "projeto": {
        "nomeProjeto": "Implantação Alfa",
        "quantidadeHoras": 100,
        "valorHora": 100
      },
      "contrato": {
        "id": 912,
        "tipoContrato": "SERVICO",
        "numCtr": "CTR-0091",
        "codStatus": "ATIVO",
        "descStatus": "Ativo",
        "valorTotalMensal": 1200,
        "diaFaturamento": 10,
        "vigenciaInicio": "2026-09-01T00:00:00.000Z",
        "vigenciaFim": "2027-08-31T00:00:00.000Z",
        "pagamentoStatus": "PAGA",
        "dataPrimeiroRecebimento": "2026-10-20T00:00:00.000Z"
      },
      "primeiraOsPaga": {
        "id": 48213,
        "numOs": "000412",
        "codStatus": "PAGO",
        "descStatus": "Pago",
        "valorTotal": 10000,
        "dataFaturamento": "2026-10-01T00:00:00.000Z",
        "dataVencimento": "2026-10-10T00:00:00.000Z",
        "quantidadeParcelas": 1,
        "pagamentoStatus": "PAGA",
        "dataPrimeiroRecebimento": "2026-10-20T00:00:00.000Z"
      },
      "primeiraOsPendente": null,
      "componentes": {
        "SERVICO": {
          "aplicavel": true,
          "aptoPagamento": true,
          "conferencia": {
            "status": "CONFERIDO",
            "em": "2026-10-05T14:20:00.000Z",
            "porId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
            "observacao": null
          },
          "pagamento": {
            "status": "PENDENTE",
            "em": null,
            "porId": null,
            "observacao": null
          }
        },
        "PRIMEIRA_PARCELA": {
          "aplicavel": true,
          "aptoPagamento": true,
          "conferencia": {
            "status": "CONFERIDO",
            "em": "2026-10-05T14:20:00.000Z",
            "porId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
            "observacao": null
          },
          "pagamento": {
            "status": "PENDENTE",
            "em": null,
            "porId": null,
            "observacao": null
          }
        }
      }
    }
  ],
  "pagination": {
    "page": 1,
    "pageSize": 20,
    "total": 1,
    "totalPages": 1
  }
}
```

#### Erros

- **400**: Parâmetros inválidos. `message` é uma lista com um item por problema, no formato `campo: motivo`.
- **401**: Token ausente, inválido, expirado ou de usuário desativado. Faça login de novo.
- **403**: O usuário do token não tem a permissão exigida pela rota.

---

### GET /comissoes/resumo

**Totais de comissões por etapa do fluxo** · operationId `obterResumoComissoes`

Autenticação: `Authorization: Bearer <token>`.

Soma quantidade e valor das comissões visíveis por etapa do fluxo, com os mesmos filtros de `GET /comissoes` (sem paginação). Resposta: `{ cards: { pendenteRegra, pendenteConferencia, pendenteElegibilidade, prontaPagamento, paga } }`.

Mapeamento dos cartões: `pendenteRegra` = `PENDENTE_REGRA`; `pendenteConferencia` = `PENDENTE_CONFERENCIA` + especiais `ABERTA`; `pendenteElegibilidade` = `PENDENTE_ELEGIBILIDADE`; `prontaPagamento` = `ELEGIVEL` + `FECHADA` + `PAGA_PARCIAL` + especiais `CONFERIDA`; `paga` = `PAGA` + especiais `PAGA`. `CANCELADA` não entra em nenhum. Valores em **reais**.

Armadilhas: em `prontaPagamento`, comissões `PAGA_PARCIAL` contribuem só com o valor ainda não pago. Em `pendenteRegra`, o valor é a base de serviço estimada do projeto (horas x valor da hora), pois ainda não há comissão calculada. O filtro `status` limita o que entra, mas os cartões continuam sendo por etapa (um cartão fora do filtro fica zerado).

**Sem efeito colateral:** é só leitura. Comissões `PENDENTE_REGRA` passam a `PENDENTE_CONFERENCIA` quando uma regra de comissão vigente é criada ou alterada, não numa consulta.

**Permissão:** capacidade `LER_COMISSOES`. Sem ela, 403 ("Usuário sem permissão para acessar o módulo de comissões."). Em geral: usuário de tipo `ADMIN` ou `COMERCIAL`; com acesso por setor ligado, administrador pleno ou membro/gestor do setor Comercial.
**Escopo de registros:** modo legado: `type ADMIN` ou usuário com `is_admin` vê todas as comissões da organização; usuário `COMERCIAL` sem `is_admin` vê só as do vendedor vinculado ao seu usuário. Com acesso por setor ligado: Dono/Admin e gestor do Comercial veem todas; membro do Comercial vê só as do vendedor vinculado. Sem o interruptor `ESCOPO_COMERCIAL`, um membro do Comercial que também pertence a outro setor pode ver todas. Sem vínculo de vendedor, ou com mais de um, **não há erro: lista vazia / zeros** (404 no detalhe).

### Ciclo de status da comissão padrão

1. `PENDENTE_REGRA`: o vendedor é comissionado, mas não há regra de comissão ativa e vigente (vendedor + produto + tipo de projeto) na data da venda. Vira `PENDENTE_CONFERENCIA` assim que a regra existe.
2. `PENDENTE_CONFERENCIA`: regra resolvida; percentuais congelados (`percentualPrimeiraParcelaSnapshot`, `percentualServicoSnapshot`); aguardando a **conferência da venda**, feita manualmente por gestão ou automaticamente na aprovação do formulário.
3. `PENDENTE_ELEGIBILIDADE`: venda conferida (`conferidaEm` preenchido); aguarda a **primeira OS paga**.
4. `ELEGIVEL`: liberada para pagamento. Acontece quando a **primeira OS do projeto/contrato muda para `PAGO` no Omie** (`primeiraOsPagaId` e `dataElegibilidade` são gravados e os valores calculados). Atalhos: sem projeto (importada, ou formulário que não gera projeto) ou projeto não faturável pelo financeiro, a conferência já libera a comissão sem depender de OS; o mesmo vale para venda sem comissão de serviço cujo SaaS foi conferido. Se a OS foi paga antes da conferência, a conferência já a encontra. Se a OS vinculada for cancelada/excluída e outra OS for paga, a comissão é revinculada à nova.
5. `FECHADA`: congelada em um fechamento de período (`fechamentoId`); continua apta a pagamento.
6. `PAGA_PARCIAL`: um componente pago (`SERVICO` ou `PRIMEIRA_PARCELA`) e o outro não.
7. `PAGA`: todos os componentes aplicáveis pagos (`pagaEm` = o pagamento mais recente).
8. `CANCELADA`: a OS ligada à comissão foi cancelada ou excluída no Omie antes da elegibilidade. Se uma OS for paga depois, a comissão é revivida ao estágio em que estava. Não há cancelamento manual.

O pagamento exige conferência final registrada (feita por administrador); esses passos são escritas e não fazem parte desta documentação de leitura.

**Componentes:** `SERVICO` (comissão sobre o serviço/implantação) e `PRIMEIRA_PARCELA` (comissão sobre a primeira parcela do SaaS/mensalidade). Cada um tem conferência e pagamento próprios em `componentes`. `valorComissao` é a soma dos dois; percentuais são de 0 a 100; valores em **reais**, números JSON (a API converte os decimais do banco para número).

**Comissões especiais** (`tipoComissao = ESPECIAL`) são comissões adicionais para outro vendedor beneficiário, derivadas de uma comissão padrão por uma regra especial. Têm ciclo próprio: `ABERTA` -> `CONFERIDA` -> `PAGA` (ou `CANCELADA`), um único componente cada, e não pertencem a fechamento.

#### Parâmetros

| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| `status` | query | lista de string — um de: `PENDENTE_REGRA`, `PENDENTE_CONFERENCIA`, `PENDENTE_ELEGIBILIDADE`, `ELEGIVEL`, `FECHADA`, `PAGA_PARCIAL`, `PAGA`, `CANCELADA`, `ABERTA`, `CONFERIDA` | não | Filtra por status. Aceita parâmetro repetido ou lista separada por vírgula. Valores de comissão padrão: `PENDENTE_REGRA`, `PENDENTE_CONFERENCIA`, `PENDENTE_ELEGIBILIDADE`, `ELEGIVEL`, `FECHADA`, `PAGA_PARCIAL`, `PAGA`, `CANCELADA`; de comissão especial: `ABERTA`, `CONFERIDA`, `PAGA`, `CANCELADA`. Valores desconhecidos são **ignorados sem erro**; cada tipo de comissão só é filtrado pelos valores que reconhece (se nenhum valor da lista é válido para um tipo, esse tipo some do resultado). Ex.: `["ELEGIVEL","PAGA_PARCIAL"]` |
| `vendedorId` | query | string (uuid) | não | Id (UUID) do vendedor; para comissão especial, o beneficiário. UUID inválido (inclusive texto vazio) responde 400. Ex.: `2d4f6a80-1b3c-4e5f-8a7b-9c0d1e2f3a4b` |
| `fechamentoId` | query | string (uuid) | não | Id (UUID) de um fechamento. Comissões especiais não pertencem a fechamento: com este filtro elas são excluídas. |
| `dataVendaInicio` | query | string (date) | não | Início do período, inclusivo. Prefira `YYYY-MM-DD` (vira 00:00:00.000Z do dia, UTC); qualquer texto que `new Date()` entenda é aceito, e texto não interpretável responde 400 ("Data inválida para o domínio de comissões."). **Sem `componente`**, compara com a data da venda/conclusão (`dataVendaConclusao`; nas especiais, `dataReferenciaVenda`). **Com `componente`**, comissões de formulário passam a ser comparadas com a data de assinatura do contrato do componente (serviço ou SaaS) do formulário, e as sem formulário (`formularioId` nulo) com a data da venda. Ex.: `2026-10-01` |
| `dataVendaFim` | query | string (date) | não | Fim do período, inclusivo até 23:59:59.999Z do dia. Mesmas regras de `dataVendaInicio`. Ex.: `2026-10-31` |
| `componente` | query | string — um de: `SERVICO`, `PRIMEIRA_PARCELA` | não | Mostra só comissões em que o componente é aplicável (valor > 0): `SERVICO` ou `PRIMEIRA_PARCELA` (SaaS/mensalidade). Comissões ligadas a formulário só entram se o formulário tiver a data de assinatura do contrato desse componente (`contratoDataAssinaturaServico` / `contratoDataAssinaturaSaas`), mesmo sem filtro de data; comissões sem formulário entram sempre. Entre as que passam por esse corte, as `PENDENTE_REGRA` aparecem mesmo sem valor. Nas especiais, filtra pelo `componente` da especial. Texto vazio é ignorado; outro valor responde 400. Também muda a base do filtro de data (ver `dataVendaInicio`). Ex.: `SERVICO` |
| `produtoId` | query | string (uuid) | não | Id (UUID) do produto. UUID inválido responde 400. |
| `classe` | query | string — um de: `NOVO`, `ADITIVO` | não | `ADITIVO` quando o tipo de projeto se chama "Aditivo" (sem diferenciar acento/caixa); `NOVO` para todos os demais. Outro valor responde 400. Ex.: `NOVO` |

#### Resposta 200

Totais por etapa.

Tipo da raiz: ComissoesResumoResponse

| Campo | Tipo | Sempre presente | Descrição |
|---|---|---|---|
| `cards` | object | sim |  |
| `cards.pendenteRegra` | object | sim | Sem regra de comissão vigente. `valorComissaoTotal` aqui é a base de serviço estimada do projeto (horas x valor da hora) quando existe, não uma comissão calculada. |
| `cards.pendenteRegra.totalComissoes` | integer | sim | Quantidade de comissões (padrão + especiais) em `PENDENTE_REGRA`. |
| `cards.pendenteRegra.valorComissaoTotal` | number | sim | Valor total em reais. |
| `cards.pendenteConferencia` | object | sim | Aguardando conferência da venda. |
| `cards.pendenteConferencia.totalComissoes` | integer | sim | Quantidade de comissões (padrão + especiais) em `PENDENTE_CONFERENCIA` (mais especiais `ABERTA`). |
| `cards.pendenteConferencia.valorComissaoTotal` | number | sim | Valor total em reais. |
| `cards.pendenteElegibilidade` | object | sim | Venda conferida, aguardando a primeira OS paga. |
| `cards.pendenteElegibilidade.totalComissoes` | integer | sim | Quantidade de comissões (padrão + especiais) em `PENDENTE_ELEGIBILIDADE`. |
| `cards.pendenteElegibilidade.valorComissaoTotal` | number | sim | Valor total em reais. |
| `cards.prontaPagamento` | object | sim | Comissões `ELEGIVEL`, `FECHADA` ou `PAGA_PARCIAL` (mais especiais `CONFERIDA`). Para `PAGA_PARCIAL` conta só o que ainda falta pagar. |
| `cards.prontaPagamento.totalComissoes` | integer | sim | Quantidade de comissões prontas para pagamento. |
| `cards.prontaPagamento.valorComissaoTotal` | number | sim | Valor total em reais (saldo a pagar nas parcialmente pagas). |
| `cards.prontaPagamento.valorComissaoPrimeiraParcelaPendente` | number | sim | Parte do saldo que é componente primeira parcela/SaaS ainda não pago, em reais. |
| `cards.prontaPagamento.valorComissaoServicoPendente` | number | sim | Parte do saldo que é componente serviço ainda não pago, em reais. |
| `cards.paga` | object | sim | Totalmente paga. |
| `cards.paga.totalComissoes` | integer | sim | Quantidade de comissões (padrão + especiais) em `PAGA` (mais especiais `PAGA`). |
| `cards.paga.valorComissaoTotal` | number | sim | Valor total em reais. |

Exemplo (dados fictícios):

```json
{
  "cards": {
    "pendenteRegra": {
      "totalComissoes": 1,
      "valorComissaoTotal": 8000
    },
    "pendenteConferencia": {
      "totalComissoes": 2,
      "valorComissaoTotal": 2300
    },
    "pendenteElegibilidade": {
      "totalComissoes": 3,
      "valorComissaoTotal": 4100.5
    },
    "prontaPagamento": {
      "totalComissoes": 4,
      "valorComissaoTotal": 5200,
      "valorComissaoPrimeiraParcelaPendente": 1800,
      "valorComissaoServicoPendente": 3400
    },
    "paga": {
      "totalComissoes": 6,
      "valorComissaoTotal": 9100
    }
  }
}
```

#### Erros

- **400**: Parâmetros inválidos. `message` é uma lista com um item por problema, no formato `campo: motivo`.
- **401**: Token ausente, inválido, expirado ou de usuário desativado. Faça login de novo.
- **403**: O usuário do token não tem a permissão exigida pela rota.

---

### GET /comissoes/filter-options

**Opções para os filtros de comissões** · operationId `listarOpcoesFiltroComissoes`

Autenticação: `Authorization: Bearer <token>`.

Devolve os valores que alimentam os filtros de `GET /comissoes`: status existentes, vendedores, produtos e fechamentos, **somente a partir do que o usuário pode ver** (mesmo escopo de registros da listagem). Não recebe parâmetros.

Resposta: `{ statuses, vendedores, produtos, fechamentos }`.

**Sem efeito colateral:** é só leitura. Comissões `PENDENTE_REGRA` passam a `PENDENTE_CONFERENCIA` quando uma regra de comissão vigente é criada ou alterada, não numa consulta.

**Permissão:** capacidade `LER_COMISSOES`. Sem ela, 403 ("Usuário sem permissão para acessar o módulo de comissões."). Em geral: usuário de tipo `ADMIN` ou `COMERCIAL`; com acesso por setor ligado, administrador pleno ou membro/gestor do setor Comercial.
**Escopo de registros:** modo legado: `type ADMIN` ou usuário com `is_admin` vê todas as comissões da organização; usuário `COMERCIAL` sem `is_admin` vê só as do vendedor vinculado ao seu usuário. Com acesso por setor ligado: Dono/Admin e gestor do Comercial veem todas; membro do Comercial vê só as do vendedor vinculado. Sem o interruptor `ESCOPO_COMERCIAL`, um membro do Comercial que também pertence a outro setor pode ver todas. Sem vínculo de vendedor, ou com mais de um, **não há erro: lista vazia / zeros** (404 no detalhe).

#### Resposta 200

Opções de filtro.

Tipo da raiz: ComissoesFilterOptionsResponse

| Campo | Tipo | Sempre presente | Descrição |
|---|---|---|---|
| `statuses` | lista de string — um de: `PENDENTE_REGRA`, `PENDENTE_CONFERENCIA`, `PENDENTE_ELEGIBILIDADE`, `ELEGIVEL`, `FECHADA`, `PAGA_PARCIAL`, `PAGA`, `CANCELADA`, `ABERTA`, `CONFERIDA` | sim | Status presentes nos dados visíveis ao usuário (padrão e especiais), ordenados alfabeticamente e sem repetição. |
| `vendedores` | object[] | sim | Vendedores com ao menos uma comissão visível. |
| `vendedores[].id` | string (uuid) | sim | Id do vendedor (UUID). |
| `vendedores[].nome` | string \| null | sim | Nome do vendedor. |
| `produtos` | object[] | sim | Produtos com comissão visível, em ordem alfabética (pt-BR). |
| `produtos[].id` | string (uuid) | sim | Id do produto (UUID). |
| `produtos[].produto` | string \| null | sim | Nome do produto. |
| `fechamentos` | object[] | sim | Fechamentos de período visíveis, do período mais recente ao mais antigo. Quem vê só as próprias comissões vê só os fechamentos que as contêm. |
| `fechamentos[].id` | string (uuid) | sim | Id do fechamento (UUID). |
| `fechamentos[].periodoInicio` | string (date-time) | sim | Início do período. |
| `fechamentos[].periodoFim` | string (date-time) | sim | Fim do período. |

Exemplo (dados fictícios):

```json
{
  "statuses": [
    "ELEGIVEL",
    "PAGA",
    "PENDENTE_CONFERENCIA"
  ],
  "vendedores": [
    {
      "id": "2d4f6a80-1b3c-4e5f-8a7b-9c0d1e2f3a4b",
      "nome": "Vendedor Exemplo"
    }
  ],
  "produtos": [
    {
      "id": "5f0c1e7a-8d2b-4a39-b0c4-1e2d3c4b5a69",
      "produto": "Plataforma Exemplo"
    }
  ],
  "fechamentos": [
    {
      "id": "e1f2a3b4-c5d6-4789-8a9b-0c1d2e3f4a5b",
      "periodoInicio": "2026-09-01T00:00:00.000Z",
      "periodoFim": "2026-09-30T23:59:59.999Z"
    }
  ]
}
```

#### Erros

- **401**: Token ausente, inválido, expirado ou de usuário desativado. Faça login de novo.
- **403**: O usuário do token não tem a permissão exigida pela rota.

---

### GET /comissoes/{id}

**Detalhe de uma comissão** · operationId `obterComissao`

Autenticação: `Authorization: Bearer <token>`.

Devolve uma comissão pelo id, no mesmo formato dos itens de `GET /comissoes` (sem o envelope `data`), já com `primeiraOsPendente` e a situação de recebimento da OS e do contrato (`pagamentoStatus`, `dataPrimeiroRecebimento`) (só na comissão padrão; a especial não tem esses campos).

Padrão: procura entre as comissões **padrão**. Para uma comissão especial é obrigatório enviar `tipoComissao=ESPECIAL`; sem isso o id de uma especial responde 404. O usuário só enxerga comissões do seu escopo (ver abaixo); fora dele a resposta é 404, não 403. O `id` precisa ser um UUID (senão 400).

**Sem efeito colateral:** é só leitura. Comissões `PENDENTE_REGRA` passam a `PENDENTE_CONFERENCIA` quando uma regra de comissão vigente é criada ou alterada, não numa consulta.

**Permissão:** capacidade `LER_COMISSOES`. Sem ela, 403 ("Usuário sem permissão para acessar o módulo de comissões."). Em geral: usuário de tipo `ADMIN` ou `COMERCIAL`; com acesso por setor ligado, administrador pleno ou membro/gestor do setor Comercial.
**Escopo de registros:** modo legado: `type ADMIN` ou usuário com `is_admin` vê todas as comissões da organização; usuário `COMERCIAL` sem `is_admin` vê só as do vendedor vinculado ao seu usuário. Com acesso por setor ligado: Dono/Admin e gestor do Comercial veem todas; membro do Comercial vê só as do vendedor vinculado. Sem o interruptor `ESCOPO_COMERCIAL`, um membro do Comercial que também pertence a outro setor pode ver todas. Sem vínculo de vendedor, ou com mais de um, **não há erro: lista vazia / zeros** (404 no detalhe).

### Ciclo de status da comissão padrão

1. `PENDENTE_REGRA`: o vendedor é comissionado, mas não há regra de comissão ativa e vigente (vendedor + produto + tipo de projeto) na data da venda. Vira `PENDENTE_CONFERENCIA` assim que a regra existe.
2. `PENDENTE_CONFERENCIA`: regra resolvida; percentuais congelados (`percentualPrimeiraParcelaSnapshot`, `percentualServicoSnapshot`); aguardando a **conferência da venda**, feita manualmente por gestão ou automaticamente na aprovação do formulário.
3. `PENDENTE_ELEGIBILIDADE`: venda conferida (`conferidaEm` preenchido); aguarda a **primeira OS paga**.
4. `ELEGIVEL`: liberada para pagamento. Acontece quando a **primeira OS do projeto/contrato muda para `PAGO` no Omie** (`primeiraOsPagaId` e `dataElegibilidade` são gravados e os valores calculados). Atalhos: sem projeto (importada, ou formulário que não gera projeto) ou projeto não faturável pelo financeiro, a conferência já libera a comissão sem depender de OS; o mesmo vale para venda sem comissão de serviço cujo SaaS foi conferido. Se a OS foi paga antes da conferência, a conferência já a encontra. Se a OS vinculada for cancelada/excluída e outra OS for paga, a comissão é revinculada à nova.
5. `FECHADA`: congelada em um fechamento de período (`fechamentoId`); continua apta a pagamento.
6. `PAGA_PARCIAL`: um componente pago (`SERVICO` ou `PRIMEIRA_PARCELA`) e o outro não.
7. `PAGA`: todos os componentes aplicáveis pagos (`pagaEm` = o pagamento mais recente).
8. `CANCELADA`: a OS ligada à comissão foi cancelada ou excluída no Omie antes da elegibilidade. Se uma OS for paga depois, a comissão é revivida ao estágio em que estava. Não há cancelamento manual.

O pagamento exige conferência final registrada (feita por administrador); esses passos são escritas e não fazem parte desta documentação de leitura.

**Componentes:** `SERVICO` (comissão sobre o serviço/implantação) e `PRIMEIRA_PARCELA` (comissão sobre a primeira parcela do SaaS/mensalidade). Cada um tem conferência e pagamento próprios em `componentes`. `valorComissao` é a soma dos dois; percentuais são de 0 a 100; valores em **reais**, números JSON (a API converte os decimais do banco para número).

**Comissões especiais** (`tipoComissao = ESPECIAL`) são comissões adicionais para outro vendedor beneficiário, derivadas de uma comissão padrão por uma regra especial. Têm ciclo próprio: `ABERTA` -> `CONFERIDA` -> `PAGA` (ou `CANCELADA`), um único componente cada, e não pertencem a fechamento.

#### Parâmetros

| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| `id` | path | string (uuid) | sim | Id (UUID) da comissão. Ex.: `c1a2b3c4-d5e6-4f70-8a91-b2c3d4e5f607` |
| `tipoComissao` | query | string — um de: `PADRAO`, `ESPECIAL`; padrão `"PADRAO"` | não | `PADRAO` (padrão quando omitido) ou `ESPECIAL`. Outro valor responde 400. Ex.: `PADRAO` |

#### Resposta 200

Comissão encontrada.

Tipo: ComissoesComissaoPadrao | ComissoesComissaoEspecial

Exemplo (dados fictícios):

```json
{
  "id": "c1a2b3c4-d5e6-4f70-8a91-b2c3d4e5f607",
  "tipoComissao": "PADRAO",
  "origem": "FORMULARIO",
  "formularioId": "f0e1d2c3-b4a5-4968-8776-5a4b3c2d1e0f",
  "projetoId": "7e3d1c20-9a54-4d3b-8f21-0c6b5a4d3e22",
  "vendedorId": "2d4f6a80-1b3c-4e5f-8a7b-9c0d1e2f3a4b",
  "produtoId": "5f0c1e7a-8d2b-4a39-b0c4-1e2d3c4b5a69",
  "tipoProjetoId": "a1b2c3d4-0000-4000-8000-000000000001",
  "regraId": "d9c8b7a6-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
  "importacaoReferenciaExterna": null,
  "clienteSnapshot": null,
  "projetoSnapshot": null,
  "vendedorNomeSnapshot": null,
  "produtoSnapshot": null,
  "tipoProjetoSnapshot": null,
  "contratoId": 912,
  "primeiraOsPagaId": 48213,
  "fechamentoId": null,
  "status": "ELEGIVEL",
  "dataVendaConclusao": "2026-09-28T00:00:00.000Z",
  "dataBaseRegra": "2026-09-28T00:00:00.000Z",
  "percentualPrimeiraParcelaSnapshot": 50,
  "percentualServicoSnapshot": 5,
  "regraVigenciaInicio": "2026-01-01T00:00:00.000Z",
  "regraVigenciaFim": null,
  "baseCalculoPrimeiraParcela": 1200,
  "valorComissaoPrimeiraParcela": 600,
  "baseCalculoServico": 10000,
  "valorComissaoServico": 500,
  "baseCalculo": 11200,
  "valorComissao": 1100,
  "dataElegibilidade": "2026-10-20T13:05:00.000Z",
  "conferidaEm": "2026-10-05T14:20:00.000Z",
  "conferidaPorId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
  "observacaoConferencia": null,
  "primeiraParcelaConferidaEm": "2026-10-05T14:20:00.000Z",
  "primeiraParcelaConferidaPorId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
  "observacaoConferenciaPrimeiraParcela": null,
  "primeiraParcelaPagaEm": null,
  "primeiraParcelaPagaPorId": null,
  "servicoPagoEm": null,
  "servicoPagoPorId": null,
  "observacaoPagamentoServico": null,
  "observacaoPagamentoPrimeiraParcela": null,
  "pagaEm": null,
  "pagaPorId": null,
  "observacaoOperacional": "Comissão elegível pela primeira OS paga confirmada no Omie.",
  "createdAt": "2026-09-28T17:00:00.000Z",
  "updatedAt": "2026-10-20T13:05:00.000Z",
  "vendedor": {
    "id": "2d4f6a80-1b3c-4e5f-8a7b-9c0d1e2f3a4b",
    "nome": "Vendedor Exemplo"
  },
  "produto": {
    "id": "5f0c1e7a-8d2b-4a39-b0c4-1e2d3c4b5a69",
    "produto": "Plataforma Exemplo"
  },
  "tipoProjeto": {
    "id": "a1b2c3d4-0000-4000-8000-000000000001",
    "tipoProjeto": "Implantação",
    "status": true
  },
  "fechamento": null,
  "cliente": {
    "id": "0b6a1d52-3f0e-4c6a-9d0e-5a1f2f6d7a11",
    "nomeEmpresa": "Empresa Alfa Ltda"
  },
  "projeto": {
    "nomeProjeto": "Implantação Alfa",
    "quantidadeHoras": 100,
    "valorHora": 100
  },
  "contrato": {
    "id": 912,
    "tipoContrato": "SERVICO",
    "numCtr": "CTR-0091",
    "codStatus": "ATIVO",
    "descStatus": "Ativo",
    "valorTotalMensal": 1200,
    "diaFaturamento": 10,
    "vigenciaInicio": "2026-09-01T00:00:00.000Z",
    "vigenciaFim": "2027-08-31T00:00:00.000Z",
    "pagamentoStatus": "PAGA",
    "dataPrimeiroRecebimento": "2026-10-20T00:00:00.000Z"
  },
  "primeiraOsPaga": {
    "id": 48213,
    "numOs": "000412",
    "codStatus": "PAGO",
    "descStatus": "Pago",
    "valorTotal": 10000,
    "dataFaturamento": "2026-10-01T00:00:00.000Z",
    "dataVencimento": "2026-10-10T00:00:00.000Z",
    "quantidadeParcelas": 1,
    "pagamentoStatus": "PAGA",
    "dataPrimeiroRecebimento": "2026-10-20T00:00:00.000Z"
  },
  "primeiraOsPendente": null,
  "componentes": {
    "SERVICO": {
      "aplicavel": true,
      "aptoPagamento": true,
      "conferencia": {
        "status": "CONFERIDO",
        "em": "2026-10-05T14:20:00.000Z",
        "porId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
        "observacao": null
      },
      "pagamento": {
        "status": "PENDENTE",
        "em": null,
        "porId": null,
        "observacao": null
      }
    },
    "PRIMEIRA_PARCELA": {
      "aplicavel": true,
      "aptoPagamento": true,
      "conferencia": {
        "status": "CONFERIDO",
        "em": "2026-10-05T14:20:00.000Z",
        "porId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
        "observacao": null
      },
      "pagamento": {
        "status": "PENDENTE",
        "em": null,
        "porId": null,
        "observacao": null
      }
    }
  }
}
```

#### Erros

- **400**: Parâmetros inválidos. `message` é uma lista com um item por problema, no formato `campo: motivo`.
- **401**: Token ausente, inválido, expirado ou de usuário desativado. Faça login de novo.
- **403**: O usuário do token não tem a permissão exigida pela rota.
- **404**: Registro não encontrado (ou de outra organização).
