Fórmulas e validações

Campos computed, a AST de expressões, validações entre campos e a prévia reativa nos formulários — uma única declaração, autoridade no backend.

Campos calculados

computed é permitido em campos number, currency e currencyConverted.

{
  "kind": "currency",
  "computed": {
    "expression": { "op": "multiply", "args": [{ "field": "quantidade" }, { "field": "valorUnitario" }] },
    "precision": 2,
    "nullAsZero": true
  }
}
Propriedade Padrão Descrição
expression — Expressão obrigatória.
precision 2 Casas decimais, de 0 a 8.
nullAsZero true Trata campos ausentes ou vazios como zero.

Campos calculados:

  • são automaticamente readonly;
  • são recalculados no backend em criação, edição, patch e importação;
  • são calculados em ordem de dependência e não podem formar ciclos;
  • aparecem na metadata com readonly: true e a declaração computed.

Expressões

Uma expressão declara exatamente um destes nós:

{ "value": 100 }
{ "field": "valorUnitario" }
{ "op": "multiply", "args": [{ "field": "quantidade" }, { "field": "valorUnitario" }] }

Operadores

Grupo Operadores
Aritméticos add, subtract, multiply, divide, min, max, abs, negate, coalesce
Comparação eq, neq, gt, gte, lt, lte
Lógicos e presença and, or, not, present, in
Somente em processos if, concat, formatCurrency

Divisão por zero e valores não numéricos geram DomainRuleError com status 422.

Validações entre campos

As validações rodam depois que o Core consolidou o registro e recalculou todos os dependentes.

{
  "name": "valor-pago-valido",
  "code": "PAGAMENTO_ACIMA_CONTRATADO",
  "field": "valorPago",
  "message": "O valor pago não pode superar o valor contratado.",
  "when": { "op": "present", "args": [{ "field": "valorPago" }] },
  "assert": { "op": "lte", "args": [{ "field": "valorPago" }, { "field": "valorContratado" }] }
}
Propriedade Obrigatória Descrição
name sim Identificador único dentro da model.
message sim Mensagem apresentada ao usuário.
assert sim Expressão que deve resultar em verdadeiro.
when não Condição para executar a regra.
field não Campo associado ao erro.
code não Código em maiúsculas para tratamento programático.

Falhas geram DomainRuleError com statusCode: 422, code, field, rule e detalhes compatíveis com o envelope de erros.

Prévia reativa no frontend

Campos computed são recalculados imediatamente nos formulários padrão do oon-core-front — sem repetir a fórmula no frontend.

  1. O backend carrega e valida central.domain.json.
  2. A metadata expõe readonly e computed.
  3. O frontend interpreta a mesma AST fechada para exibir a prévia.
  4. Calculados e readonly são removidos do payload enviado.
  5. O backend recalcula, valida e persiste o valor autoritativo.
  6. O formulário passa a exibir o registro devolvido pelo servidor.

Formulários atendidos: formulário dinâmico de coleções, formulário principal da modal com abas, criação e edição, e formulários com apresentação local desde que a model venha da metadata.

Usando o avaliador no seu código

O frontend exporta o mesmo avaliador para páginas próprias:

import { evaluateDomainExpression, applyReactiveFormulas, buildDomainMutationPayload } from "@oondemand/oon-core-front";

const total = evaluateDomainExpression(
  { op: "multiply", args: [{ field: "quantidade" }, { field: "valorUnitario" }] },
  { quantidade: 2, valorUnitario: 50 },
); // 100

Quando usar código local

Não crie funções de cálculo em componentes para campos já descritos por computed. Use código local (no backend) apenas quando a regra:

  • não puder ser representada pela AST;
  • depender de consulta externa;
  • exigir agregação de registros relacionados — prefira os bindings de processo;
  • ainda não possuir contrato declarativo.