O Add-on Studio agora oferece uma nova abordagem para a criação das classes que manipulam objetos personalizados dentro do Sankhya, como:

  • Botão de Ação
  • Callback
  • Regra de Negócio

Essas classes, devem ser criadas dentro do diretório br.com.contextodoaddon, conforme imagem abaixo:

Requisitos para utilizar as anotações em seu projeto

  • Configurar no arquivo builde.gradle da raiz do projeto, as dependências do kotlin e do KSP, conforme abaixo:
    • classpath "com.google.devtools.ksp:symbol-processing-gradle-plugin:2.0.20-1.0.24"
    • classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.0"

Utilizando a anotação @Callback

A anotação @Callback deve ser utilizada em uma classe que implementa br.com.sankhya.modelcore.custommodule.ICustomCallBack.

Um callback é utilizado para ouvir eventos específicos de documentos dentro do Sankhya Om. Estes eventos são:

  • Antes ou Depois DE:
    • Inserção de Nota - CallbackEvent.INSERTION
    • Confirmação - CallbackEvent.CONFIRMATION
    • Processamento de Faturamento - CallbackEvent.PROCESS_BILLING
    • Processamento de Confirmação - CallbackEvent.PROCESS_CONFIRMATION

Abaixo segue um exemplo de callback executado ANTES de INSERIR uma nota:

package br.com.fabricante.addon.exemplos.anotacoes.callback;

import br.com.sankhya.modelcore.custommodule.ICustomCallBack;
import br.com.sankhya.studio.annotations.hooks.Callback;
import br.com.sankhya.studio.annotations.hooks.CallbackEvent;
import br.com.sankhya.studio.annotations.hooks.CallbackWhen;

import java.util.Map;

@Callback(
    when = CallbackWhen.BEFORE,
    event = CallbackEvent.INSERTION,
    description = "Callback Executa Acao Antes Inserir Nota"
)
public class CallbackAnotado implements ICustomCallBack {
    @Override
    public Object call(String id, Map<String, Object> data) {
        System.out.println("########### CALLBACK ANTES DE INSERIR NOTA ###############");
        return null;
    }
}

Dentro da anotação @Callback podemos verificar os seguintes itens:

  • when: Define em que momento a ação será executada em relação ao evento.
  • event: Define qual evento do ciclo de vida está sendo interceptado.
  • description: Texto explicativo ou rótulo que descreve a finalidade do callback. É útil para fins de documentação e leitura no código.

Utilizando a anotação @BusinessRule

A anotação @BusinessRule deve ser utilizada em uma classe que implementa br.com.sankhya.modelcore.comercial.Regra.

Uma regra é disparada em eventos de CRUD de notas, confirmação e faturamento. Diferente de um callback que é mais específico, uma Regra de Negócio contém toda regra de gerenciamento dos eventos na própria classe.

Abaixo segue um exemplo de como implementar uma regra de negócio dentro do seu addon:

package br.com.fabricante.addon.exemplos.anotacoes.regra;

import br.com.sankhya.modelcore.comercial.ContextoRegra;
import br.com.sankhya.modelcore.comercial.Regra;
import br.com.sankhya.studio.annotations.hooks.BusinessRule;

@BusinessRule(
    description = "Regra anotada"
)
public class RegraAnotada implements Regra {
    @Override
    public void beforeInsert(ContextoRegra ctx) throws Exception {
        System.out.println("############# REGRA ANTES INSERIR #################");
    }

    @Override
    public void beforeUpdate(ContextoRegra ctx) throws Exception {

    }

    @Override
    public void beforeDelete(ContextoRegra ctx) throws Exception {

    }

    @Override
    public void afterInsert(ContextoRegra ctx) throws Exception {

    }

    @Override
    public void afterUpdate(ContextoRegra ctx) throws Exception {

    }

    @Override
    public void afterDelete(ContextoRegra ctx) throws Exception {

    }
}

Dentro da anotação @BusinessRule podemos verificar o seguinte campo:

  • description: Representa a descrição da regra dentro do código.

Utilizando a anotação @ActionButton

A anotação @ActionButton deve ser utilizada em uma classe que implementa br.com.sankhya.extensions.actionbutton.AcaoRotinaJava.

Um botão de ação é inserido em telas do Sankhya Om, e fica visível através de um ícone, conforme mostrado na imagem abaixo:

Podemos criar dois tipos de botão de ação dentro do Sankhya, um com formulário e outro sem formulário.

Botão de ação sem formulário

O botão de ação sem formulário é um tipo de botão que, ao ser clicado diretamente na interface pelo usuário, dispara imediatamente uma ação programada, sem a necessidade de preenchimento ou submissão de um formulário. Quando o usuário interage com esse botão, a classe associada a ele é automaticamente invocada, executando a lógica previamente definida para aquela ação.

A seguir, apresentamos um exemplo de utilização de um botão de ação sem formulário:

package br.com.fabricante.addon.exemplos;

import br.com.sankhya.extensions.actionbutton.AcaoRotinaJava;
import br.com.sankhya.extensions.actionbutton.ContextoAcao;
import br.com.sankhya.studio.annotations.hooks.*;

@ActionButton(
    description = "Botao Acao Anotado sem Form",
    instanceName = "Veiculo",
    accessControlled = false,
    transactionType = TransactionType.AUTOMATIC,
    refreshType = RefreshTypeEnum.SELECTED_ITEMS
)

public class BotaoAcaoAnotadoSemForm  implements AcaoRotinaJava{

    @Override
    public void doAction(ContextoAcao contexto) throws Exception {
        System.out.println("################BOTÃO AÇÃO ANOTADO SEM FORMULARIO###############");
    }
}

Dentro da anotação @ActionButton podemos verificar os seguintes campos:

  • description: Representa o texto exibido na interface, servindo como identificação visual do botão de ação para o usuário.
  • instanceName: Representa qual a instância o botão de ação será criado dentro do Sankhya.
  • accessControlled: Define se o botão de ação estará sujeito ao controle de acesso (autorização)
  • transactionType: Determina o tipo de transação a ser utilizada durante a execução da ação.
    • Contém as seguintes opções: AUTOMATIC e MANUAL
  • refreshType: Define o comportamento de atualização da interface após a execução da ação.
    • Contém as seguintes opções: NONE_ITEM, ALL_ITEMS, SELECTED_ITEMS, PARENT_ITEM e MASTER_ITEM

Botão de ação com formulário

Um botão de ação também pode estar associado a um formulário, que é exibido ao usuário quando ele clica no botão. Nesse caso, a classe responsável pela execução da ação só será invocada após o usuário preencher o formulário e clicar em "Enviar".

Abaixo, temos um exemplo de botão de ação com formulário:

package br.com.fabricante.addon.exemplos.hooks;

import br.com.sankhya.studio.annotations.hooks.ActionButton;
import br.com.sankhya.studio.annotations.hooks.TransactionType;
import br.com.sankhya.studio.annotations.hooks.RefreshTypeEnum;
import br.com.sankhya.studio.annotations.hooks.Form;
import br.com.sankhya.studio.annotations.hooks.Field;
import br.com.sankhya.studio.annotations.hooks.FieldType;
import br.com.sankhya.studio.annotations.hooks.Option;
import br.com.sankhya.extensions.actionbutton.AcaoRotinaJava;
import br.com.sankhya.extensions.actionbutton.ContextoAcao;

@ActionButton(
    description = "Example Action Button",
    instanceName = "CabecalhoNota",
    accessControlled = true,
    transactionType = TransactionType.AUTOMATIC,
    resourceId = "resourceId.de.uma.tela.especifica",
    refreshType = RefreshTypeEnum.NONE_ITEM,
    form = @Form(fields = {
        @Field(
            label = "Field Text",
            name = "FIELD_TEXT",
            type = FieldType.TEXT,
            required = true
        ),
        @Field(
            label = "Field Integer",
            name = "FIELD_INTEGER",
            type = FieldType.INTEGER,
            required = true
        ),
        @Field(
            label = "Field Search",
            name = "FIELD_SEARCH",
            instance = "Veiculo",
            type = FieldType.SEARCH,
            required = false
        ),
        @Field(
            label = "Field Decimal",
            name = "FIELD_DECIMAL",
            type = FieldType.DECIMAL,
            precision = 6,
            required = true
        ),
        @Field(
            label = "Field Date",
            name = "FIELD_DATE",
            type = FieldType.DATE,
            required = true
        ),
        @Field(
            label = "Field Date Time",
            name = "FIELD_DATE_TIME",
            type = FieldType.DATE_TIME,
            required = true
        ),
        @Field(
            label = "Field Boolean",
            name = "FIELD_BOOLEAN",
            type = FieldType.BOOLEAN,
            required = true
        ),
        @Field(
            label = "Field List",
            name = "FIELD_LIST",
            type = FieldType.LIST,
            required = true,
            options = {@Option(label = "Option 1", value = "1"), @Option(label = "Option 2", value = "2")}
        )
    })
)
public class ActionButtonExample implements br.com.sankhya.extensions.actionbutton.AcaoRotinaJava  {
    @Override
  public void doAction(ContextoAcao contexto) throws Exception {
				System.out.println("Valor recebido do campo Field Text: " + contexto.getParam("FIELD_TEXT"));
        System.out.println("Valor recebido do campo Field Integer: " + contexto.getParam("FIELD_INTEGER"));
        System.out.println("Valor recebido do campo Field Search: " + contexto.getParam("FIELD_SEARCH"));
        System.out.println("Valor recebido do campo Field Decimal: " + contexto.getParam("FIELD_DECIMAL"));
        System.out.println("Valor recebido do campo Field Date: " + contexto.getParam("FIELD_DATE"));
    		System.out.println("Valor recebido do campo Field Date Time: " + contexto.getParam("FIELD_DATE_TIME"));
				System.out.println("Valor recebido do campo Field Boolean: " + contexto.getParam("FIELD_BOOLEAN"));
				System.out.println("Valor recebido do campo Field List: " + contexto.getParam("FIELD_LIST"));

    }
}



❗️

Importante

Quando o botão de ação possui um formulário, o atributo name deve ser utilizado para capturar os valores dos campos preenchidos pelo usuário, enquanto o atributo label define o texto visível na tela para cada campo do formulário.