segunda-feira, 22 de abril de 2013

Business Component com Transação de Dois Níveis

Acho que vou insistir mais um pouco nesse tema, me desculpem os já convencidos, mas creio que Business Component é bom demais para não ser utilizado, e infelizmente o que tenho percebido é que ainda tem muita gente que insiste em utilizar as procedures para operar as tabelas geradas pelo Gx, quer por falta de conhecimento ou mesmo receio ante a tanta mudança conceitual, então, para tentar convencê-lo, nada melhor que ampliar um pouco o conceito dos posts anteriores, com algo, diria, mais substancial.

O tema fundamental aqui é o seguinte: E se eu tiver uma transação de dois ou mais níveis, como encaixo o Business Component?

O GeneXus tem evoluído também na questão que se refere (parece a Dilma!, rs...)  à sua linguagem de programação, e em alguns pontos está claramente mais 'orientado à objetos', pois na sintaxe dos BC´s existem propriedades e métodos que claramente remetem à esse novo modelo.  O lado negativo é que esse modelo, implica em maior dificuldade para aqueles que não estão acostumados com esse estilo. Então, acredito que a melhor maneira de explicar é simplesmente esquecendo-se de toda teoria envolvida e partindo para um lado mais prático da coisa.

Portanto, o que buscaremos é montar um modelo que possa ser reproduzido nas diversas situações, e sem muita teoria, e as transações escolhidas são os já tão explorados NotaFiscal, Cliente e Produto, mais especificamente a NotaFiscal que possui dois níveis.



Essa transação, como você já sabe, gera duas tabelas distintas, conectadas porque no segundo nível da transação temos o atributo NotaFiscalId, que fica meio 'oculto' na estrutura.


Portanto qualquer operação de inserção ou atualização de registros se deve levar em conta que temos duas tabelas, e era isso que tínhamos que programar no modelo, diria, 'mais tradicional' do Genexus.  Sendo ainda que primeiro tinhamos que criar o registro em NotaFiscal para em seguida operar a tabela NotaFiscalProduto. Então, se fossemos inserir um registro nas duas tabelas teriamos que programar algo como:

 new
    NotaFiscalData  = &Today
    ClienteId  = &ClienteId
 endnewZ

 for each // (autonumber)
    &NotaFiscalId   = NotaFiscalId
 endfor

 new
    NotaFiscalId         = &NotaFiscalId
    ProdutoId            = &ProdutoId
    NotaFiscalProdutoQtd = &NotaFiscalProdutoQtd
 endnew


Essa foi apenas uma forma simplificada de tratar a situação, cuidado não é segura, pois o for each incluído para pegar o último registro inserido, devido à caracteristica do autonumber no atributo NotaFiscalId, não é uma boa estratégia, pois teríamos problema se tivessemos um caso de concorrência de inclusão simultânea na base.  Mas por outro lado o exemplo explicita uma situação que vivemos no GeneXus tradicional que é a necessidade de incluir primeiro o registro em NotaFiscal para em seguida incluir alguma coisa em NotaFiscalProduto.

Business Component de Dois Níveis

No modelo aplicado aos Business Components, as duas tabelas são vistas como apenas uma, pois não é necessário separar as operações, da mesma forma que funciona no formulário da transação. O trecho de código abaixo realiza a mesma operação do modelo anterior, sem o problema da concorrência que citamos anteriormente.

&notafiscal.Load(&notafiscalId)
&notafiscal.NotaFiscalData = &Today
&notafiscal.ClienteId      = &ClienteId
&notafiscal.Produto.Item(1).ProdutoId = &ProdutoQtd
&notafiscal.Produto.Item(1).NotaFiscalProdutoQtd = &NotaFiscalProdutoQtd
&notafiscal.Save()
commit

 

Ou seja, só pela razão da inserção ocorrer apenas em uma única operação, já é melhor que o modelo anterior. Porém o modelo tem algumas coisas estranhas a primeira vista, como por exemplo, as duas linhas abaixo.

&notafiscal.Produto.Item(1).ProdutoId
&notafiscal.Produto.Item(1).NotaFiscalProdutoQtd


Referindo-se à estrutura da Transação temos a equivalência dos elementos da seguinte forma, Produto é o subnível da transação e NotaFiscalProdutoQtd e ProdutoId são atributos do segundo nível.


E o número entre parenteses Item(1), este equivale ao item a ser inserido na nota, 1, 2, 3, ....

'update' de um item


Este trecho de código pode ser utilizado para realizer o update de um item da nota fiscal.

&notafiscal.Load(&notafiscalId)
&notafiscal.Produto.Item(&item).ProdutoId = &NovoProdutoQtd
&notafiscal.Produto.Item(&item).NotaFiscalProdutoQtd = &NovoNotaFiscalProdutoQtd
&notafiscal.Save()
commit


'delete' um item


Para remover um item da nota fiscal poderíamos programar:

&notafiscal.Load(&notafiscalId)
&notafiscal.Produto.Remove(&itemaremover)

&notafiscal.Save()
commit


Percorrendo os itens

O exemplo a seguir é útil para percorrer a lista para realizar uma operação qualquer, como a  atualização dos dados. No caso, altera-se a quantidade de certo produto previamente inserido na nota fiscal. Para isso é necessário criar uma variável &item do tipo NotaFiscal.Produto. e com esta realizar uma operação for...in


&notafiscal.Load(&notafiscalId)
for &item in &notafiscal.Produto
   if &item.ProdutoId = &ProdutoId
      &item.NotaFiscalProdutoQtd = &NotaFiscalProdutoQtd
   endif
endfor
&notafiscal.Save()
commit


Observe que a atualização ocorre na variável &item, e ao realizar o save()commit, os dados são gravados na nota.



Chega por hoje,


Business component é um recurso indispensável, você não acha? Eu sim, e vou além, sem ele estamos perdendo tempo.  Mesmo que de vez em quando temos certos enroscos pra resolver, algumas mensagens estranhas, creio que deixar a transação cuidando da inserção, atualização e eliminação dos registros nas tabelas é um bom negócio.  Claro, que essa é apenas minha humilde opinião.

Tem mais exemplos em:

http://wiki.gxtechnical.com/commwiki/servlet/hwiki?Business+Component+Samples,