# 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`. ```json { "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: ```json { "value": 100 } ``` ```json { "field": "valorUnitario" } ``` ```json { "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. ```json { "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. > [!NOTE] > O cálculo no navegador melhora a experiência. Ele nunca substitui o cálculo, a proteção readonly ou a validação do backend. Erros de prévia (divisão por zero) aparecem associados ao campo calculado. ### Usando o avaliador no seu código O frontend exporta o mesmo avaliador para páginas próprias: ```tsx 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](/docs/backend/esteiras-e-processos#bindings-cross-model); - ainda não possuir contrato declarativo. Fonte: https://sdk.oonapps.com/docs/backend/formulas-e-validacoes