Install
$ agentstack add skill-snk-devcenter-addon-studio-business-rule ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
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")
public class ValidacaoDescontoRegra implements Regra {
private final DescontoService descontoService;
@Inject
public ValidacaoDescontoRegra(DescontoService descontoService) {
this.descontoService = descontoService;
}
@Override
public void beforeUpdate(ContextoRegra ctx) throws Exception {
DynamicVO notaVO = (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
@Override public void beforeInsert(ContextoRegra ctx) throws Exception {}
@Override public void afterInsert(ContextoRegra ctx) throws Exception {}
@Override public void afterUpdate(ContextoRegra ctx) throws Exception {}
@Override public void beforeDelete(ContextoRegra ctx) throws Exception {}
@Override public void afterDelete(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)
DynamicVO notaVO = (DynamicVO) ctx.getPrePersistEntityState().getNewVO();
// Estado anterior (disponivel em beforeUpdate e beforeDelete)
DynamicVO oldNotaVO = (DynamicVO) ctx.getPrePersistEntityState().getOldVO();
// Leitura de campos do DynamicVO
BigDecimal nuNota = notaVO.asBigDecimal("NUNOTA");
String confirmada = notaVO.asString("CONFIRMADA");
BigDecimal percDesc = 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)
LiberacaoSolicitada lib = new LiberacaoSolicitada(
notaVO.asBigDecimal("NUNOTA"), // numero da nota
"TGFCAB", // tabela
2000, // 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 revertida
throw new Exception("Limite de credito excedido. Operacao bloqueada.");
6. Detectar o momento da confirmacao
O evento beforeUpdate dispara em varios momentos. Para agir somente na confirmacao:
@Override
public void beforeUpdate(ContextoRegra ctx) throws Exception {
DynamicVO notaVO = (DynamicVO) ctx.getPrePersistEntityState().getNewVO();
DynamicVO oldNotaVO = (DynamicVO) ctx.getPrePersistEntityState().getOldVO();
// Abordagem 1: comparar campo CONFIRMADA entre old e new
boolean isConfirmando = "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")
public class LiberacaoDescontoRegra implements Regra {
@Override
public void beforeUpdate(ContextoRegra ctx) throws Exception {
DynamicVO notaVO = (DynamicVO) ctx.getPrePersistEntityState().getNewVO();
Boolean isConfirmando = (Boolean) JapeSession.getProperty("CabecalhoNota.confirmando.nota");
if (!Boolean.TRUE.equals(isConfirmando)) return;
BigDecimal percDesc = notaVO.asBigDecimal("PERCDESC");
if (percDesc == null || percDesc.compareTo(new BigDecimal("10")) integracaoService.enviar(nuNota));
}
// interface exige os 6; deixe vazios os que nao usar
@Override public void beforeInsert(ContextoRegra ctx) throws Exception {}
@Override public void beforeUpdate(ContextoRegra ctx) throws Exception {}
@Override public void afterInsert(ContextoRegra ctx) throws Exception {}
@Override public void beforeDelete(ContextoRegra ctx) throws Exception {}
@Override public void afterDelete(ContextoRegra ctx) throws Exception {}
}
8. Boas Praticas
- Velocidade: Regra roda dentro da transacao da confirmacao. Deve executar em milissegundos.
- Assincronismo para integracoes: Chamadas a APIs externas = sempre
CompletableFuture,ExecutorServiceou JMS. Nunca sincrono. - Logica em Services: Mantenha a classe da
@BusinessRuleenxuta — delegue para@Component. - Feedback ao usuario: Use
addMensagem()para informar acoes automaticas executadas. - Excecoes para bloqueio: Lance
Exceptioncom 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
@Callbackou@Listener. - [ ] Criar classe implementando
Regra(nomearRegra). - [ ] 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/newVOouJapeSession. - [ ] 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). Verdependency-injection.
Skills relacionadas
action-button— botão dispara fluxo que pode invocar regracontroller— controller pode invocar regra via barramentoentity— entidade alvo do eventorepository— acesso a dados dentro da regradependency-injection— wiring Guice dos services injetados na regratest— JUnit + Mockito daRegra
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: snk-devcenter
- Source: snk-devcenter/addon-studio
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.