Cria, revisa e refatora regras de negócio Sankhya com `@BusinessRule` (interface `Regra` + `ContextoRegra`) para barramento de eventos, liberação de limite e regras transacionais. Use ao criar, alterar, revisar, auditar ou padronizar regras de negócio, ao implementar `beforeInsert`/`beforeUpdate`/`beforeDelete`/`afterInsert`/`afterUpdate`/`afterDelete`, ao trabalhar com arquivos `*Regra.java`, ou ao tocar em código com `@BusinessRule`.
التثبيت
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
Cria, revisa e refatora regras de negócio Sankhya com `@BusinessRule` (interface `Regra` + `ContextoRegra`) para barramento de eventos, liberação de limite e regras transacionais. Use ao criar, alterar, revisar, auditar ou padronizar regras de negócio, ao implementar `beforeInsert`/`beforeUpdate`/`beforeDelete`/`afterInsert`/`afterUpdate`/`afterDelete`, ao trabalhar com arquivos `*Regra.java`, ou ao tocar em código com `@BusinessRule`.
Regra de Negocio (@BusinessRule) — Addon Studio 2.0
@BusinessRule implementa logica automatica disparada por eventos do ciclo de vida comercial — principalmente confirmacao e faturamento de documentos (Pedidos, Notas de Venda). Disponivel a partir do Addon Studio 2.0.
Referencias complementares:
addon-studio — Stack + restricoes Java 8
dependency-injection — Injecao de dependencia (Guice)
1. Quando usar — @BusinessRule vs @Callback vs @Listener
Hook
Escopo
Quando usar
@BusinessRule
Notas de Saida e Mov. Interna (Vendas, Remessas, etc.)
Logica que interage com barramento de regras (ContextoRegra): liberacoes de limite, validacoes complexas na confirmacao/faturamento.
@Callback
Todos documentos comerciais, incluindo Notas de Entrada
Eventos de negocio onde @BusinessRule nao atua (ex: notas de compra) ou quando barramento nao e necessario.
@Listener
Operacoes CRUD (insert/update/delete) em qualquer entidade
Validacoes e modificacoes de campo disparadas ao salvar/excluir. Preferir para CRUD simples.
Regra rapida:
Liberacao de limite em nota de venda? @BusinessRule.
Validar nota de compra na confirmacao? @Callback.
Logica ao salvar/excluir qualquer registro? @Listener.
2. Anatomia de um @BusinessRule
import br.com.sankhya.jape.vo.DynamicVO;
import br.com.sankhya.modelcore.comercial.Regra;
import br.com.sankhya.modelcore.comercial.ContextoRegra;
import br.com.sankhya.studio.annotations.hooks.BusinessRule;
import com.google.inject.Inject;
@BusinessRule(description = "Valida desconto na confirmacao")publicclassValidacaoDescontoRegraimplementsRegra {
privatefinal DescontoService descontoService;
@InjectpublicValidacaoDescontoRegra(DescontoService descontoService) {
this.descontoService = descontoService;
}
@OverridepublicvoidbeforeUpdate(ContextoRegra ctx)throws Exception {
DynamicVOnotaVO= (DynamicVO) ctx.getPrePersistEntityState().getNewVO();
// logica de negocio delegada ao Service
descontoService.validar(notaVO, ctx.getBarramentoRegra());
}
// A interface exige os 6 metodos (sem default) — deixe vazios os que nao usar@OverridepublicvoidbeforeInsert(ContextoRegra ctx)throws Exception {}
@OverridepublicvoidafterInsert(ContextoRegra ctx)throws Exception {}
@OverridepublicvoidafterUpdate(ContextoRegra ctx)throws Exception {}
@OverridepublicvoidbeforeDelete(ContextoRegra ctx)throws Exception {}
@OverridepublicvoidafterDelete(ContextoRegra ctx)throws Exception {}
}
3. Atributo da anotacao @BusinessRule
Atributo
Obrigatorio
Descricao
description
Sim
Descricao legivel da regra — aparece nos logs e configuracoes.
4. Interface Regra — Metodos disponíveis
A interface declara 6 metodos abstratos, sem default — toda classe implements Regra precisa declarar os 6. Implemente a logica nos necessarios e deixe corpo vazio nos demais.
Metodo
Quando dispara
Foco da @BusinessRule
beforeInsert(ctx)
Antes de inserir o documento
Raramente usado — prefira @Listener
afterInsert(ctx)
Apos inserir o documento
Raramente usado — prefira @Listener
beforeUpdate(ctx)
Antes de atualizar (inclui confirmacao/faturamento)
Caso de uso principal
afterUpdate(ctx)
Apos atualizar (inclui confirmacao/faturamento)
Integracoes assincronas pos-confirmacao
beforeDelete(ctx)
Antes de excluir o documento
Raramente usado — prefira @Listener
afterDelete(ctx)
Apos excluir o documento
Raramente usado — prefira @Listener
5. ContextoRegra — API
Imports usados nos trechos: br.com.sankhya.jape.vo.DynamicVO e, para propriedades de sessao, br.com.sankhya.jape.core.JapeSession.
Acessar dados da nota
// Estado atual (com modificacoes do evento)DynamicVOnotaVO= (DynamicVO) ctx.getPrePersistEntityState().getNewVO();
// Estado anterior (disponivel em beforeUpdate e beforeDelete)DynamicVOoldNotaVO= (DynamicVO) ctx.getPrePersistEntityState().getOldVO();
// Leitura de campos do DynamicVOBigDecimalnuNota= notaVO.asBigDecimal("NUNOTA");
Stringconfirmada= notaVO.asString("CONFIRMADA");
BigDecimalpercDesc= notaVO.asBigDecimal("PERCDESC");
// Escrita de campo (modificacao em memoria, persiste com a transacao)
notaVO.setProperty("OBSERVACAO", "Conferido automaticamente.");
Interagir com barramento de regras
// Aviso nao bloqueante para o usuario
ctx.getBarramentoRegra().addMensagem("Desconto acima do limite — aviso gerado.");
// Solicitacao de liberacao de limite (evento deve estar cadastrado no sistema)LiberacaoSolicitadalib=newLiberacaoSolicitada(
notaVO.asBigDecimal("NUNOTA"), // numero da nota"TGFCAB", // tabela2000, // ID do evento de liberacao
BigDecimal.ONE // ID do usuario solicitante
);
lib.setPendente(true);
ctx.getBarramentoRegra().addLiberacaoSolicitada(lib);
Bloquear a operacao
// Lance excecao — mensagem exibida ao usuario e transacao revertidathrownewException("Limite de credito excedido. Operacao bloqueada.");
6. Detectar o momento da confirmacao
O evento beforeUpdate dispara em varios momentos. Para agir somente na confirmacao:
@OverridepublicvoidbeforeUpdate(ContextoRegra ctx)throws Exception {
DynamicVOnotaVO= (DynamicVO) ctx.getPrePersistEntityState().getNewVO();
DynamicVOoldNotaVO= (DynamicVO) ctx.getPrePersistEntityState().getOldVO();
// Abordagem 1: comparar campo CONFIRMADA entre old e newbooleanisConfirmando="S".equals(notaVO.asString("CONFIRMADA"))
&& (oldNotaVO == null || !"S".equals(oldNotaVO.asString("CONFIRMADA")));
if (!isConfirmando) return;
// ... logica especifica da confirmacao
}
7. Exemplos completos
Exemplo 1: Solicitacao de liberacao de limite
import br.com.sankhya.jape.core.JapeSession;
import br.com.sankhya.jape.vo.DynamicVO;
import br.com.sankhya.modelcore.comercial.Regra;
import br.com.sankhya.modelcore.comercial.ContextoRegra;
import br.com.sankhya.modelcore.comercial.LiberacaoSolicitada;
import br.com.sankhya.studio.annotations.hooks.BusinessRule;
import com.google.inject.Inject;
import java.math.BigDecimal;
@BusinessRule(description = "Solicita liberacao para vendas com desconto alto")publicclassLiberacaoDescontoRegraimplementsRegra {
@OverridepublicvoidbeforeUpdate(ContextoRegra ctx)throws Exception {
DynamicVOnotaVO= (DynamicVO) ctx.getPrePersistEntityState().getNewVO();
BooleanisConfirmando= (Boolean) JapeSession.getProperty("CabecalhoNota.confirmando.nota");
if (!Boolean.TRUE.equals(isConfirmando)) return;
BigDecimalpercDesc= notaVO.asBigDecimal("PERCDESC");
if (percDesc == null || percDesc.compareTo(newBigDecimal("10")) <= 0) return;
LiberacaoSolicitadalib=newLiberacaoSolicitada(
notaVO.asBigDecimal("NUNOTA"),
"TGFCAB",
2000, // ID do evento de liberacao cadastrado no sistema
BigDecimal.ONE
);
lib.setPendente(true);
ctx.getBarramentoRegra().addLiberacaoSolicitada(lib);
ctx.getBarramentoRegra().addMensagem("Solicitacao de liberacao enviada para desconto acima de 10%.");
}
// interface exige os 6; deixe vazios os que nao usar@OverridepublicvoidbeforeInsert(ContextoRegra ctx)throws Exception {}
@OverridepublicvoidafterInsert(ContextoRegra ctx)throws Exception {}
@OverridepublicvoidafterUpdate(ContextoRegra ctx)throws Exception {}
@OverridepublicvoidbeforeDelete(ContextoRegra ctx)throws Exception {}
@OverridepublicvoidafterDelete(ContextoRegra ctx)throws Exception {}
}
Velocidade: Regra roda dentro da transacao da confirmacao. Deve executar em milissegundos.
Assincronismo para integracoes: Chamadas a APIs externas = sempre CompletableFuture, ExecutorService ou JMS. Nunca sincrono.
Logica em Services: Mantenha a classe da @BusinessRule enxuta — delegue para @Component.
Feedback ao usuario: Use addMensagem() para informar acoes automaticas executadas.
Excecoes para bloqueio: Lance Exception com mensagem clara para impedir a operacao.
9. Anti-Patterns (PROIBIDO)
Anti-Pattern
Correcao
Usar para CRUD simples (salvar/excluir)
Usar @Listener
Chamada sincrona a API/Web Service
Usar CompletableFuture ou JMS
Logica de negocio no metodo da interface
Mover para Service (@Component)
Usar afterInsert para validacao
Validar em beforeInsert — apos salvar e tarde demais
new em dependencias gerenciadas
Injetar via construtor com @Inject
Usar para Notas de Entrada (compras)
Usar @Callback
10. Checklist: Novo @BusinessRule
Confirmar que o caso de uso e especifico de nota de saida/mov. interna — senao usar @Callback ou @Listener.
Criar classe implementando Regra (nomear <Feature>Regra).
Anotar com @BusinessRule(description = "...").
Injetar dependencias via construtor com @Inject (Guice).
Implementar apenas os metodos de evento necessarios.
Detectar o momento correto (confirmacao, faturamento) via comparacao oldVO/newVO ou JapeSession.
Delegar logica de negocio para Service (@Component).
Integracoes externas: usar mecanismo assincrono.
Fornecer feedback ao usuario via addMensagem() ou excecao com mensagem clara.
Registrar no modulo Guice os services/dependencias injetados na classe — a classe da regra em si nao precisa de binding (o SDK a descobre pela anotacao @BusinessRule). Ver dependency-injection.
Skills relacionadas
action-button — botão dispara fluxo que pode invocar regra
controller — controller pode invocar regra via barramento
entity — entidade alvo do evento
repository — acesso a dados dentro da regra
dependency-injection — wiring Guice dos services injetados na regra