ContractTemplate) é a estrutura que define a experiência de cadastro de um contrato na plataforma. Ele combina um tipo base pré-definido pela plataforma (CPR Física, CCB, Duplicata, etc.) com campos customizados definidos pela empresa, organizados em seções visuais e com suporte a regras condicionais e cálculos automáticos.CPR_PHYSICAL) — com campos agronômicos de sojaCPR_PHYSICAL) — com campos específicos de café┌─────────────────────────────────────────────────┐
│ Camada 1 — Campos comuns do contrato │ Definidos pela plataforma
│ (code, description, total, dates, etc.) │ no ContractFieldDictionary.
│ │ Capturados via snapshot
│ │ na criação do template.
├─────────────────────────────────────────────────┤
│ Camada 2 — Campos do tipo base │ Definidos pela plataforma
│ (baseTypeFields) │ no ContractFieldDictionary,
│ Ex: CPR_PHYSICAL → safra, cultura, entrega │ por baseType. Capturados
│ │ via snapshot na criação.
├─────────────────────────────────────────────────┤
│ Camada 3 — Campos customizados da empresa │ Configurados pela empresa
│ (customFields) │ no template. Organizados
│ Ex: variedade, área cultivada, laudo │ em seções, com regras.
└─────────────────────────────────────────────────┘ContractFieldDictionary (ver seção 5) e acrescenta a camada 3 configurada pela empresa. O template fica autocontido — carrega tudo o que precisa para validar contratos.| Conceito AgFlow | Equivalente no template de contrato |
|---|---|
| Start Form | Template de contrato |
| Seções (sectionMetadata) | Seções do template (sections) |
| Campos do formulário | customFields do template |
| Rules (onChange, onCalculate, onLoad) | rules do template |
| Campos condicionais (category) | category: "conditional" nos custom fields |
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| id | UUID | Sim | Identificador único do template. |
| companyId | UUID | Sim | Empresa à qual o template pertence. Todo template tem uma empresa proprietária. |
| baseType | Enum | Sim | Tipo base: CPR_PHYSICAL, CPR_FINANCIAL, INVOICE, PURCHASE_SALE_CONTRACT, CCB, PROMISSORY_NOTE, OTHER. Imutável após criação. |
| name | String | Sim | Nome do template. Único por empresa. |
| description | String | Não | Descrição do propósito. |
| commonFields | Array | Sim | Snapshot da camada 1 capturado do ContractFieldDictionary na criação. Ver seção 5. |
| baseTypeFields | Array | Sim | Snapshot da camada 2 capturado do ContractFieldDictionary na criação. Array vazio quando baseType = OTHER. Ver seção 5. |
| sections | Array<TemplateSection> | Não | Seções visuais para agrupamento dos campos customizados (camada 3). Ver seção 2.2. |
| customFields | Array<CustomFieldDefinition> | Não | Campos customizados (camada 3). Ver seção 2.3. |
| rules | Array<FieldRule> | Não | Regras condicionais e cálculos (camada 3). Ver seção 2.5. |
| allowedPaymentTypes | Array<Enum> | Sim | Snapshot dos tipos de pagamento permitidos, capturado do dictionary na criação. |
| paymentDefaults | Object | Sim | Snapshot dos defaults de aplicabilidade de encargos, capturado do dictionary na criação. |
| dictionaryVersion | Integer | Sim | Versão do ContractFieldDictionary capturada na criação ou no último refresh. |
| dictionarySnapshotAt | DateTime (ISO 8601 UTC) | Sim | Data/hora do último snapshot do dictionary (criação ou refresh). |
| status | Enum | Sim | ACTIVE, INACTIVE. |
| createdBy | object | Sim | Usuário que criou, hidratado: { id, name }. No armazenamento permanece como UUID flat. |
| createdAt | DateTime (ISO 8601 UTC) | Sim | Data de criação. |
| updatedAt | DateTime (ISO 8601 UTC) | Sim | Data da última atualização. |
sectionId são exibidos juntos na interface.| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| id | UUID | Sim | Identificador único da seção. Gerado automaticamente. |
| title | String | Sim | Título da seção exibido na interface (ex: "Dados agronômicos", "Documentos"). |
| description | String | Não | Descrição auxiliar da seção. |
| order | Integer | Sim | Ordem de exibição da seção no formulário. Começa em 1. |
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| id | UUID | Sim | Identificador único do campo. Gerado automaticamente na criação. Obrigatório em atualizações — sem ele, a API cria campo duplicado. |
| sectionId | UUID | Não | Seção à qual o campo pertence. null para campos fora de seção (exibidos no topo). |
| key | String | Sim | Chave técnica (camelCase, sem espaços). Única no template. Não pode colidir com campos do tipo base. Usada como chave no customFields do contrato. |
| label | String | Sim | Label exibido na interface. |
| fieldType | Enum | Sim | Tipo do campo. Ver seção 2.4. |
| required | Boolean | Sim | Se obrigatório na criação do contrato. Pode ser sobrescrito por regra setRequired/setOptional. |
| editable | Boolean | Sim | true = editável pelo usuário. false = somente leitura (usado para campos calculados). Default: true. |
| active | Boolean | Sim | true = campo visível. false = desativado (não aparece no formulário nem na validação). Default: true. |
| category | Enum | Sim | "default" = sempre visível. "conditional" = oculto por padrão, controlado por regras. Default: "default". |
| helpText | String | Não | Texto de instrução exibido abaixo do campo. |
| placeholder | String | Não | Placeholder do campo no formulário. |
| defaultValue | Any | Não | Valor padrão estático. Para inicialização dinâmica, usar regra onLoad. |
| options | Array<FieldOption> | Condicional | Opções para SELECT, MULTI_SELECT, RADIO. Obrigatório nesses tipos. Mínimo: 2 opções. |
| validation | Object | Não | Regras de validação adicionais. Ver seção 2.6. |
| order | Integer | Sim | Ordem do campo dentro da seção (ou do topo, se sem seção). Começa em 1. |
| Tipo | Descrição | Valor armazenado | Observação |
|---|---|---|---|
TEXT | Texto curto (uma linha). | String | — |
TEXT_AREA | Texto longo (múltiplas linhas). | String | — |
NUMBER | Número decimal. | Decimal | Ideal para área em hectares, percentuais. |
INTEGER | Número inteiro. | Integer | — |
CURRENCY | Valor monetário (BRL). | Decimal | Exibido com máscara R$. |
DATE | Data sem hora. | Date (ISO) | — |
BOOLEAN | Sim/Não. | Boolean | — |
SELECT | Dropdown de seleção única. | String (value da opç ão) | Requer options. |
MULTI_SELECT | Seleção múltipla (checkboxes). | Array<String> | Requer options. |
RADIO | Botões de escolha única. | String (value da opção) | Equivalente visual ao SELECT. Requer options. |
EMAIL | E-mail com validação de formato. | String | — |
PHONE | Telefone com máscara. | String | — |
ATTACHMENT | Upload de arquivo(s). | Object ou Array<Object>. Ver seção 2.7. | Aceita PDF, imagens, planilhas. |
fieldId) e define um gatilho (trigger) com condições e ações.| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| id | UUID | Sim | Identificador único da regra. Gerado automaticamente. |
| fieldId | UUID | Sim | Campo que dispara ou recebe a regra. |
| trigger | Enum | Sim | Tipo do gatilho: ON_CHANGE, ON_CALCULATE, ON_LOAD. |
| active | Boolean | Sim | Se a regra está ativa. Default: true. |
| operations | Array<RuleOperation> | Condicional | Condições e ações. Obrigatório para ON_CHANGE e ON_LOAD. |
| calculation | Object | Condicional | Configuração de cálculo. Obrigatório para ON_CALCULATE. |
| Trigger | Quando dispara | Uso principal |
|---|---|---|
ON_CHANGE | Quando o valor do campo fieldId muda. | Mostrar/ocultar campos condicionais, setar valores, alterar obrigatoriedade. |
ON_CALCULATE | Quando qualquer campo da expressão é alterado. | Calcular soma, multiplicação ou resultado em um campo de destino. |
ON_LOAD | Ao abrir o formulário de criação do contrato. | Inicializar campos com valor padrão dinâmico. |
operations em uma regra são tratadas como OR (qualquer uma verdadeira dispara suas ações). Múltiplas conditions dentro de uma operation são tratadas como AND (todas precisam ser verdadeiras).| Campo | Tipo | Descrição |
|---|---|---|
| conditions | Array<RuleCondition> | Condições a serem avaliadas. Vazio para ON_LOAD (dispara sempre). |
| actions | Array<RuleAction> | Ações executadas quando as condições são satisfeitas. |
| Campo | Tipo | Descrição |
|---|---|---|
| fieldId | UUID | Campo avaliado na condição. |
| operator | Enum | Operador. Ver tabela abaixo. |
| value | Any | Valor de comparação. Tipo depende do operador e do campo. |
| Operador | Uso | Tipos de campo compatíveis |
|---|---|---|
EQUALS | Igual a | Todos |
NOT_EQUALS | Diferente de | Todos |
GREATER_THAN | Maior que | NUMBER, INTEGER, CURRENCY |
LESS_THAN | Menor que | NUMBER, INTEGER, CURRENCY |
GREATER_OR_EQUAL | Maior ou igual | NUMBER, INTEGER, CURRENCY |
LESS_OR_EQUAL | Menor ou igual | NUMBER, INTEGER, CURRENCY |
CONTAINS | Contém o valor | MULTI_SELECT |
NOT_CONTAINS | Não contém | MULTI_SELECT |
IS_EMPTY | Campo vazio | Todos |
IS_NOT_EMPTY | Campo preenchido | Todos |
| Campo | Tipo | Descrição |
|---|---|---|
| type | Enum | Tipo da ação. Ver tabela abaixo. |
| targetFieldId | UUID | Campo alvo da ação. |
| value | Any | Valor a ser aplicado. Usado com SET_VALUE. |
| Tipo | Efeito | Observação |
|---|---|---|
SHOW | Exibe o campo alvo. | Usado com campos category: "conditional". |
HIDE | Oculta o campo alvo. | — |
SET_REQUIRED | Torna o campo alvo obrigatório. | — |
SET_OPTIONAL | Torna o campo alvo opcional. | — |
SET_VALUE | Popula o campo alvo com value. | — |
CLEAR_VALUE | Limpa o valor do campo alvo. | — |
SHOW + SET_REQUIRED. Para ocultar: HIDE + SET_OPTIONAL + CLEAR_VALUE.| Campo | Tipo | Descrição |
|---|---|---|
| expression | String | Expressão matemática usando IDs dos campos como variáveis. Ex: "({cf-001} * {cf-002})". Suporta +, -, *, /, parênteses. |
| targetFieldId | UUID | Campo de destino que recebe o resultado. Deve ter editable: false. |
| precision | Integer | Casas decimais do resultado. Default: 2. |
{
"fieldId": "cf-price",
"trigger": "ON_CALCULATE",
"active": true,
"calculation": {
"expression": "({cf-price} * {cf-quantity})",
"targetFieldId": "cf-total-estimated",
"precision": 2
}
}| Regra | Tipos aplicáveis | Descrição |
|---|---|---|
| minLength | TEXT, TEXT_AREA | Comprimento mínimo. |
| maxLength | TEXT, TEXT_AREA | Comprimento máximo. |
| min | NUMBER, INTEGER, CURRENCY | Valor mínimo. |
| max | NUMBER, INTEGER, CURRENCY | Valor máximo. |
| minDate | DATE | Data mínima. |
| maxDate | DATE | Data máxima. |
| maxFileSize | ATTACHMENT | Tamanho máximo em MB. Default plataforma: 10 MB. |
| allowedFileTypes | ATTACHMENT | Array de extensões aceitas (ex: ["pdf", "jpg", "png"]). |
| maxFiles | ATTACHMENT | Número máximo de arquivos. Default: 1. |
fieldType = ATTACHMENT, o valor armazenado no customFields do contrato é:{
"fileId": "file-uuid-001",
"fileName": "laudo_vistoria.pdf",
"fileSize": 245000,
"mimeType": "application/pdf",
"uploadedBy": "user-uuid",
"uploadedAt": "2025-03-17T09:00:00.000+00:00",
"url": "link do bucket" //necessário confirmar
}maxFiles > 1, o valor é um array de objetos. O upload é feito via endpoint separado de arquivos (fora do escopo deste documento).| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| value | String | Sim | Valor armazenado. |
| label | String | Sim | Label exibido. |
| order | Integer | Sim | Ordem de exibição. |
Nota: O JSON abaixo representa a entidade ContractTemplatecomo armazenada — autocontida, com snapshot das camadas 1 e 2 capturado doContractFieldDictionaryna criação (ver seção 5) somado à camada 3 configurada pela empresa.
{
"id": "tpl-001",
"companyId": "company-001",
"baseType": "CPR_PHYSICAL",
"name": "CPR Soja — Safra",
"description": "Template para CPRs de soja com campos agronômicos e documentos.",
"status": "ACTIVE",
"dictionaryVersion": 3,
"dictionarySnapshotAt": "2025-03-17T09:00:00.000+00:00",
"commonFields": [
{ "field": "code", "type": "STRING", "visibility": "REQUIRED" },
{ "field": "description", "type": "STRING", "visibility": "REQUIRED" },
{ "field": "total", "type": "DECIMAL", "visibility": "REQUIRED" },
{ "field": "startDate", "type": "DATE", "visibility": "REQUIRED" },
{ "field": "endDate", "type": "DATE", "visibility": "REQUIRED" },
{ "field": "interestRate", "type": "DECIMAL", "visibility": "HIDDEN", "helpText": "CPRs Físicas não possuem taxa de juros." },
{ "field": "paymentPeriodicity", "type": "ENUM", "visibility": "OPTIONAL", "defaultValue": "HARVEST", "helpText": "Geralmente liquidação na colheita." },
{ "field": "currency", "type": "ENUM", "visibility": "OPTIONAL", "defaultValue": "COMMODITY_LINKED" }
],
"baseTypeFields": [
{ "field": "crop", "type": "ENUM", "visibility": "REQUIRED", "enumValues": ["SOYBEAN", "CORN", "COTTON", "COFFEE", "SUGARCANE", "WHEAT", "RICE", "OTHER"], "helpText": "Cultura vinculada à CPR." },
{ "field": "harvestSeason", "type": "STRING", "visibility": "REQUIRED", "helpText": "Safra (ex: 2024/2025)." },
{ "field": "expectedQuantity", "type": "DECIMAL", "visibility": "REQUIRED", "helpText": "Quantidade de produto a ser entregue." },
{ "field": "quantityUnit", "type": "ENUM", "visibility": "REQUIRED", "enumValues": ["TONS", "BAGS_60KG", "BAGS_50KG", "ARROBAS", "LITERS", "OTHER"] },
{ "field": "deliveryLocation", "type": "STRING", "visibility": "REQUIRED" },
{ "field": "deliveryDeadline", "type": "DATE", "visibility": "REQUIRED" },
{ "field": "productPriceAtContract", "type": "DECIMAL", "visibility": "OPTIONAL", "helpText": "Preço unitário de referência." },
{ "field": "priceUnit", "type": "ENUM", "visibility": "OPTIONAL", "enumValues": ["PER_TON", "PER_BAG_60KG", "PER_ARROBA"] }
],
"allowedPaymentTypes": ["CPR"],
"paymentDefaults": {
"typeDefault": "CPR",
"interestApplicable": false,
"fineApplicable": true,
"discountApplicable": false
},
"sections": [
{ "id": "sec-01", "title": "Dados agronômicos", "description": "Informações sobre a cultura e produção.", "order": 1 },
{ "id": "sec-02", "title": "Registro e documentos", "description": null, "order": 2 }
],
"customFields": [
{
"id": "cf-001", "sectionId": "sec-01", "key": "variedadeSoja", "label": "Variedade de soja",
"fieldType": "SELECT", "required": true, "editable": true, "active": true, "category": "default",
"helpText": "Variedade da soja plantada.",
"options": [
{ "value": "TMG7062", "label": "TMG 7062 IPRO", "order": 1 },
{ "value": "M8644", "label": "M 8644 IPRO", "order": 2 },
{ "value": "OUTRA", "label": "Outra", "order": 3 }
],
"order": 1
},
{
"id": "cf-002", "sectionId": "sec-01", "key": "variedadeOutraDescricao", "label": "Descrição da variedade",
"fieldType": "TEXT", "required": false, "editable": true, "active": true, "category": "conditional",
"helpText": "Informe a variedade quando 'Outra' selecionada.",
"order": 2
},
{
"id": "cf-003", "sectionId": "sec-01", "key": "areaCultivada", "label": "Área cultivada (hectares)",
"fieldType": "NUMBER", "required": true, "editable": true, "active": true, "category": "default",
"validation": { "min": 0.1 },
"order": 3
},
{
"id": "cf-004", "sectionId": "sec-01", "key": "produtividadeEstimada", "label": "Produtividade estimada (sacas/ha)",
"fieldType": "NUMBER", "required": false, "editable": true, "active": true, "category": "default",
"order": 4
},
{
"id": "cf-005", "sectionId": "sec-01", "key": "producaoTotalEstimada", "label": "Produção total estimada (sacas)",
"fieldType": "NUMBER", "required": false, "editable": false, "active": true, "category": "default",
"helpText": "Calculado automaticamente: área × produtividade.",
"order": 5
},
{
"id": "cf-006", "sectionId": "sec-02", "key": "cprRegistrada", "label": "CPR registrada em cartório?",
"fieldType": "BOOLEAN", "required": true, "editable": true, "active": true, "category": "default",
"defaultValue": false,
"order": 1
},
{
"id": "cf-007", "sectionId": "sec-02", "key": "codigoCartorio", "label": "Código do cartório",
"fieldType": "TEXT", "required": false, "editable": true, "active": true, "category": "conditional",
"order": 2
},
{
"id": "cf-008", "sectionId": "sec-02", "key": "laudoVistoria", "label": "Laudo de vistoria",
"fieldType": "ATTACHMENT", "required": false, "editable": true, "active": true, "category": "default",
"validation": { "maxFileSize": 10, "allowedFileTypes": ["pdf", "jpg", "png"], "maxFiles": 3 },
"order": 3
}
],
"rules": [
{
"id": "rule-001",
"fieldId": "cf-001",
"trigger": "ON_CHANGE",
"active": true,
"operations": [
{
"conditions": [{ "fieldId": "cf-001", "operator": "EQUALS", "value": "OUTRA" }],
"actions": [
{ "type": "SHOW", "targetFieldId": "cf-002" },
{ "type": "SET_REQUIRED", "targetFieldId": "cf-002" }
]
},
{
"conditions": [{ "fieldId": "cf-001", "operator": "NOT_EQUALS", "value": "OUTRA" }],
"actions": [
{ "type": "HIDE", "targetFieldId": "cf-002" },
{ "type": "SET_OPTIONAL", "targetFieldId": "cf-002" },
{ "type": "CLEAR_VALUE", "targetFieldId": "cf-002" }
]
}
]
},
{
"id": "rule-002",
"fieldId": "cf-003",
"trigger": "ON_CALCULATE",
"active": true,
"calculation": {
"expression": "({cf-003} * {cf-004})",
"targetFieldId": "cf-005",
"precision": 0
}
},
{
"id": "rule-003",
"fieldId": "cf-006",
"trigger": "ON_CHANGE",
"active": true,
"operations": [
{
"conditions": [{ "fieldId": "cf-006", "operator": "EQUALS", "value": true }],
"actions": [
{ "type": "SHOW", "targetFieldId": "cf-007" },
{ "type": "SET_REQUIRED", "targetFieldId": "cf-007" }
]
},
{
"conditions": [{ "fieldId": "cf-006", "operator": "EQUALS", "value": false }],
"actions": [
{ "type": "HIDE", "targetFieldId": "cf-007" },
{ "type": "SET_OPTIONAL", "targetFieldId": "cf-007" },
{ "type": "CLEAR_VALUE", "targetFieldId": "cf-007" }
]
}
]
},
{
"id": "rule-004",
"fieldId": "cf-006",
"trigger": "ON_LOAD",
"active": true,
"operations": [
{
"conditions": [],
"actions": [
{ "type": "SET_VALUE", "targetFieldId": "cf-006", "value": false }
]
}
]
}
]
}false via regra ON_LOADbaseType = OTHER. Neste caso, a camada 2 é vazia — a entrada do dictionary para OTHER define baseTypeFields: []. Toda a especificidade do contrato vem da camada 3, definida pela empresa.Nota: O JSON abaixo é autocontido — inclui o snapshot da camada 1 (do dictionary OTHER), a camada 2 vazia, e a camada 3 configurada pela empresa.
{
"id": "tpl-other-001",
"companyId": "company-001",
"baseType": "OTHER",
"name": "Contrato de Parceria Agrícola",
"description": "Template para contratos de parceria agrícola customizados.",
"status": "ACTIVE",
"dictionaryVersion": 2,
"dictionarySnapshotAt": "2025-03-17T09:00:00.000+00:00",
"commonFields": [
{ "field": "code", "type": "STRING", "visibility": "REQUIRED" },
{ "field": "description", "type": "STRING", "visibility": "REQUIRED" },
{ "field": "total", "type": "DECIMAL", "visibility": "REQUIRED" },
{ "field": "startDate", "type": "DATE", "visibility": "REQUIRED" },
{ "field": "endDate", "type": "DATE", "visibility": "REQUIRED" },
{ "field": "interestRate", "type": "DECIMAL", "visibility": "OPTIONAL" },
{ "field": "interestRateType", "type": "ENUM", "visibility": "OPTIONAL", "defaultValue": "ANNUAL" },
{ "field": "interestCalculationMethod", "type": "ENUM", "visibility": "OPTIONAL", "defaultValue": "SIMPLE" },
{ "field": "correctionIndex", "type": "ENUM", "visibility": "OPTIONAL", "defaultValue": "NONE" },
{ "field": "paymentPeriodicity", "type": "ENUM", "visibility": "OPTIONAL" },
{ "field": "currency", "type": "ENUM", "visibility": "REQUIRED", "defaultValue": "BRL" },
{ "field": "typeDescription", "type": "STRING", "visibility": "REQUIRED", "helpText": "Descrição livre do instrumento jurídico." }
],
"baseTypeFields": [],
"allowedPaymentTypes": ["OTHER"],
"paymentDefaults": {
"typeDefault": "OTHER",
"interestApplicable": true,
"fineApplicable": true,
"discountApplicable": true
},
"sections": [
{ "id": "sec-pa-01", "title": "Dados da parceria", "description": "Informações sobre a parceria agrícola.", "order": 1 },
{ "id": "sec-pa-02", "title": "Documentos", "description": null, "order": 2 }
],
"customFields": [
{
"id": "cf-pa-001", "sectionId": "sec-pa-01", "key": "tipoParceria", "label": "Tipo de parceria",
"fieldType": "SELECT", "required": true, "editable": true, "active": true, "category": "default",
"helpText": "Modalidade da parceria agrícola.",
"options": [
{ "value": "MEACAO", "label": "Meação (50/50)", "order": 1 },
{ "value": "TERCO", "label": "Terço (1/3 proprietário)", "order": 2 },
{ "value": "ARRENDAMENTO", "label": "Arrendamento fixo", "order": 3 },
{ "value": "CUSTOM", "label": "Percentual customizado", "order": 4 }
],
"order": 1
},
{
"id": "cf-pa-002", "sectionId": "sec-pa-01", "key": "percentualProprietario", "label": "Percentual do proprietário (%)",
"fieldType": "NUMBER", "required": false, "editable": true, "active": true, "category": "conditional",
"helpText": "Informe o percentual quando 'Percentual customizado' selecionado.",
"validation": { "min": 0, "max": 100 },
"order": 2
},
{
"id": "cf-pa-003", "sectionId": "sec-pa-01", "key": "propriedadeNome", "label": "Nome da propriedade",
"fieldType": "TEXT", "required": true, "editable": true, "active": true, "category": "default",
"placeholder": "Ex: Fazenda Horizonte",
"order": 3
},
{
"id": "cf-pa-004", "sectionId": "sec-pa-01", "key": "areaTotal", "label": "Área total (hectares)",
"fieldType": "NUMBER", "required": true, "editable": true, "active": true, "category": "default",
"validation": { "min": 0.1 },
"order": 4
},
{
"id": "cf-pa-005", "sectionId": "sec-pa-01", "key": "culturaPrincipal", "label": "Cultura principal",
"fieldType": "TEXT", "required": true, "editable": true, "active": true, "category": "default",
"placeholder": "Ex: Soja, Milho safrinha",
"order": 5
},
{
"id": "cf-pa-006", "sectionId": "sec-pa-01", "key": "safra", "label": "Safra",
"fieldType": "TEXT", "required": true, "editable": true, "active": true, "category": "default",
"placeholder": "Ex: 2024/2025",
"order": 6
},
{
"id": "cf-pa-007", "sectionId": "sec-pa-02", "key": "contratoAssinado", "label": "Contrato assinado",
"fieldType": "ATTACHMENT", "required": false, "editable": true, "active": true, "category": "default",
"validation": { "maxFileSize": 10, "allowedFileTypes": ["pdf"], "maxFiles": 1 },
"order": 1
},
{
"id": "cf-pa-008", "sectionId": "sec-pa-02", "key": "observacoesGerais", "label": "Observações",
"fieldType": "TEXT_AREA", "required": false, "editable": true, "active": true, "category": "default",
"validation": { "maxLength": 2000 },
"order": 2
}
],
"rules": [
{
"id": "rule-pa-001", "fieldId": "cf-pa-001", "trigger": "ON_CHANGE", "active": true,
"operations": [
{
"conditions": [{ "fieldId": "cf-pa-001", "operator": "EQUALS", "value": "CUSTOM" }],
"actions": [
{ "type": "SHOW", "targetFieldId": "cf-pa-002" },
{ "type": "SET_REQUIRED", "targetFieldId": "cf-pa-002" }
]
},
{
"conditions": [{ "fieldId": "cf-pa-001", "operator": "NOT_EQUALS", "value": "CUSTOM" }],
"actions": [
{ "type": "HIDE", "targetFieldId": "cf-pa-002" },
{ "type": "SET_OPTIONAL", "targetFieldId": "cf-pa-002" },
{ "type": "CLEAR_VALUE", "targetFieldId": "cf-pa-002" }
]
}
]
}
]
}sections + customFields + rules). O tipo base OTHER não impõe nenhum campo específico (camada 2 vazia) — apenas a obrigatoriedade de typeDescription no contrato (campo da camada 1).| Campo do Contract | Descrição |
|---|---|
type | Tipo base herdado do template. Imutável. |
templateId | Referência ao template. Imutável. |
typeSpecificFields | Valores dos campos da camada 2. Validados contra o snapshot baseTypeFields do template (não contra o dictionary atual da plataforma). |
customFields | Valores dos campos customizados (camada 3). Validados contra a camada 3 do template. |
customFields armazenado:{
"variedadeSoja": "TMG7062",
"areaCultivada": 500.0,
"produtividadeEstimada": 65.0,
"producaoTotalEstimada": 32500,
"cprRegistrada": true,
"codigoCartorio": "1º Cartório de Lucas do Rio Verde",
"laudoVistoria": [
{ "fileId": "file-001", "fileName": "laudo_fazenda.pdf", "fileSize": 245000, "mimeType": "application/pdf", "uploadedBy": "user-001", "uploadedAt": "2025-03-17T09:00:00.000+00:00" }
]
}HIDE) não são armazenados — suas chaves simplesmente não existem no JSON.customFields é um snapshot dos valores. Se um campo for removido do template, o valor permanece no contrato. Se um campo for adicionado, contratos antigos não o possuem.ContractFieldDictionary — recurso de referência centralizado e versionado, gerido pelo AgRisk. O dictionary tem uma entrada por baseType, com a definição completa dos campos aplicáveis e das configurações de pagamento padrão.CPR_PHYSICAL):{
"baseType": "CPR_PHYSICAL",
"version": 3,
"commonFields": [
{ "field": "code", "type": "STRING", "visibility": "REQUIRED" },
{ "field": "total", "type": "DECIMAL", "visibility": "REQUIRED" },
{ "field": "startDate", "type": "DATE", "visibility": "REQUIRED" },
{ "field": "endDate", "type": "DATE", "visibility": "REQUIRED" },
{ "field": "interestRate", "type": "DECIMAL", "visibility": "HIDDEN", "helpText": "CPRs Físicas não possuem taxa de juros." },
{ "field": "paymentPeriodicity", "type": "ENUM", "visibility": "OPTIONAL", "defaultValue": "HARVEST" },
{ "field": "currency", "type": "ENUM", "visibility": "OPTIONAL", "defaultValue": "COMMODITY_LINKED" }
],
"baseTypeFields": [
{ "field": "crop", "type": "ENUM", "visibility": "REQUIRED", "enumValues": ["SOYBEAN", "CORN", "COTTON", "COFFEE", "SUGARCANE", "WHEAT", "RICE", "OTHER"] },
{ "field": "harvestSeason", "type": "STRING", "visibility": "REQUIRED" },
{ "field": "expectedQuantity", "type": "DECIMAL", "visibility": "REQUIRED" },
{ "field": "quantityUnit", "type": "ENUM", "visibility": "REQUIRED", "enumValues": ["TONS", "BAGS_60KG", "BAGS_50KG", "ARROBAS", "LITERS", "OTHER"] },
{ "field": "deliveryLocation", "type": "STRING", "visibility": "REQUIRED" },
{ "field": "deliveryDeadline", "type": "DATE", "visibility": "REQUIRED" },
{ "field": "productPriceAtContract", "type": "DECIMAL", "visibility": "OPTIONAL" },
{ "field": "priceUnit", "type": "ENUM", "visibility": "OPTIONAL", "enumValues": ["PER_TON", "PER_BAG_60KG", "PER_ARROBA"] }
],
"allowedPaymentTypes": ["CPR"],
"paymentDefaults": {
"typeDefault": "CPR",
"interestApplicable": false,
"fineApplicable": true,
"discountApplicable": false
},
"updatedAt": "2025-03-17T09:00:00.000+00:00"
}baseType (CPR_PHYSICAL, CPR_FINANCIAL, INVOICE, PURCHASE_SALE_CONTRACT, CCB, PROMISSORY_NOTE, OTHER) tem sua própria entrada no dictionary com os mesmos campos.enumValue, alterar paymentDefaults)./admin/contract-field-dictionary) e é documentada em runbook técnico interno, fora do escopo deste módulo.version (inteiro) incrementado a cada mudança aprovada na entrada daquele baseType. A versão é registrada no template no momento da criação (campo dictionaryVersion), permitindo rastrear contra qual snapshot do dictionary o template foi configurado.Nota: o formato exato do versionestá sob avaliação. A documentação atual considera inteiro incremental (1, 2, 3, ...). Pode evoluir para semver, timestamp ou outra convenção em revisão futura.
POST /v2/companies/:companyId/contract-templates, o backend:baseType informado.commonFields, baseTypeFields, allowedPaymentTypes e paymentDefaults para o template (snapshot).customFields, sections e rules enviados pela empresa (camada 3).dictionaryVersion e dictionarySnapshotAt marcando a fotografia capturada.POST /:templateId/refresh-dictionary). O refresh é atômico (substitui o snapshot inteiro) e preserva a camada 3 do template (customFields, sections, rules).companyId = null. Todo template tem uma empresa proprietária (companyId definido).customFields, apenas com o snapshot do dictionary. A empresa pode editar/desativar/excluir esses templates a qualquer momento como qualquer outro.baseType = OTHEROTHER tem:commonFields — campos comuns aplicáveis (camada 1), incluindo typeDescription como obrigatório.baseTypeFields: [] — vazio (não há campos específicos do "tipo" OTHER).allowedPaymentTypes: ["OTHER"].paymentDefaults — geralmente todos aplicáveis (true), permitindo flexibilidade na configuração da empresa.baseType = OTHER capturam essa entrada normalmente — o snapshot da camada 2 fica vazio e toda a especificidade vem da camada 3 da empresa.TEMPLATE_NAME_ALREADY_EXISTS.TEMPLATE_BASE_TYPE_IMMUTABLE.TEMPLATE_INACTIVE.CUSTOM_FIELD_KEY_ALREADY_EXISTS.CUSTOM_FIELD_KEY_CONFLICTS_WITH_BASE.SELECT, MULTI_SELECT e RADIO exigem ao menos 2 opções. Erro: SELECT_FIELD_REQUIRES_OPTIONS.GREATER_THAN, etc.) só são aceitos para campos numéricos. CONTAINS só para MULTI_SELECT. Erro: INVALID_RULE_OPERATOR.targetFieldId de uma regra ON_CALCULATE, ele deve ter editable: false. Erro: CALCULATED_FIELD_MUST_BE_READONLY.ON_CALCULATE não pode referenciar o próprio targetFieldId na expressão. Erro: CIRCULAR_CALCULATION_REFERENCE.type é herdado automaticamente. Erro: TEMPLATE_REQUIRED.required = true (que não estão ocultos por regra) devem estar presentes. Campos SELECT/RADIO/MULTI_SELECT devem conter valores das opções. Validações numéricas (min/max) e de texto (maxLength) são aplicadas. Erros: MISSING_CUSTOM_FIELD, INVALID_CUSTOM_FIELD_VALUE, CUSTOM_FIELD_OUT_OF_RANGE, CUSTOM_FIELD_TOO_LONG.templateId não pode ser alterado via PATCH. Erro: CONTRACT_TEMPLATE_IMMUTABLE.sections, customFields e rules inline.commonFields) e 2 (baseTypeFields), além de allowedPaymentTypes e paymentDefaults, da entrada do ContractFieldDictionary correspondente ao baseType informado. O snapshot fica armazenado no template (campos commonFields, baseTypeFields, allowedPaymentTypes, paymentDefaults, dictionaryVersion, dictionarySnapshotAt). Alterações posteriores do dictionary não afetam templates existentes.POST /:templateId/refresh-dictionary substitui de forma atômica as camadas 1 e 2 (commonFields, baseTypeFields), allowedPaymentTypes e paymentDefaults do template pelos valores atuais do ContractFieldDictionary correspondente ao baseType. A camada 3 (customFields, sections, rules) é preservada integralmente. Contratos já criados a partir do template não são afetados pelo refresh — eles têm seus próprios snapshots de valores. Erro: INCOMPATIBLE_CUSTOM_FIELD_KEY quando o refresh introduz campo da camada 1 ou 2 cuja field colide com key de campo customizado existente.| Status | Código | Descrição |
|---|---|---|
| 404 | TEMPLATE_NOT_FOUND | Template não encontrado. |
| 409 | TEMPLATE_NAME_ALREADY_EXISTS | Nome duplicado. |
| 422 | TEMPLATE_BASE_TYPE_IMMUTABLE | Tentativa de alterar tipo base. |
| 422 | TEMPLATE_INACTIVE | Template inativo. |
| 409 | CUSTOM_FIELD_KEY_ALREADY_EXISTS | Key duplicada no template. |
| 422 | CUSTOM_FIELD_KEY_CONFLICTS_WITH_BASE | Key colide com campo do tipo base. |
| 422 | SELECT_FIELD_REQUIRES_OPTIONS | SELECT/MULTI_SELECT/RADIO sem opções suficientes. |
| 422 | INVALID_VALIDATION_RULE | Regra de validação incompatível com tipo de campo. |
| 422 | INVALID_RULE_OPERATOR | Operador incompatível com tipo de campo na rule. |
| 422 | CALCULATED_FIELD_MUST_BE_READONLY | Campo alvo de cálculo não é read-only. |
| 422 | CIRCULAR_CALCULATION_REFERENCE | Referência circular em cálculo. |
| 422 | MISSING_CUSTOM_FIELD | Campo obrigatório ausente no contrato. |
| 422 | INVALID_CUSTOM_FIELD_VALUE | Valor inválido. |
| 422 | CUSTOM_FIELD_OUT_OF_RANGE | Fora do range min/max. |
| 422 | CUSTOM_FIELD_TOO_LONG | Texto excede maxLength. |
| 422 | INVALID_ATTACHMENT | Arquivo inválido. |
| 422 | CONTRACT_TEMPLATE_IMMUTABLE | Tentativa de alterar templateId do contrato. |
| 422 | INCOMPATIBLE_CUSTOM_FIELD_KEY | Refresh do dictionary introduziu campo da plataforma cuja key colide com campo customizado existente no template. |
| 404 | DICTIONARY_ENTRY_NOT_FOUND | Entrada do dictionary não encontrada para o baseType informado (situação anômala — indica problema na plataforma). |
/v2/companies/:companyId/contract-templatescompanyId sempre definido). A listagem é escopada por companyId via path. Quando uma empresa começa sem templates configurados, a Nagro pode criar um conjunto inicial via POST normal (ver seção 5.6) — templates com snapshot do dictionary atual e sem customFields, que a empresa pode editar/desativar a qualquer momento.sections, customFields e rules na mesma requisição, ou eles podem ser configurados separadamente via PUT depois.contract_template:create{
"baseType": "CPR_PHYSICAL",
"name": "CPR Soja — Safra",
"description": "Template para CPRs de soja com campos agronômicos.",
"sections": [
{ "title": "Dados agronômicos", "description": "Informações sobre a cultura e produção.", "order": 1 },
{ "title": "Registro e documentos", "order": 2 }
],
"customFields": [
{
"sectionId": null,
"key": "variedadeSoja",
"label": "Variedade de soja",
"fieldType": "SELECT",
"required": true,
"editable": true,
"active": true,
"category": "default",
"helpText": "Variedade da soja plantada.",
"options": [
{ "value": "TMG7062", "label": "TMG 7062 IPRO", "order": 1 },
{ "value": "M8644", "label": "M 8644 IPRO", "order": 2 },
{ "value": "OUTRA", "label": "Outra", "order": 3 }
],
"order": 1
},
{
"sectionId": null,
"key": "areaCultivada",
"label": "Área cultivada (hectares)",
"fieldType": "NUMBER",
"required": true,
"editable": true,
"active": true,
"category": "default",
"validation": { "min": 0.1 },
"order": 2
}
]
}id nos campos, seções ou regras — a API gera automaticamente. O sectionId nos campos é resolvido após a criação das seções; quando enviados juntos no POST, o backend vincula pela posição/ordem.{
"id": "tpl-001",
"companyId": "company-001",
"baseType": "CPR_PHYSICAL",
"name": "CPR Soja — Safra",
"description": "Template para CPRs de soja com campos agronômicos.",
"status": "ACTIVE",
"dictionaryVersion": 3,
"dictionarySnapshotAt": "2025-03-17T09:00:00.000+00:00",
"commonFields": [
{ "field": "code", "type": "STRING", "visibility": "REQUIRED" },
{ "field": "total", "type": "DECIMAL", "visibility": "REQUIRED" },
{ "field": "startDate", "type": "DATE", "visibility": "REQUIRED" },
{ "field": "endDate", "type": "DATE", "visibility": "REQUIRED" },
{ "field": "interestRate", "type": "DECIMAL", "visibility": "HIDDEN" },
{ "field": "paymentPeriodicity", "type": "ENUM", "visibility": "OPTIONAL", "defaultValue": "HARVEST" },
{ "field": "currency", "type": "ENUM", "visibility": "OPTIONAL", "defaultValue": "COMMODITY_LINKED" }
],
"baseTypeFields": [
{ "field": "crop", "type": "ENUM", "visibility": "REQUIRED", "enumValues": ["SOYBEAN", "CORN", "COTTON", "COFFEE", "SUGARCANE", "WHEAT", "RICE", "OTHER"] },
{ "field": "harvestSeason", "type": "STRING", "visibility": "REQUIRED" },
{ "field": "expectedQuantity", "type": "DECIMAL", "visibility": "REQUIRED" },
{ "field": "quantityUnit", "type": "ENUM", "visibility": "REQUIRED", "enumValues": ["TONS", "BAGS_60KG", "BAGS_50KG", "ARROBAS", "LITERS", "OTHER"] },
{ "field": "deliveryLocation", "type": "STRING", "visibility": "REQUIRED" },
{ "field": "deliveryDeadline", "type": "DATE", "visibility": "REQUIRED" },
{ "field": "productPriceAtContract", "type": "DECIMAL", "visibility": "OPTIONAL" },
{ "field": "priceUnit", "type": "ENUM", "visibility": "OPTIONAL", "enumValues": ["PER_TON", "PER_BAG_60KG", "PER_ARROBA"] }
],
"allowedPaymentTypes": ["CPR"],
"paymentDefaults": {
"typeDefault": "CPR",
"interestApplicable": false,
"fineApplicable": true,
"discountApplicable": false
},
"sections": [
{ "id": "sec-01", "title": "Dados agronômicos", "description": "Informações sobre a cultura e produção.", "order": 1 },
{ "id": "sec-02", "title": "Registro e documentos", "description": null, "order": 2 }
],
"customFields": [
{
"id": "cf-001",
"sectionId": "sec-01",
"key": "variedadeSoja",
"label": "Variedade de soja",
"fieldType": "SELECT",
"required": true,
"editable": true,
"active": true,
"category": "default",
"helpText": "Variedade da soja plantada.",
"placeholder": null,
"defaultValue": null,
"options": [
{ "value": "TMG7062", "label": "TMG 7062 IPRO", "order": 1 },
{ "value": "M8644", "label": "M 8644 IPRO", "order": 2 },
{ "value": "OUTRA", "label": "Outra", "order": 3 }
],
"validation": null,
"order": 1
},
{
"id": "cf-002",
"sectionId": "sec-01",
"key": "areaCultivada",
"label": "Área cultivada (hectares)",
"fieldType": "NUMBER",
"required": true,
"editable": true,
"active": true,
"category": "default",
"helpText": null,
"placeholder": null,
"defaultValue": null,
"options": null,
"validation": { "min": 0.1 },
"order": 2
}
],
"rules": [],
"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"
}| Status | Código |
|---|---|
| 409 | TEMPLATE_NAME_ALREADY_EXISTS |
| 422 | CUSTOM_FIELD_KEY_ALREADY_EXISTS |
| 422 | CUSTOM_FIELD_KEY_CONFLICTS_WITH_BASE |
| 422 | SELECT_FIELD_REQUIRES_OPTIONS |
contract_template:read| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
baseType | Enum | Não | Filtrar por tipo base. |
status | Enum | Não | ACTIVE ou INACTIVE. |
search | String | Não | Busca por name. |
orderBy | Enum | Não | Ordenação: name, createdAt. Default: name. |
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": "tpl-001",
"companyId": "company-001",
"baseType": "CPR_PHYSICAL",
"name": "CPR Soja — Safra",
"description": "Template para CPRs de soja com campos agronômicos.",
"summary": {
"sections": 2,
"customFields": 8,
"rules": 4
},
"status": "ACTIVE",
"createdAt": "2025-03-17T09:00:00.000+00:00"
},
{
"id": "tpl-002",
"companyId": "company-001",
"baseType": "CPR_PHYSICAL",
"name": "CPR Café — Safra",
"description": "Template para CPRs de café.",
"summary": {
"sections": 1,
"customFields": 5,
"rules": 2
},
"status": "ACTIVE",
"createdAt": "2025-03-18T10:00:00.000+00:00"
},
{
"id": "tpl-003",
"companyId": "company-001",
"baseType": "CPR_FINANCIAL",
"name": "CPR Financeira — Default",
"description": "Template inicial criado para a empresa, sem customização.",
"summary": {
"sections": 0,
"customFields": 0,
"rules": 0
},
"status": "ACTIVE",
"createdAt": "2025-03-16T08:00:00.000+00:00"
}
],
"nextPage": false
}contract_template:readContractFieldDictionary correspondente ao baseType do template. O refresh é atômico: substitui commonFields, baseTypeFields, allowedPaymentTypes e paymentDefaults de uma vez. A camada 3 (customFields, sections, rules) é preservada integralmente.contract_template:updatebaseType do template.dictionaryVersion e dictionarySnapshotAt refletindo o novo snapshot.{
"id": "tpl-001",
"companyId": "company-001",
"baseType": "CPR_PHYSICAL",
"name": "CPR Soja — Safra",
"dictionaryVersion": 4,
"dictionarySnapshotAt": "2025-04-10T14:30:00.000+00:00",
"commonFields": [ /* snapshot atualizado */ ],
"baseTypeFields": [ /* snapshot atualizado */ ],
"allowedPaymentTypes": ["CPR"],
"paymentDefaults": { /* ... */ },
"sections": [ /* preservado */ ],
"customFields": [ /* preservado */ ],
"rules": [ /* preservado */ ],
"status": "ACTIVE",
"updatedAt": "2025-04-10T14:30:00.000+00:00"
}INCOMPATIBLE_CUSTOM_FIELD_KEY (quando o snapshot atualizado introduz campo das camadas 1 ou 2 cuja field colide com key de campo customizado existente — exige resolução manual antes), DICTIONARY_ENTRY_NOT_FOUND (entrada do dictionary não encontrada para o baseType, situação anômala).ContractFieldDictionary para o baseType do template. Usado pela UI para sinalizar ao usuário se há atualização disponível e o que mudou antes de confirmar o refresh.contract_template:read{
"templateId": "tpl-001",
"baseType": "CPR_PHYSICAL",
"currentVersion": 3,
"latestVersion": 4,
"hasUpdate": true,
"diff": {
"commonFields": {
"added": [
{ "field": "correctionIndex", "type": "ENUM", "visibility": "OPTIONAL", "defaultValue": "NONE" }
],
"removed": [],
"changed": [
{ "field": "paymentPeriodicity", "previous": { "visibility": "OPTIONAL" }, "current": { "visibility": "REQUIRED" } }
]
},
"baseTypeFields": {
"added": [
{ "field": "registrationNumber", "type": "STRING", "visibility": "OPTIONAL" }
],
"removed": [],
"changed": []
},
"allowedPaymentTypes": {
"previous": ["CPR"],
"current": ["CPR"]
},
"paymentDefaults": {
"previous": { /* anterior */ },
"current": { /* atual */ }
}
}
}hasUpdate = false, o template já está na versão atual e os arrays de diff retornam vazios.name, description. Não altera seções, campos nem regras — esses são gerenciados pelos CRUDs individuais (ver seção 8.2).contract_template:update{
"name": "CPR Soja — Safra 24/25",
"description": "Template revisado para safra 24/25."
}TEMPLATE_NAME_ALREADY_EXISTS.sectionId; regras referenciam campos por fieldId e targetFieldId) exigem ordem na criação:sectionId recém-criados.fieldId e targetFieldId dos campos.contract_template:update{
"title": "Documentos complementares",
"description": "Anexos opcionais relacionados ao contrato.",
"order": 3
}{
"id": "sec-03",
"title": "Documentos complementares",
"description": "Anexos opcionais relacionados ao contrato.",
"order": 3
}title, description, order).contract_template:updatesectionId = null (órfãos), exibidos no topo do formulário.contract_template:updatecontract_template:update{
"sectionId": "sec-01",
"key": "sistemaPlantio",
"label": "Sistema de plantio",
"fieldType": "SELECT",
"required": false,
"editable": true,
"active": true,
"category": "default",
"options": [
{ "value": "DIRETO", "label": "Plantio direto", "order": 1 },
{ "value": "CONVENCIONAL", "label": "Convencional", "order": 2 }
],
"order": 6
}id gerado.CUSTOM_FIELD_KEY_ALREADY_EXISTS, CUSTOM_FIELD_KEY_CONFLICTS_WITH_BASE, SELECT_FIELD_REQUIRES_OPTIONS, INVALID_VALIDATION_RULE.contract_template:update{
"label": "Variedade de soja plantada",
"options": [
{ "value": "TMG7062", "label": "TMG 7062 IPRO", "order": 1 },
{ "value": "M8644", "label": "M 8644 IPRO", "order": 2 },
{ "value": "NS7709", "label": "NS 7709 IPRO", "order": 3 },
{ "value": "OUTRA", "label": "Outra", "order": 4 }
]
}CUSTOM_FIELD_KEY_ALREADY_EXISTS (se key for alterada e conflitar), SELECT_FIELD_REQUIRES_OPTIONS, INVALID_VALIDATION_RULE.customFields.{key} permanece nos contratos antigos).fieldId ou targetFieldId) também são removidas em cascata.contract_template:updatefieldId ou targetFieldId existente (criar campos antes).contract_template:update{
"fieldId": "cf-001",
"trigger": "ON_CHANGE",
"active": true,
"operations": [
{
"conditions": [{ "fieldId": "cf-001", "operator": "EQUALS", "value": "OUTRA" }],
"actions": [
{ "type": "SHOW", "targetFieldId": "cf-002" },
{ "type": "SET_REQUIRED", "targetFieldId": "cf-002" }
]
},
{
"conditions": [{ "fieldId": "cf-001", "operator": "NOT_EQUALS", "value": "OUTRA" }],
"actions": [
{ "type": "HIDE", "targetFieldId": "cf-002" },
{ "type": "SET_OPTIONAL", "targetFieldId": "cf-002" },
{ "type": "CLEAR_VALUE", "targetFieldId": "cf-002" }
]
}
]
}id gerado.INVALID_RULE_OPERATOR, CALCULATED_FIELD_MUST_BE_READONLY, CIRCULAR_CALCULATION_REFERENCE.contract_template:update{
"active": false
}contract_template:updatecontract_template:delete{
"status": "INACTIVE"
}{
"id": "tpl-001",
"status": "INACTIVE",
"updatedAt": "2025-03-20T11:00:00.000+00:00"
}| Resource | Domínio | Actions |
|---|---|---|
contract_template | TENANT | create, read, update, delete |
templateId (obrigatório, imutável), customFields (JSON).GET /contract-templates/:templateId — não há mais endpoint /schema separado. O template já carrega o snapshot autocontido das camadas 1, 2 e 3.templateId por contrato.key, validados contra o template.customFields registradas como customFields.{key}.