Client já existente na plataforma, enriquecida com indicadores financeiros calculados a partir dos contratos e títulos vinculados ao cliente.status != CANCELLED na empresa. Não existe vínculo manual — a presença é derivada da existência de contratos. Se todos os contratos de um cliente forem cancelados, ele deixa de aparecer na listagem da carteira.Client existente (nome, taxId, e-mail, telefone, endereço).status no contexto deste módulo) é um campo derivado que classifica a situação do cliente na carteira com base nos status das parcelas e contratos vinculados a ele. É calculado em tempo de leitura e exibido na listagem e no detalhe do cliente.Contract e ContractPayment — não há configuração de limiar de dias separada para este módulo. As transições para OVERDUE e DEFAULTED ocorrem no nível das parcelas e contratos, conforme regras do contrato (ver Visão Geral, seções 5 e 11).Contract (filtradas pelos participantes com role DEBTOR correspondente ao cliente) e ContractPayment (das parcelas dos contratos desse cliente). Não existe entidade PortfolioClient armazenada — é uma view derivada.{
"client": {
"id": "a3f1c2d4-0000-0000-0000-000000000010",
"name": "Fazenda Tijucal",
"taxId": "12345678000190"
},
"contracts": {
"total": 3,
"active": 2,
"value": 730000.00,
"open": 85000.00,
"overdue": 85000.00,
"overduePayments": 2,
"maxOverdueDays": 45
},
"status": "OVERDUE"
}| Campo | Tipo | Descrição |
|---|---|---|
client.id | UUID | Referência ao Client existente. |
client.name | String | Nome/Razão social do cliente. |
client.taxId | String | CPF (11 dígitos) ou CNPJ (14 dígitos) — apenas dígitos, sem máscara. |
contracts.total | Integer | Quantidade de contratos do cliente na carteira (todos os status exceto CANCELLED). |
contracts.active | Integer | Quantidade de contratos com status = ACTIVE. |
contracts.value | Decimal | Soma do value de todos os contratos não cancelados. |
contracts.open | Decimal | Soma do amounts.remaining de todos os títulos em aberto (PENDING, PARTIALLY_PAID, OVERDUE). |
contracts.overdue | Decimal | Soma do amounts.remaining dos títulos com status = OVERDUE. |
contracts.overduePayments | Integer | Quantidade de títulos com status = OVERDUE. |
contracts.maxOverdueDays | Integer | Maior número de dias em atraso entre todos os títulos OVERDUE do cliente. 0 se nenhum título em atraso. |
status | Enum | Status de cobrança derivado: ON_TRACK, OVERDUE, CRITICAL. Ver seção 2.2. |
OVERDUE e DEFAULTED já estão definidas no nível das parcelas e contratos (regra do contrato, ver Visão Geral, seção 11).| status (do cliente) | Condição |
|---|---|
ON_TRACK | Cliente sem nenhuma parcela em OVERDUE ou DEFAULTED e sem nenhum contrato em OVERDUE ou DEFAULTED. |
OVERDUE | Cliente com ao menos uma parcela ou contrato em OVERDUE (e nenhum em DEFAULTED). |
CRITICAL | Cliente com ao menos uma parcela ou contrato em DEFAULTED. |
CRITICAL prevalece sobre OVERDUE quando ambos coexistem — basta um DEFAULTED em parcela ou contrato para o cliente ser classificado como crítico.| status (backend) | Label exibida (frontend) |
|---|---|
ON_TRACK | "Em dia" |
OVERDUE | "Em atraso" |
CRITICAL | "Crítico" |
{
"client": {
"id": "a3f1c2d4-0000-0000-0000-000000000010",
"name": "Fazenda Tijucal",
"taxId": "98765432000110",
"email": "contato@fazendatijucal.com.br",
"phone": "11999999999",
"address": "Fazenda Horizonte, Km 15, Zona Rural - Ribeirão Preto/SP"
},
"contracts": {
"total": 3,
"active": 2,
"closed": 1,
"defaulted": 0,
"value": 730000.00,
"open": 85000.00,
"overdue": 85000.00,
"paid": 645000.00,
"overduePayments": 2,
"pendingPayments": 3,
"paidPayments": 8,
"maxOverdueDays": 45,
"averageOverdueDays": 30,
"items": { [
{
"key": "CPR_PHYSICAL",
"total": 1,
"value": 450000.00,
"open": 0.00
},
{
"key": "INVOICE",
"total": 2,
"value": 280000.00,
"open": 85000.00
}
]
}
},
"status": "OVERDUE"
}| Campo | Tipo | Descrição |
|---|---|---|
client.email | String | E-mail do cliente. null se não cadastrado. |
client.phone | String | Telefone do cliente (apenas dígitos, sem máscara). null se não cadastrado. |
client.address | String | Endereço completo. null se não cadastrado. |
contracts.closed | Integer | Contratos encerrados. |
contracts.defaulted | Integer | Contratos inadimplentes. |
contracts.paid | Decimal | Valor total já pago (soma de baixas confirmadas). |
contracts.pendingPayments | Integer | Títulos pendentes (não vencidos). |
contracts.paidPayments | Integer | Títulos pagos. |
contracts.averageOverdueDays | Integer | Média de dias em atraso dos títulos OVERDUE. |
contracts.groupedBy | Object | Breakdown dos contratos por dimensão. Chave é a dimensão de agrupamento (ex: type). Valor é array de buckets. Permite expansão futura para outras dimensões (status, subPortfolio, etc.) sem mudar a forma do payload. |
contracts.groupedBy.type[] | Array | Breakdown dos contratos agrupados por tipo. Um item por valor distinto de type que o cliente possui em contratos não cancelados. |
contracts.groupedBy.type[].key | Enum | Valor do tipo do contrato (ex: CPR_PHYSICAL, INVOICE). Os valores possíveis seguem o enum de Contract.type (ver doc 3). |
contracts.groupedBy.type[].total | Integer | Quantidade de contratos do cliente com esse tipo. |
contracts.groupedBy.type[].value | Decimal | Soma do value dos contratos dessa quebra. |
contracts.groupedBy.type[].open | Decimal | Soma do valor em aberto dos contratos dessa quebra. |
status != CANCELLED. Não existe operação de vínculo ou desvínculo manual de clientes à carteira. A visibilidade é puramente derivada dos dados.status = CANCELLED), o cliente deixa de aparecer na listagem da carteira. Os dados do Client não são afetados — ele continua existente no módulo de Clientes da plataforma.Visão Geral, seção 9): a permissão RBAC sobre o resource contract combinada com a atribuição do usuário a portfolios e/ou carteiras determina quais clientes são visíveis. Um cliente aparece para o usuário quando o usuário enxerga ao menos um dos contratos daquele cliente.status do cliente é calculado em tempo de leitura combinando os status das parcelas e contratos vinculados a ele:ON_TRACK quando não há parcela nem contrato em OVERDUE ou DEFAULTED.OVERDUE quando há ao menos uma parcela ou contrato em OVERDUE (e nenhum em DEFAULTED).CRITICAL quando há ao menos uma parcela ou contrato em DEFAULTED.Cliente → collectionStatus (ver seção 6) avalia diariamente o status efetivo de cada cliente e detecta transições (ex.: cliente passou de OVERDUE para CRITICAL), emitindo eventos de domínio para consumo por outros módulos (notificações, integrações com Gestão de Cobrança).ACTIVE mas com todos os títulos PAID é classificado como ON_TRACK com contracts.open = 0. Não há ação manual envolvida — é cálculo direto sobre os dados.PortfolioClientSummary e PortfolioClientDetail são calculados sob demanda por agregação sobre Contract (filtrando por participantes do cliente) e ContractPayment (das parcelas desses contratos). Não são armazenados.GET .../portfolio/clients aceita filtro de período (startDate / endDate). Quando informado, os indicadores financeiros (contracts.value, contracts.open, contracts.overdue, contracts.maxOverdueDays, etc.) consideram apenas títulos com dueDate dentro do período. Quando omitido, considera todos os títulos em aberto independente da data.Client existente. Este módulo não oferece endpoints para edição de dados cadastrais — a edição é feita pelo módulo de Clientes da plataforma. Qualquer alteração no Client é refletida automaticamente na carteira.Carteiras.md.| Status | Código | Descrição |
|---|---|---|
| 404 Not Found | CLIENT_NOT_FOUND | Cliente não encontrado ou não pertence à empresa. |
| 404 Not Found | CLIENT_NOT_IN_PORTFOLIO | Cliente existe mas não possui contratos na carteira. |
portfolio:read| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
search | String | Não | Busca textual por nome, razão social ou taxId do cliente. |
status | Enum (multi) | Não | Filtrar por status de cobrança: ON_TRACK, OVERDUE, CRITICAL. Aceita múltiplos valores. |
startDate | Datetime (ISO) | Não | Início do período para cálculo dos indicadores. |
endDate | Datetime (ISO) | Não | Fim do período para cálculo dos indicadores. |
subPortfolioId | UUID | Não | Filtrar por carteira específica (clientes com ao menos um contrato naquela carteira). |
orderBy | Enum | Não | Ordenação: clientName, contracts.open, contracts.maxOverdueDays. Default: clientName. |
order | Enum | Não | asc ou desc. Default: asc. |
offset | Integer | Não | Default: 0. |
limit | Integer | Não | Default: 20. Máximo: 100. |
type | String | Não | Campo para buscar pelo tipo do cliente (DEBTOR, CREDOR, GUARANTOR, WITNESS) |
{
"items": [
{
"client": {
"id": "a3f1c2d4-0000-0000-0000-000000000010",
"name": "Fazenda Tijucal",
"taxId": "12345678000190"
},
"contracts": {
"total": 3,
"active": 2,
"value": 730000.00,
"open": 85000.00,
"overdue": 85000.00,
"overduePayments": 2,
"maxOverdueDays": 45
},
"status": "OVERDUE"
},
{
"client": {
"id": "b4g2d3e5-0000-0000-0000-000000000020",
"name": "Fazenda Rio Verde",
"taxId": "98765432000110"
},
"contracts": {
"total": 1,
"active": 1,
"value": 200000.00,
"open": 0.00,
"overdue": 0.00,
"overduePayments": 0,
"maxOverdueDays": 0
},
"status": "ON_TRACK"
},
{
"client": {
"id": "c5h3e4f6-0000-0000-0000-000000000030",
"name": "Fazenda Cocal",
"taxId": "55666777000188"
},
"contracts": {
"total": 2,
"active": 1,
"value": 520000.00,
"open": 320000.00,
"overdue": 320000.00,
"overduePayments": 5,
"maxOverdueDays": 92
},
"status": "CRITICAL"
}
],
"nextPage": false
}contracts.groupedBy no futuro).portfolio:read| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
startDate | Datetime (ISO) | Não | Período para indicadores. Default: primeiro dia do ano corrente. |
endDate | Datetime (ISO) | Não | Default: último dia do ano corrente. |
{
"client": {
"id": "a3f1c2d4-0000-0000-0000-000000000010",
"name": "Fazenda Tijucal",
"taxId": "98765432000110",
"email": "contato@fazendatijucal.com.br",
"phone": "11999999999",
"address": "Fazenda Horizonte, Km 15, Zona Rural - Ribeirão Preto/SP"
},
"contracts": {
"total": 3,
"active": 2,
"closed": 1,
"defaulted": 0,
"value": 730000.00,
"open": 85000.00,
"overdue": 85000.00,
"paid": 645000.00,
"overduePayments": 2,
"pendingPayments": 3,
"paidPayments": 8,
"maxOverdueDays": 45,
"averageOverdueDays": 30,
"items":[
{
"key": "CPR_PHYSICAL",
"total": 1,
"value": 450000.00,
"open": 0.00
},
{
"key": "INVOICE",
"total": 2,
"value": 280000.00,
"open": 85000.00
}
]
},
"status": "OVERDUE"
}| Status | Código |
|---|---|
| 404 | CLIENT_NOT_FOUND |
| 404 | CLIENT_NOT_IN_PORTFOLIO |
GET /portfolios/:portfolioId/contracts com filtro implícito por clientId, mas aninhado na rota do cliente para acesso direto sem passar o ID via query param.contract:read| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
search | String | Não | Busca por code ou description. |
status | Enum (multi) | Não | Filtrar por status do contrato. |
type | Enum (multi) | Não | Filtrar por tipo do contrato. |
startDate | Datetime (ISO) | Não | Contratos com startDate >= esta data. |
endDate | Datetime (ISO) | Não | Contratos com endDate <= esta data. |
offset | Integer | Não | Default: 0. |
limit | Integer | Não | Default: 20. Máximo: 100. |
{
"items": [
{
"id": "b9d3f1aa-22cc-4e72-b430-1e45a3d6e001",
"code": "CT-2024-001",
"client": {
"id": "a3f1c2d4-0000-0000-0000-000000000010",
"name": "Fazenda Tijucal"
},
"type": "PURCHASE_SALE_CONTRACT",
"description": "Financiamento Safra Soja 2024",
"value": 450000.00,
"currency": "BRL",
"startDate": "2024-03-14T00:00:00.000+00:00",
"endDate": "2024-03-14T00:00:00.000+00:00",
"status": "OVERDUE",
"typeSpecificFields": {
"product": "Insumos agrícolas"
},
"createdBy": {
"id": "8c3f1a2b-...",
"name": "João Silva"
},
"createdAt": "2025-03-17T09:00:00.000+00:00",
"updatedAt": "2025-03-17T09:00:00.000+00:00"
}
],
"nextPage": false
}Nota técnica: typeSpecificFieldsé um objeto JSON cuja estrutura interna varia conforme otypedo contrato. Cada tipo base define seu próprio schema (camada 2 do template — verVisão Geral, seção 4.3). A validação é feita contra esse schema no momento da criação/edição do contrato.
payment:read| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
status | Enum (multi) | Não | Filtrar por status do título. |
contractId | UUID | Não | Filtrar por contrato específico. |
dueDateStart | Datetime (ISO) | Não | Títulos com dueDate >= esta data. |
dueDateEnd | Datetime (ISO) | Não | Títulos com dueDate <= esta data. |
orderBy | Enum | Não | Ordenação: dueDate, amounts.value, overdueDays, status. Default: dueDate. |
order | Enum | Não | asc ou desc. Default: asc. |
offset | Integer | Não | Default: 0. |
limit | Integer | Não | Default: 20. Máximo: 100. |
{
"items": [
{
"id": "r1a2b3c4-0000-0000-0000-000000000001",
"contract": {
"id": "b9d3f1aa-22cc-4e72-b430-1e45a3d6e001",
"code": "CT-2024-001"
},
"code": "NF-001",
"type": "INVOICE",
"description": null,
"dueDate": "2024-03-14T00:00:00.000+00:00",
"status": "OVERDUE",
"overdueDays": 45,
"amounts": {
"value": 150000.00,
"corrected": null,
"due": 156750.00,
"received": 71750.00,
"remaining": 85000.00
},
"charges": {
"interest": 3750.00,
"fine": 3000.00,
"discount": {
"type": null,
"value": null,
"calculatedAmount": null
}
},
"createdBy": {
"id": "8c3f1a2b-...",
"name": "João Silva"
},
"createdAt": "2025-03-17T09:00:00.000+00:00"
}
],
"nextPage": false
}GET /contracts/:contractId/payments é que este endpoint não exige contractId na rota — traz títulos de todos os contratos do cliente. O objeto contract é incluído na resposta para contexto. A estrutura do título segue a mesma definição de ContractPayment do doc 5 (amounts, charges, createdBy hidratado).portfolio:readGET /portfolio/clients, acrescidos de:| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
format | Enum | Sim | CSV ou XLSX. |
| Job | Descrição |
|---|---|
Cliente → collectionStatus | Avalia diariamente o status de cobrança de cada cliente da carteira (derivado das parcelas e contratos). Detecta transições entre ON_TRACK, OVERDUE e CRITICAL, e emite eventos de domínio para consumo por outros módulos (notificações, integrações com Gestão de Cobrança quando implementada). |
GET /portfolios/:portfolioId/contracts já suporta filtro clientId. O endpoint GET /portfolios/:portfolioId/clients/:clientId/contracts é um atalho de conveniência para a UI — internamente pode reutilizar a mesma lógica com o filtro implícito.PortfolioSummary em Carteiras.md) incluem defaultersCount — número de clientes com ao menos um título OVERDUE. Esse indicador é coerente com status != ON_TRACK deste módulo.