# Validations e triggers > defineValidation valida o estado consolidado antes de persistir; defineTrigger registra efeitos antes e depois da mutação. ## defineValidation Use validations para regras de negócio síncronas com mensagens claras. ```javascript title="backend/src/validations/Pedido.js" const { defineValidation, GenericError } = require("@oondemand/oon-core-back"); defineValidation("Pedido", async (dados, contexto) => { if (dados.status === "Aprovado" && !(dados.valor > 0)) { throw new GenericError("Pedidos aprovados precisam de valor.", { statusCode: 422, code: "PEDIDO_SEM_VALOR", details: { field: "valor" }, }); } if (contexto.op === "update" && contexto.changedFields?.includes("fornecedor") && contexto.current.status !== "Rascunho") { throw new GenericError("O fornecedor só pode mudar em rascunho.", { statusCode: 422, code: "FORNECEDOR_BLOQUEADO" }); } }); ``` ### O contexto | Propriedade | Conteúdo | |---|---| | `op` | `"create"` ou `"update"` | | `method` | `"post"`, `"put"` ou `"patch"` | | `id` | Identificador em updates | | `current` | Registro antes da alteração | | `requestedChanges` | O que o cliente enviou | | `changes` | Somente os campos enviados e permitidos | | `consolidated` | Registro completo usado em `dados` | | `changedFields` | Campos cujo valor final realmente mudou (inclui derivados) | Em inclusões, a validation recebe os dados enviados. Em `PUT`/`PATCH`, o Core carrega o registro atual e entrega o **registro consolidado** — por isso formulários em abas e grids podem enviar só os campos alterados sem perder referências obrigatórias. > [!TIP] > Avalie `dados` como o estado final pretendido. Use `changes`/`changedFields` apenas quando a regra depender do que efetivamente mudou. A validation roda **depois** das fórmulas, das validações declarativas e das regras de processo. ## defineTrigger ```javascript title="backend/src/triggers/Pedido.js" const { defineTrigger } = require("@oondemand/oon-core-back"); defineTrigger("Pedido", { before: [async (doc, { op }) => { if (op === "create" && !doc.numero) doc.numero = await gerarNumero(); }], after: [async (doc) => { await registrarHistorico(doc); }], }); ``` Triggers são executados nos hooks `save` da model. ### Regras - Trigger não deve esconder regra crítica sem validação. - Evite efeitos irreversíveis sem log. - Integração externa deve passar por um serviço do App com timeout, idempotência e status rastreável. - Falhas de integração devem gerar estado visível, não quebrar silenciosamente o processo. - **Não trate hooks como entrega exatamente-uma-vez de efeitos externos.** ## Ordem completa de uma mutação ```txt requisição → auth → RBAC → escopo → readonly/computed protegidos → consolidação → fórmulas → validações declarativas → processo (transições, locks, bindings, invariantes) → defineValidation → trigger before → persistência → trigger after → recálculos dependentes → auditoria ``` Fonte: https://sdk.oonapps.com/docs/backend/validations-e-triggers