quinta-feira, 29 de novembro de 2012

Genexus Business Component - Parte I

Ao desenvolver aplicativos através do Genexus, podemos determinar diferentes formas de atualizar a nossa base de dados, seja através de transações, procedimentos ou até web panels. Cada uma destas opções possui os seus prós e contras de utilização.

O grande diferencial das transações, é a sua facilidade de criação, já que o analista não necessita programar as rotinas de inserção, alteração e exclusão dos dados informados pelo usuário.

Já os procedimentos são utilizados quando há a necessidade de realizar inserções/alterações/exclusões com muitos dados de forma automatizada e até por rotinas batch. Sua principal característica é sua alta performance, principalmente quando utilizamos a função "Blocking" para estas grandes atualizações.

Porém e quando necessitamos trabalhar com uma web panel, quem sabe um grid de clientes que informe entre outros dados, a coluna ativo/inativo. E, através de um clique sobre esta coluna, este status é alterado, sem a necessidade de entrar no modo alteração da transação, alterar o valor do atributo e clicar em confirmar. São em situações como esta que a utilização de Business Component (BC) é a mais recomendada.

Lembre-se

Antes de visualizarmos alguns exemplos do Business Component em ação, precisamos lembrar que:
  1. Os Data Providers podem ser utilizados junto com o Business Component apenas para operações de inserção;
  2. O Business Component omite o valor da propriedade "commit on exit" dos objetos. Isto é, ao utilizarmos o BC precisamos utilizar o comando "commit" para finalizar a UTL;
  3. O BC importa algumas regras e eventos definidos na sua respectiva transação:
    1. todas as regras são executadas, exceto aquelas que chamam outro objeto com interface, e regras como parm, prompt, noprompt;
    2. todos os eventos são ignorados, exceto os eventos START e AFTER TRN. Comandos que chamam outro objeto com interface (WebPanel.Call()) são ignorados sempre;
  4. Para capturarmos as mensagens de erro utilizamos a variável "messages", programando:
&messages = &VariavelBC.GetMessages()
for &message in &messages
endfor

Inserindo valores através de Business Component

Para exemplificar o método de inserção utilizando BC, considere uma aplicação Genexus para uma livraria. Neste livraria os livros são catalogados por Assunto, Editora e edição correspondente. A partir do seu Assunto cada livro recebe um código único. Neste código, os três primeiros dígitos é o código de seu assunto e os três últimos são sequenciais. Então, os livros do assunto "Negócios" (código 100), terão códigos de 100001 a 100999.

De acordo com esta definição, o desenho de nossa transação Livro e suas regras definidas serão:
Livros

Genexus Transação
//=====Define a Data de inserção como Data de Cadastro=====
Default(LivroDataCadastro,&Today);

//=====Serializa o Código do Livro, de acordo com seu Assunto=====
LivroCodigo = SerializaLivroCodigo.Udp(AssuntoCod) 
on beforeinsert;

Antes de tudo, para utilizarmos o BC precisamos definir qual a transação que iremos trabalhar. Definida esta transação, em suas propriedades, precisamos definir o item "Business Component" como True, conforme figura abaixo:

Business Component


Para facilitarmos a inserção de novos livros, é criado uma Web Panel contendo um grid, com todos os livros registrados. Na última coluna da direita deste grid, inserimos uma imagem e criamos um evento associado a esta, com a opção de clonar este livro. Isto é, inserir um novo livro a partir dos dados do livro selecionado. Logo em nossa form teríamos:

Genexus Grid

Obs.: Este grid contém todos os atributos da transação Livro, aqueles que não nos interessa mostrar para o usuário estar marcados como invisíveis. Mais adiante será explicado o porque.

Adicionamos a variável "Livro" que terá como Tipo de Dado o Business Component Livro. Agora, na aba de eventos desta Web Panel, iremos programar o evento associado ao clique da imagem "Clonar":
Event 'ClonarLivro'
//=====Referencia um novo registro=====
&Livro = new()

//=====Iguala Atributos do BC ao da linha selecionada=====
&Livro.LivroNome = LivroNome
&Livro.LivroSinopse = LivroSinopse
&Livro.LivroAtivo = LivroAtivo
&Livro.LivroDataLancamento = LivroDataLancamento
&Livro.LivroCapa = LivroCapa
&Livro.LivroEdicao = LivroEdicao
&Livro.LivroPaginas = LivroPaginas
&Livro.LivroValor = LivroValor
&Livro.AssuntoCod = AssuntoCod
&Livro.EditoraId = EditoraId

//=====Salva os Dados=====
&Livro.Save()

//=====Finaliza a UTL=====
commit

//=====Atualiza a página para aparecer o novo registro no grid=====
Refresh
EndEvent
Note que, todos os atributos referenciados estão presentes no grid, alguns visíveis outros não. Isto é necessário para que ele carregue corretamente o valor de cada atributo.

Quando este Business Component for executado, as regras correspondentes a sua transação são carregadas automaticamente. Nestas regras, o atributo LivroDataCadastro recebe o valor default do dia e, o atributo LivroCodigo recebe um valor definido através de um procedimento. Por isso, estes dois atributos não são assinalados no evento "ClonarLivro".

Inserindo valores em transações com níveis

Agora a situação é um pouco diferente, após algum tempo foi verificado a necessidade de adicionar o(s) autor(es) de cada livro. Considere que um livro pode ter mais de um autor e um autor pode ter mais de um livro, logo o desenho da transação ficará (AutorCodigo é chave estrangeira):

Genexus Transação

Após isto será necessário alterar o evento "ClonarLivro" da nossa Web Panel, a variável "LivroAutores" é do tipo de dado - Business Component: Livro.Autores:

Event 'ClonarLivro'
//=====Referencia um novo registro=====
&Livro = new()

//=====Iguala Atributos do BC ao da linha selecionada=====
&Livro.LivroNome = LivroNome
&Livro.LivroSinopse = LivroSinopse
&Livro.LivroAtivo = LivroAtivo
&Livro.LivroDataLancamento = LivroDataLancamento
&Livro.LivroCapa = LivroCapa
&Livro.LivroEdicao = LivroEdicao
&Livro.LivroPaginas = LivroPaginas
&Livro.LivroValor = LivroValor
&Livro.AssuntoCod = AssuntoCod
&Livro.EditoraId = EditoraId

//=====Referencia novo registro de Autor A===== &LivroAutores = new() &LivroAutores.AutorCodigo = 1 //=====Adiciona referencia ao primeiro nível===== &Livro.Autores.Add(&LivroAutores) //=====Referencia novo registro de Autor B===== &LivroAutores = new() &LivroAutores.AutorCodigo = 2 //=====Adiciona referencia ao primeiro nível===== &Livro.Autores.Add(&LivroAutores)

//=====Salva os Dados=====
&Livro.Save()

//=====Finaliza a UTL=====
commit

//=====Atualiza a página para aparecer o novo registro no grid=====
Refresh
EndEvent
Note que a forma de trabalho do Business Component é muito semelhante ao trabalho com SDTs, possuem os mesmo comandos "new" e "add".

Na próxima parte vamos ver como inserir dados a partir de um Data Provider (ai o bicho pega) e as operações de Alteração e Exclusão de dados.

Era isso gurizada, qualquer dúvida ou sugestão enviem através dos comentários ou então pelo email genexus@outlook.com. Abraço

quinta-feira, 22 de novembro de 2012

Certificação Genexus - Experiência Pessoal

Terça-feira, 19 de novembro realizei a tão esperada prova de certificação da Artech para analista sênior. Hoje irei contar como foi o passo a passo desta experiência, desde o contato junto ao centro de treinamento, responsável por realizar a prova, até a correção desta.

Como Realizar a Inscrição?

A inscrição para a prova pode ser feita de duas formas, através do email apieroni@genexus.com (responsável da área comercial da Artech Brasil), ou então a partir de um centro de treinamento parceiro da Artech.

A partir deste contato inicial, você saberá quando é a próxima data marcada para ocorrerem as provas. Estas datas são determinadas pela Artech, por isso, não vá planejando e escolhendo uma data que deseje.. hehehe

Para confirmar a inscrição é necessário informar alguns dados como, nome completo, data de nascimento, endereço, CPF, empresa, usuário cadastrado no GxTechnical e horário de preferência, 09:00 ou 13:30.

Após isto, você irá receber um email com o boleto bancário a ser pago, no meu caso R$ 700,00 para analista sênior... este boleto tem que ser pago e até 3 dias úteis antes da realização da prova.

A Prova

A prova é realizada em algum centro de treinamento parceiro da artech. Esta prova é efetuada a partir do site GxTechnical, basta o usuário acessar este site, efetuar o login, e clicar no último link a esquerda do menu, "Exames".

Há um total de 36 questões, e para cada questão, uma alternativa correta. As questões serão:

  • 70% de múltipla escolha - 3, 4 ou 5 alternativas, a última será sempre a opção "nenhuma das alternativas";
  • 30% de Verdadeiro/Falso;

Você terá 180 minutos para realizar a prova, durante este tempo poderá avançar e retroceder as questões, revisar a prova de forma sucinta e confirmar o seu término. Após isto é pedido um usuário e senha da empresa que ministrou a certificação, para finalmente apresentar o resultado da certificação.

Na figura abaixo você pode conferir o layout do modo como a prova é apresentada. No seu topo, sempre irá aparecer o tempo que falta para a realização da prova, abaixo é apresentada a questão com o percentual  que compõe a prova. As questões mais difíceis valem de 5% a 6%, já as mais fáceis de 1% a 2%. Abaixo da questão são apresentadas as suas alternativas de respostas, e no rodapé os botões para avançar, retornar e efetuar revisão.

Genexus Certificação

Conteúdo cobrado

O conteúdo cobrado foi:

CONTEÚDONº DE QUESTÕES
Modelagem de transações segundo os relacionamentos 1-N, 1-1, N-13
Tabela base e estendida aplicado ao modelo de bachman, às transações e for each4
Desenho das tabelas a partir de transações1
Adicionar conteúdo a um SDT através de Data Provider2
Business Component - inserções, inserções de níveis e atualizações3
Data Provider2
Ordem de execução das regras3
Condições de fórmulas1
Subtipos2
GxServer1
Patterns1
UTL - unidade de trabalho lógica1
Definição de tabela base de uma Web Panel, através de atributos1
Web Panel Grid, evento load de um objeto com e sem tabela base2
Web Panel, condições de um grid1
Fórmulas Horizontais - expressões aritméticas1
Conhecimento de for each aninhado - break, join, produto cartesiano5
Procedure1
Execução de uma compilação - run, build all, rebuild all1

Uma recomendação, façam simulados, leiam a parte teórica disponibilizada no site Genexus Training,  e façam anotação, resumos desta teoria lida.

O tempo para a realização da prova é mais que o suficiente, não há por que se apressar. Tenham bastante paciência, mesmo que após uma hora e meia já estejam cansados. Peçam uma folha e um lápis para rascunho, vai ser muito útil. E imaginem que os enunciados são especificações de projetos, para resolvê-lo sem antes precisar olhar cada alternativa.

O simulado compartilhado pelo blog contém mais de 10 questões muito parecidas com o que foi cobrado, caso se interesse deixe seu email nos cometários, que envio sem nenhum problema.

Ah..por fim, consegui minha certificação com 87% de acertos, terminando a prova em cerca de 100 minutos. As vezes as questões mais simples se tornam as mais complicadas... hehehe, é isso pessoal, forte abraço

sexta-feira, 16 de novembro de 2012

Ordem de execução das Regras - Parte II

Vamos para a segunda e última parte desta "série"... Bom gurizada, conforme combinado no dia primeiro de novembro (post "Ordem de Execução das Regras - Parte I"), darei continuidade a este assunto. Como, diabos, esse tal de Genexus trata a execução de regras e fórmulas especificadas nas transações. 

Hoje iremos conhecer, ou então recordarmos, as regras com eventos de disparos definidos. 

Mas que eventos de disparos são estes? 

Em alguns casos, quando programamos as regras em nossa transação, precisamos adicionar um evento para controlar o momento em que esta regra será executada, e dessa forma, controlar para que o objeto aja da forma esperada. 

Os eventos de disparos são:
  1. BeforeValidate;
  2. AfterValidate - BeforeInsert - BeforeUpdate - BeforeDelete;
  3. AfterInsert - AfterUpdate - AfterDelete;
  4. AfterLevel;
  5. BeforeComplete;
  6. AfterComplete;
Podemos visualizar na nossa figura de apoio abaixo, em qual momento cada um se executa:

Genexus Rules

Este conhecimento é essencial ao analista genexus, e é um assunto que sempre cai nas provas de certificações, por isso, vamos tentar capturar esta lógica de ordenação!

BeforeValidate

Este evento ocorre um momento antes que a informação trabalhada (cabeçalho ou linha de um grid) seja validada. Este é um evento pouco utilizado, visto que as informações digitadas na form ainda não foram validadas. Podemos utilizar para chamar procedures passando como parâmetro os próprios parâmetros recebidos através da regra parm.

AfterValidate - BeforeInsert - BeforeUpdate - BeforeDelete

Este evento ocorre após a validação da informação trabalhada (cabeçalho ou linha de um grid) e, antes da inserção física dos dados. Isso mesmo, a inserção física dos dados no banco de dados, ocorre após este evento de disparo, e não no famoso commit

Efetuar um commit, significa que um conjunto de operações realizada na base de dados, foi finalizada com sucesso. E assim, se da por finalizada uma unidade de trabalho lógica (UTL).

Preste atenção, pois os eventos especificados abaixo são idênticos:
[Regra] if insert on AfterValidate = [Regra] on BeforeInsert;
[Regra] if update on AfterValidate = [Regra] on BeforeUpdate;
[Regra] if delete on AfterValidate = [Regra] on BeforeDelete;
Porém, se especificarmos somente o evento AfterValidate, a regra será executada em todas as ações anteriores, inserção, alteração e exclusão. Cuide isto.

AfterInsert - AfterUpdate - AfterDelete

Este evento ocorre após a inserção física da informação trabalhada (seja cabeçalho ou linha de um grid).
Lembre-se então, para setarmos valores a atributos através de regras, o último momento é a regra anterior (AfterValidate). Desta regra em diante, os dados já estarão gravados no nosso banco de dados.

AfterLevel

Este evento ocorrerá após o abandono do nível (grid) trabalhado e, após a gravação física da última linha deste grid. Caso a nossa transação só possuir um grid, este evento ocorrerá no mesmo instante do evento BeforeComplete. Caso a transação possuir 2 ou mais níveis, este evento ocorrerá no mesmo número de vezes.

Exemplo, caso precisamos obrigar o usuário a inserir no mínimo uma linha do Grid, especificaríamos:
Error("....") if Count(AtributoGrid) = 0 on AfterLevel Level AtributoGrid;

BeforeComplete

Este evento ocorrerá antes de se realizar o commit, isto é, terminar a UTL trabalhada. Como visto anteriormente, este evento coincidirá com o evento AfterLevel quando só existir um nível ou então, caso possua N níveis, com o último nível criado.

AfterComplete

Este evento ocorrerá após a realização do commit.

Exemplos de utilização

Em uma transação de Clientes, desejamos emitir um relatório dos dados dos clientes nos determinados momentos: ao inserir um registro; ao atualizar um registro; e ao excluir um registro,

Inserção de novo registro

Neste caso só podemos chamar o relatório após os dados da transação terem sido gravados fisicamente na tabela. Por isso, não poderíamos utilizar o evento BeforeInsert/AfterValidate, pois os dados estariam apenas validados. Logo nossa regra seria:
Relatório.Call(ClienteId) on AfterInsert;
Se utilizássemos a regra BeforeInsert, o Id do Cliente não estaria inserido no banco de dados e nosso relatório se apresentaria vazio.
  
Atualização de um registro  - relatório dos dados antigos, antes de serem alterados

Neste caso, desejamos que o relatório seja gerado antes da gravação física dos novos dados, ou seja, um log da situação anterior à mudança. Logo nossa regra seria:
Relatorio.Call(ClienteId) on BeforeUpdate; ou então
Relatorio.Call(ClienteId) if update on AfterValidate;
Se utilizássemos a regra AfterUpdate, os novos dados já estariam sido gravados fisicamente na tabela, sendo assim, impossível de capturar sua posição anterior.

Exclusão de um registro - dados do cliente excluído do sistema

Neste caso, desejamos que o relatório seja gerado antes da exclusão ter sido realizada na tabela, para desta forma, podermos capturar todas as informações do cliente a ser excluído. Logo nossa regra seria:
Relatorio.Call(ClienteId) on BeforeDelete; ou então
Relatorio.Call(ClienteId) if delete on AfterValidate;
Caso utilizássemos a regra AfterDelete, a exclusão física já haveria sido realizada, e não existiria mais as informações sobre nosso pobre cliente.
-----------------------------------------------------------------------------------------------
Exercícios

Verdadeiro ou falso, algumas regras estão mal programadas?
FaturaData = &today on AfterInsert;
Incorreto: o último momento de assinalarmos algum valor para os atributos é o evento AfterValidate/BeforeInsert/BeforeUpdate.

Procedure.Call(FaturaData) on AfterInsert;
Correto: os dados já foram inseridos fisicamente na tabela, por isso, caso o restante da transação não apresente erro, o comando irá se executar com sucesso.

sexta-feira, 9 de novembro de 2012

Efeito Jquery em uma WebPanel - Genexus

Bom pessoal, vamos a mais um post a respeito de jquery. Esta biblioteca que tanto tem crescido no desenvolvimento de aplicações web, acredito que, por permitir trabalhar com javascript de uma forma muito fácil e prazerosa. Os efeitos abrangentes são fantásticos, muitas vezes quando achamos que um site foi programado em flash, por permitir interações através da movimentação do mouse, vamos mais a fundo, visualizamos seu código fonte, e eis que esse efeito é nada mais que um plugin desenvolvido em jquery.

Hoje vou mostrar o desenvolvimento de um efeito de slide a uma camada de Filtro, que tanto utilizamos nos nossos Patterns. Neste caso, a camada de Filtro se iniciará Invisível para o usuário, porém com a possibilidade de expandi-la através de um TextBlock.

Ao tentar realizar este exemplo me deparei com alguns bugs tanto do Internet Explorer (quase extinto, finalmente) quanto do próprio Genexus. O IE não trata o slideToggle (função jquery), da mesma forma que os outros browsers, ao realizarmos o efeito ele parece piscar, cada vez que é executado. Já no Genexus, a função slide parece não respeitar as tabelas, textblocks, variáveis presentes na tela.

Porém com um pouco de pesquisa cheguei a uma solução, para realizarmos o efeito da forma desejada precisaremos executar três funções do jquery, são:


slideToggle()
hide() - show()


------------------------------------------------------------------------------------------------------------

Vamos lá então, em uma Web Panel crie a seguinte estrutura de tabelas em "Form":

Genexus Web Panel

Legenda:
      Vermelho: Tabela principal (2 Row/1Column)
      Verde: Tabela - ControlName: Table_Slide (Height:50px, Width: 100%)
      Azul: Tabela - ControlName: Table_Filtro (Height:20px)
      "Expandir": TextBlock - ControlName: TB_Expand

Em Eventos:
Event Start
//=====Adiciona estilos - css às tabelas "filtro" e "slide"=====
Form.HeaderRawHTML = '<style>'
Form.HeaderRawHTML += '#TABLE_FILTRO{display:none;} #TABLE_SLIDE{display:none;}'
Form.HeaderRawHTML += '</style>'

//=====Adiciona biblioteca jquery - mais recente=====
Form.HeaderRawHTML += '<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>'

//=====Inclui função de slide=====
Form.HeaderRawHTML += '<script type="text/javascript">'
Form.HeaderRawHTML += '$(function() {'

//=====Ao clicar sobre o TextBlock TB_Expand - "Expandir"=====
Form.HeaderRawHTML += '$("#TB_EXPAND").click(function() {'

//=====Se a Tabela Filtro estiver invisível=====
Form.HeaderRawHTML += 'if($("#TABLE_FILTRO").css("display") == "none"){'

//=====Tabela Slide - aparece através de slide=====
Form.HeaderRawHTML += '$("#TABLE_SLIDE").slideToggle(400, function() {'

//=====Tabela Filtro se torna visível=====
Form.HeaderRawHTML += '$("#TABLE_FILTRO").show(300);});'

//=====Se a Tabela Filtro estiver visível=====
Form.HeaderRawHTML += '}else{'

//=====Tabela Filtro se torna invisível=====
Form.HeaderRawHTML += '$("#TABLE_FILTRO").hide(300, function() {'

//=====Tabela Slide - some através de slide=====
Form.HeaderRawHTML += '$("#TABLE_SLIDE").slideToggle(400);})}});'
Form.HeaderRawHTML += '});' 
Form.HeaderRawHTML += '</script>' 
EndEvent

Event TB_Expand.ClickEndEvent
Por fim, teremos uma tela semelhante a esta abaixo, onde ao clicar sobre o TextBlock "Expandir" a Tabela em Azul realiza um Slide up/down:

Genexus Web Panel

Genexus Web Panel

quinta-feira, 1 de novembro de 2012

Ordem de Execução das Regras - Parte I

Bom dia pessoal que tanto gosta de "fuçar" nesse tal de Genexus... Hoje vamos entender um pouco sobre como ou de qual maneira o Genexus realiza a execução de nossas regras, fórmulas e eventos programados, principalmente em nossas transações.

Esse papo é um pouco chato, mas se faz necessário entendermos de vez. Muitas vezes, quando possuímos aquela transação gigantesca, com diversas e diversas regras de controle, nós conseguimos a execução desejada dessas regras, com base na "sorte" ou na própria força de vontade. Mas por traz disso tudo existe aquela "mágica" da Artech.. bom vamos lá!!

Irei dividir este assunto em 2 partes, para não ficar tão corrido e confuso. Na figura abaixo podemos visualizar o momento de execução de cada regra e fórmula definida em uma transação. No post de hoje, irei exemplificar as duas primeiras: Regras Stand-Alone e a Execução de Regras e Fórmulas que NÃO possuem evento de disparo definido.

Genexus Regras


1º Regras Stand-Alone

As regras stand-alone são aquelas que podem se executar sem depender dos dados contidos na transação. Elas também podem se executar através dos parâmetros recebidos. Veja abaixo alguns exemplos:

Executadas a partir de parâmetros:
&Variavel = Parametro;
Msg("........") if Parametro = 2;
Execução de regras independentes:
msg("Bem vindo a transação X!");
&VariavelA = true;
2º Execução de Regras e Fórmulas sem evento de disparo definido

Os eventos de disparo são controles de execução de regras inseridas, tais como: AfterValidate, AfterInsert e AfterComplete.

Vamos considerar que geramos uma transação de Fatura, a esta transação incluímos 7 fórmulas, 3 horizontais (simples operações aritméticas), 4 aggregate (SUM, MAX, COUNT, etc..) e um controle de Erro:

1. Add(FaturaTotal, ConsumidorComprasTotais);
2. FaturaTotal = FaturaSubTotal - FaturaDesconto + FaturaEnvioValor;
3. FaturaDesconto = FaturaSubTotal * CategoriaDesconto;
4. FaturaEnvioValor = MAX(EnvioData,EnvioData<=FaturaData,,EnvioValor);
5. FaturaSubTotal = SUM(FaturaProdutoValor);
6. FaturaProdutoValor = ProdutoQuantidade*ProdutoPreco;
7. Subtract(ProdutoQuantidade, ProdutoEstoque)
8. Error("Estoque insuficiente") if ProdutoEstoque < 0;

Importante: a ordem de programação de fórmulas e regras não define a ordem de execução destas, quando não estão condicionadas a algum evento, por exemplo AfterValidate. Caso duas regras estejam condicionados ao mesmo evento a ordem de programação irá definir a sua execução.

No momento de gerar o programa, o Genexus irá verificar as dependências de cada uma destas fórmulas e atributos, e assim, definir a ordem correta de execução. Caso o valor de um atributo seja alterado, todas as regras que dependam deste atributo (assim como regras dependentes de regras de dependam deste atributo...) irão ser executadas.

Dessa forma, a primeira regra adiciona o valor total da fatura (FaturaTotal) ao histórico de compras do cliente (ConsumidorComprasTotais). Logo esta regra é dependente do valor contido em FaturaTotal. Já o valor de FaturaTotal é dependente de 3 outros valores, e assim em diante. Uma forma bem fácil de visualizarmos isso, é escrever um atributo destes em uma folha e, abaixo deste, escrever os atributos dependentes, e acima, os valores que dependam deste atributo.

O nosso exemplo ficaria da seguinte maneira:

Genexus Rule