Fala pessoal!
No dia 27/01 lançamos o “Sankhya Dev Talks”, nosso programa de eventos técnicos. Nesta primeira edição, conversamos sobre desenvolvimento de personalizações com módulo java. Nosso especialista em personalização, Wellyton Marques, apresentou conceitos, boas práticas, fluxo de trabalho, ferramentas de desenvolvimento, dentre outros tópicos. Ainda, foram desenvolvidos exemplos práticos funcionais de botão de ação, ação agendada e evento programado.
Confira abaixo uma seleção de recursos apresentados no evento, e também respostas para as principais dúvidas:
Sobre o evento
- Sankhya Dev Talks - conheça nosso programa de eventos técnicos: Sankhya Dev Talks
- Gravação do webinário : https://www.youtube.com/watch?v=m8LjHp5k3SI
Documentação técnica
Cases práticos
Código-fonte dos exemplos práticos
- ExemploAG.java
package br.com.sankhya.action.acaoagendada;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import org.cuckoo.core.ScheduledAction;
import org.cuckoo.core.ScheduledActionContext;
import com.sankhya.util.BigDecimalUtil;
import br.com.sankhya.jape.EntityFacade;
import br.com.sankhya.jape.core.JapeSession;
import br.com.sankhya.jape.core.JapeSession.SessionHandle;
import br.com.sankhya.jape.dao.JdbcWrapper;
import br.com.sankhya.jape.vo.DynamicVO;
import br.com.sankhya.jape.wrapper.JapeFactory;
import br.com.sankhya.jape.wrapper.JapeWrapper;
import br.com.sankhya.modelcore.util.DynamicEntityNames;
import br.com.sankhya.modelcore.util.EntityFacadeFactory;
public class ExemploAG implements ScheduledAction {
private JdbcWrapper jdbc = null;
@Override
public void onTime(ScheduledActionContext ctx) {
SessionHandle hnd = null;
try {
hnd = JapeSession.open();
EntityFacade dwfEntityFacade = EntityFacadeFactory.getDWFFacade();
jdbc = dwfEntityFacade.getJdbcWrapper();
JapeWrapper instanciaDAO = JapeFactory.dao(DynamicEntityNames.PARCEIRO);
DynamicVO registroVO = instanciaDAO.findOne("CODPARC = 1");
String mensagem = montaEmail("Parceiro codigo: "
+ registroVO.asBigDecimal("CODPARC")
+ " - Nome: "
+ registroVO.asString("NOMEPARC"));
enviarEmail("Teste Ação Agendada", mensagem, "[email protected]");
//System.out.println("EMAIL ENVIADO COM SUCESSO");
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcWrapper.closeSession(jdbc);
JapeSession.close(hnd);
}
}
public static void enviarEmail(String titulo, String mensagem, String dest) throws Exception {
SessionHandle hnd = null;
try {
hnd = JapeSession.open();
JapeWrapper ordemServicoDAO = JapeFactory.dao(DynamicEntityNames.FILA_MSG);
ordemServicoDAO.create()
.set("EMAIL", dest.trim())
.set("CODCON", BigDecimal.ZERO)
.set("CODMSG", null)
.set("STATUS", "Pendente")
.set("TIPOENVIO", "E")
.set("MAXTENTENVIO", BigDecimalUtil.valueOf(3))
.set("ASSUNTO", titulo)
.set("MENSAGEM", mensagem.toCharArray())
.save();
} catch (Exception e) {
e.printStackTrace();
} finally {
JapeSession.close(hnd);
}
}
public static String montaEmail(String texto) {
String email = usingBufferedReader();
email = email.replace("{{MENSAGEM}}", texto);
return email;
}
private static String usingBufferedReader() {
StringBuilder contentBuilder = new StringBuilder();
InputStream is = ExemploAG.class.getResourceAsStream("email.txt");
InputStreamReader reader = new InputStreamReader(is);
try {
BufferedReader br = new BufferedReader(reader);
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null) {
contentBuilder.append(sCurrentLine).append("\n");
}
} catch (Exception e) {
}
return contentBuilder.toString();
}
}
- email.txt
<html data-editor-version="2" class="sg-campaigns" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"/>
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
<!--[if (gte mso 9)|(IE)]>
<xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
<![endif]--><!--[if (gte mso 9)|(IE)]>
<style type="text/css"> body{width: 600px;margin: 0 auto;}table{border-collapse: collapse;}table, td{mso-table-lspace: 0pt;mso-table-rspace: 0pt;}img{-ms-interpolation-mode: bicubic;}</style>
<![endif]-->
<style type="text/css"> body, p, div{font-family: helvetica,arial,sans-serif; font-size: 14px;}body{color: #000000;}body a{color: #1188E6; text-decoration: none;}p{margin: 0; padding: 0;}table.wrapper{width:100% !important; table-layout: fixed; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: 100%; -moz-text-size-adjust: 100%; -ms-text-size-adjust: 100%;}img.max-width{max-width: 100% !important;}.column.of-2{width: 50%;}.column.of-3{width: 33.333%;}.column.of-4{width: 25%;}@media screen and (max-width:480px){.preheader .rightColumnContent, .footer .rightColumnContent{text-align: left !important;}.preheader .rightColumnContent div, .preheader .rightColumnContent span, .footer .rightColumnContent div, .footer .rightColumnContent span{text-align: left !important;}.preheader .rightColumnContent, .preheader .leftColumnContent{font-size: 80% !important; padding: 5px 0;}table.wrapper-mobile{width: 100% !important; table-layout: fixed;}img.max-width{height: auto !important; max-width: 480px !important;}a.bulletproof-button{display: block !important; width: auto !important; font-size: 80%; padding-left: 0 !important; padding-right: 0 !important;}.columns{width: 100% !important;}.column{display: block !important; width: 100% !important; padding-left: 0 !important; padding-right: 0 !important; margin-left: 0 !important; margin-right: 0 !important;}}</style>
<style type="text/css"> .star1:hover{background-image: url(https://marketing-image-production.s3.amazonaws.com/uploads/87451ec42a617538aaca6753c893d8b0a177fb0c00b60804d2f4445d1253bd7b4e7bf15c77c623680272deb81a9c6ad4a033e203cc1517659c733bade6b99d6b.png);}.star2:hover{background-image: url(https://marketing-image-production.s3.amazonaws.com/uploads/87451ec42a617538aaca6753c893d8b0a177fb0c00b60804d2f4445d1253bd7b4e7bf15c77c623680272deb81a9c6ad4a033e203cc1517659c733bade6b99d6b.png);}.star3:hover{background-image: url(https://marketing-image-production.s3.amazonaws.com/uploads/87451ec42a617538aaca6753c893d8b0a177fb0c00b60804d2f4445d1253bd7b4e7bf15c77c623680272deb81a9c6ad4a033e203cc1517659c733bade6b99d6b.png);}.star4:hover{background-image: url(https://marketing-image-production.s3.amazonaws.com/uploads/87451ec42a617538aaca6753c893d8b0a177fb0c00b60804d2f4445d1253bd7b4e7bf15c77c623680272deb81a9c6ad4a033e203cc1517659c733bade6b99d6b.png);}.star5:hover{background-image: url(https://marketing-image-production.s3.amazonaws.com/uploads/87451ec42a617538aaca6753c893d8b0a177fb0c00b60804d2f4445d1253bd7b4e7bf15c77c623680272deb81a9c6ad4a033e203cc1517659c733bade6b99d6b.png);}</style>
</head>
<body>
<center class="wrapper" data-link-color="#1188E6" data-body-style="font-size: 14px; font-family: helvetica,arial,sans-serif; color: #000000; background-color: #f3f3f4;">
<div class="webkit">
<table cellpadding="0" cellspacing="0" border="0" width="100%" class="wrapper" bgcolor="#f3f3f4">
<tr>
<td valign="top" bgcolor="#f3f3f4" width="100%">
<table width="100%" role="content-container" class="outer" align="center" cellpadding="0" cellspacing="0" border="0">
<tr>
<td width="100%">
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td>
<!--[if mso]>
<center>
<table>
<tr>
<td width="600">
<![endif]-->
<table width="100%" cellpadding="0" cellspacing="0" border="0" style="width: 100%; max-width:600px; padding-top: 30px" align="center">
<tr>
<td role="modules-container" style="padding: 0px 0px 0px 0px; color: #000000; text-align: left;" bgcolor="#f3f3f4" width="100%" align="left">
<table class="module preheader preheader-hide" role="module" data-type="preheader" border="0" cellpadding="0" cellspacing="0" width="100%" style="display: none !important; mso-hide: all; visibility: hidden; opacity: 0; color: transparent; height: 0; width: 0;">
<tr>
<td role="module-content">
<p>Avaliação de Atendimento</p>
</td>
</tr>
</table>
<table class="wrapper" role="module" data-type="image" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;">
<tr>
<td style="font-size:6px;line-height:10px;padding:025px 50px 25px 50px;background-color:#1e6533;" valign="top" align="center"> <img class="max-width" border="0" style="display:block;color:#000000;text-decoration:none;font-family:Helvetica, arial, sans-serif;font-size:16px;max-width:50% !important;width:50%;height:auto !important;" src="https://marketing-image-production.s3.amazonaws.com/uploads/6d6d72cd9de7a5de120f4c47317da854d912fa2505915f1a4edea2f1c9ef2c75feef345df96ed64fd8b3e5ac1a1b17a70c8c3c0a737f5c8f892f9fda2cd8a2f3.png" alt="" width="300" data-proportionally-constrained="true"> </td>
</tr>
</table>
<table class="module" role="module" data-type="text" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;border-left: 1px solid #d9d9d9 !important; border-right: 1px solid #d9d9d9 !important; border-collapse: separate">
<tr>
<td style="padding:30px 55px 0px 55px;line-height:22px;text-align:inherit;background-color:#fff;" height="100%" valign="top" bgcolor="#fff">
<div><span style="font-size:16px;"><span style="color:#474747;"><strong>Email Automatico via Ação Agendada</strong></span></span></div>
<div> </div>
<div><font color="#474747"><span style="font-size: 16px;">{{MENSAGEM}}<br/><br/></span></font></div>
</td>
</tr>
</table>
<table class="wrapper" role="module" data-type="image" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;">
<tr>
<td style="font-size:6px;line-height:10px;padding:15px 0px 15px 0px;background-color:#f3f3f4;" valign="top" align="center"> <img class="max-width" border="0" style="display:block;color:#000000;text-decoration:none;font-family:Helvetica, arial, sans-serif;font-size:16px;max-width:30% !important;width:30%;height:auto !important;" src="https://marketing-image-production.s3.amazonaws.com/uploads/8ea3bcadbebbe6e39799b6042d6858efb1ac73ffed1fd29b886f3070206f8379b85489854a9e53a2a4f043e97d82f432e2cd4d46a5f55f1a1da94e9273248b60.png" alt="" width="180"> </td>
</tr>
</table>
</td>
</tr>
</table>
<!--[if mso]>
</td>
</tr>
</table>
</center>
<![endif]-->
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</center>
</body>
</html>
- ExemploBTA.java
package br.com.sankhya.action.botaoacao;
import java.util.ArrayList;
import java.util.List;
import br.com.sankhya.extensions.actionbutton.AcaoRotinaJava;
import br.com.sankhya.extensions.actionbutton.ContextoAcao;
import br.com.sankhya.modelcore.util.PesquisaCepHelper;
import br.com.sankhya.modelcore.util.PesquisaCepHelper.Endereco;
public class ExemploBTA implements AcaoRotinaJava {
@Override
public void doAction(ContextoAcao contexto) throws Exception {
String cep = (String) contexto.getParam("CEP");
//Tentando a busca na base local
List<Endereco> cepsLocal = PesquisaCepHelper.obterDadosDoCepLocal(cep);
if (cepsLocal.size() > 0) {
contexto.setMensagemRetorno(buildResponse(cepsLocal));
return;
}
List<Endereco> cepsResolved = new ArrayList<Endereco>();
//Provedor SOAP Correios(http://apps.correios.com.br/SigepMasterJPA/AtendeClienteService/AtendeCliente)
try {
cepsResolved = PesquisaCepHelper.obterDadosDoCepCorreios(cep, false);
} catch (Exception e) {
contexto.setMensagemRetorno(e.getMessage());
return;
}
if (cepsResolved.size() > 0) {
contexto.setMensagemRetorno(resolveCepResponse(cepsResolved, cepsLocal, false));
return;
}
//Provedor Republica Virtual(http://republicavirtual.com.br/cep/index.php)
try {
cepsResolved = PesquisaCepHelper.obterDadosDoCepRepublicaVirtual(cep, false);
} catch (Exception e) {
contexto.setMensagemRetorno(e.getMessage());
return;
}
if (cepsResolved.size() > 0) {
contexto.setMensagemRetorno(resolveCepResponse(cepsResolved, cepsLocal, false));
return;
}
//Provedor ViaCep(https://viacep.com.br/)
try {
cepsResolved = PesquisaCepHelper.obterDadosDoCepViaCep(cep, false);
} catch (Exception e) {
contexto.setMensagemRetorno(e.getMessage());
return;
}
if (cepsResolved.size() > 0) {
contexto.setMensagemRetorno(resolveCepResponse(cepsResolved, cepsLocal, false));
return;
}
contexto.setMensagemRetorno("O CEP não foi encontrado em nenhuma API conhecida ou não existe!");
}
private String buildResponse(List<Endereco> ceps) {
StringBuilder ret = new StringBuilder();
for (Endereco endereco : ceps) {
ret.append("Endereço: \n");
ret.append("cep: " + endereco.getCep());
ret.append("\ncodBairro: " + endereco.getCodBairro());
ret.append("\ncodCid: " + endereco.getCodCid());
ret.append("\ncodEnd: " + endereco.getCodEnd());
ret.append("\ncodUf: " + endereco.getCodUf());
ret.append("\nDescBairro: " + endereco.getDescBairro());
ret.append("\nDescCidade: " + endereco.getDescCid());
ret.append("\nDescEndereço: " + endereco.getDescEnd());
ret.append("\nDescUF: " + endereco.getDescUf());
ret.append("\n\n");
}
return ret.toString();
}
private String resolveCepResponse(List<Endereco> cepsWebServices, List<Endereco> cepsFromLocal, Boolean insert) throws Exception {
Endereco cepFromWebService = cepsWebServices.get(0);
Endereco cepLocal = null;
if (cepsFromLocal != null && cepsFromLocal.size() > 0) {
cepLocal = cepsFromLocal.get(0);
}
List<Endereco> cepsResponse = new ArrayList<Endereco>();
if (!insert && cepFromWebService != null && cepLocal != null && PesquisaCepHelper.isDescriptionsDifferent(cepFromWebService, cepLocal)) {
cepsResponse.add(PesquisaCepHelper.updateAddress(cepLocal, cepFromWebService));
} else if (cepsFromLocal.isEmpty()) {
cepsResponse = cepsWebServices;
} else {
cepsResponse = cepsFromLocal;
}
return buildResponse(cepsResponse);
}
}
- ExemploEPJ.java
package br.com.sankhya.action.eventosprogramaveis;
import java.math.BigDecimal;
import br.com.sankhya.extensions.eventoprogramavel.EventoProgramavelJava;
import br.com.sankhya.jape.event.PersistenceEvent;
import br.com.sankhya.jape.event.TransactionContext;
import br.com.sankhya.jape.vo.DynamicVO;
import br.com.sankhya.modelcore.MGEModelException;
public class ExemploEPJ implements EventoProgramavelJava {
@Override
public void afterDelete(PersistenceEvent arg0) throws Exception {
// TODO Auto-generated method stub
}
@Override
public void afterInsert(PersistenceEvent arg0) throws Exception {
// TODO Auto-generated method stub
}
@Override
public void afterUpdate(PersistenceEvent arg0) throws Exception {
// TODO Auto-generated method stub
}
@Override
public void beforeCommit(TransactionContext arg0) throws Exception {
// TODO Auto-generated method stub
}
@Override
public void beforeDelete(PersistenceEvent arg0) throws Exception {
// TODO Auto-generated method stub
}
@Override
public void beforeInsert(PersistenceEvent arg0) throws Exception {
// travar ano < ANOFABRIC 2021
DynamicVO novoregistro = (DynamicVO) arg0.getVo();
if(novoregistro.asBigDecimal("ANOFABRIC").compareTo(new BigDecimal(2021)) < 0){
throw new MGEModelException("Não pode cadastrar veiculos com ano de fabricação menor que 2021");
}
}
@Override
public void beforeUpdate(PersistenceEvent arg0) throws Exception {
// TODO Auto-generated method stub
}
}
Resultado da enquete realizada no webinário:
Perguntas e Respostas:
Qual a melhor forma para debugar o módulo java?
- Caso o módulo esteja implantado em uma instância remota, ele poderia ser debugado remotamente, conforme descrito neste tutorial. Porém, é mais eficiente debugar usando uma base local, usando as ferramentas de debug do eclipse. Para configurar o ambiente de desenvolvimento localmente, consulte o artigo SDK Sankhya.
É possível baixar um módulo (.jar) após o upload?
- Atualmente, este recurso de download não está disponível, mas é possível acessar o módulo pelo banco de dados, ou solicitando diretamente ao desenvolvedor.
No evento programado, quando utilizar o método beforeCommit ?
- O método beforeCommit é executado após regras de negócios e listeners serem processados, para validação e verificação de dados, antes das operações serem persistidas no banco de dados. Nesse sentido, ele pode ser usado para garantir a integridade do banco de dados.
Como tenho acesso à documentação de referência dos métodos das APIs da Sankhya?
- Toda a documentação de referência das APIs públicas da Sankhya, disponível atualmente, pode ser consultada no portal Sankhya Developer.
É possível interagir com o usuário através de eventos programados sem ser utilizar o exception?
- O contexto do evento é separado do contexto da tela, por este motivo não é possível apresentar mensagens ao usuário sem utilizar o lançamento de exceções.
Onde encontro a documentação referente a inclusão de pedidos?
- Na API de serviços, disponível no portal Sankhya Developer: Cadastro de Pedidos.
Quais as configurações de hardware mínimas necessárias para instalação da base local?
- Confira no artigo SDK Sankhya, do portal Sankhya Developer, os pré-requisitos do sistema, recursos disponíveis e instruções de configuração.
O que você achou do evento? Ficou alguma dúvida?
Qual tema você gostaria que fosse abordado nos nossos talks?
Vote na enquete: Dê sua opinião: Temas Webinários Técnicos
Agradecemos a participação de todos e aguardamos vocês no próximo Sankhya Dev Talks
#SankhyaDeveloper