sexta-feira, 7 de dezembro de 2012

QR Code

Você sabia que o QrCode foi inventado pela Toyota? pois é, uma grande montadora japonesa necessitava de uma grande quantidade de informações em um espaço reduzido.  Aliás é assim que funciona o Japão: muita gente em um pequeno território. (peguei leve!)

QrCode é com certeza uma grande evolução na questão da geração de códigos de barras com alta capacidade de carga da informação, ou seja, que ultrapassam a necessidade de geração de simples números e códigos, pois o modelo trabalha em duas dimensões, ou seja, possui uma enorme capacidade de armazenamento (4Kb) e em um tamanho que pode ser significativamente reduzido, se comparado às fontes barcode tradicionais.

Esse é um recurso bem interessante para utilizarmos nos projetos GeneXus, e é o que faremos a seguir, com um pequeno projeto com o objetivo de armazenar informação num formato JSON em uma imagem QrCode.

SDT

O primeiro elemento que necessitamos para produzir um QrCode é informação, e o objeto Structured Data Type é um bom elemento para organizar e agrupar informações. A seguir apresentamos um pequeno exemplo de um SDT que armazena Código, Descrição, DataRecebimento e DataValidade de certo produto.
E em seguida podemos programar uma variável do tipo SDT, que armazene os diversos campos criados no SDT.

 &codigo.Codigo                = 1222333222
 &codigo.Descricao             = 'Mesa Executiva'
 &codigo.DataValidade          = #2020-10-02#
 &codigo.DataRecebimento       = #2012-10-02#

Gerando o QrCode
E em seguida um comando que chama um gerador de QrCodes da própria Artech, ou seja, aquele utilizado para gerar os QrCodes para instalação de aplicações Android e Blackberry no GeneXus Ev2. Observe que na chamada ao serviço já informamos qual o valor da imagem que o mesmo deverá produzir por meio do conteúdo em formato Texto.

&linkqr = link('http://sdx.genexus.com/agetqrcode.aspx', &codigo.ToJson())
&qrcode = loadbitmap(&linkqr)

A operação é realizada em duas etapas, a geração da imagem do QrCode por meio do agetqrcode e em seguida a carga dessa imagem em uma variável &qrcode do tipo Image.

As variáveis criadas nesse código são:



Resultado
Essa variável pode ser incluída em qualquer interface Web ou Report, produzindo um resultado semelhante a imagem apresentada a seguir.
Essa mesma imagem pode ser incluida em um PrintBlock de relatório produzindo o QrCode de forma impressa.
Interessante e simples, assim como a criatividade das pessoas que estão explorando essa imagem para produzir arte visua: http://mashable.com/2011/07/23/creative-qr-codes/

E para conhecer um pouco mais, ai vai a dica:





quarta-feira, 28 de novembro de 2012

Mistérios do .Net

Sabe quando você acha que sabe alguma coisa, e de repente, tudo, por alguma razão desconhecida começa a cair por água abaixo, aquela sensação de segurança que começa a esvair-se.  Pois é, nesse mundo da informática a coisa funciona dessa forma, de vez em quando, pelo menos pra mim. Tantos anos de Genexus e estudando detalhadamente seus melindres, e, subitamente o IIS 7.0, que estava funcionando perfeitamente bem, começa a apresentar um erro meio doidão.

O pior é que essas situações acontecem nos momentos mais críticos, onde você simplesmente não tem tempo a perder, como por exemplo, meia hora antes de uma palestra, já pensou no sufoco?

HTTP Error 500.19 - Internal Server Error

The requested page cannot be accessed because the related configuration data for the page is invalid.
Error Code: 0x8007000d  
 
E lógico, que antes da ficha cair de fato, o excesso de confiança nos leva a mexer aqui, ali, e aquilo que tava ruim vai ficando cada vez pior. Pois achava que o problema era o Pool de aplicação, versão do .Net, coisas de DLLs, que o pessoal do Tomcat não sofre efeito. Pesquisas na internet e ninguém dava a palavra definitiva a respeito do que estava acontecendo.  O erro persistindo, a Microsoft falava que o problema era o Web.Config mal formado, e só, se vira. E quando me vi estava apanhando feio no 10º round na luta com a Microsoft, IIS, Genexus, e por ai vai.
Acabei me lembrando que havia aplicado o pattern de Smartdevice em uma transação, e em outra ocasião o GAM. Pior que no outro note isso não estava acontecendo, então qual era o mistério?

Enfim em uma resposta muito despretenciosa em um post no Forum , o Pablo Mazzili deu uma pequena dica a respeito, que existia uma tal de URL Rewrite, seria isso? Poucas palavras e um link: http://www.iis.net/downloads/microsoft/url-rewrite.

Pior que a coisa funcionou!  Ao instalar o monstrinho, de repente tudo voltou a ser colorido.

URL-Rewrite
Este componente do IIS é no final das contas interessante, o efeito direto que ele causa no Genexus ainda não descobri totalmente, me parece que tem a ver com as chamadas REST da Ev2, mas no final das contas trouxe várias coisas interessantes na configuração do servidor, como certas regras de bloqueio e filtro de arquivos, reescrita de Urls ocultando o padrão de passagem de parametros, tornando-a mais facil.

Essa ultima, é bem interessante, pois nos dá uma série de possibilidades de aplicações, quem sabe eu conto uma, que estou fazendo, aqui no genexando. Mas imagine uma situação onde o usuário teria no seu browser algo como http://meusite.com.br/programa.aspx?id=10,valor=29 substituido por algo mais elegante como http://meusite.com.br/programa/10/29 (legal hein!)

Enfim, temos na documentação (meio fraquinha) da Microsoft um conjunto imenso de caracteristicas, providas por esse componente, que nem arrisco a falar mais nada, pois cabe aqui gastar umas horinhas para entender como a coisa funciona. Então, no melhor espirito colaborativo, segue alguns links que tratam da questão.

Para saber mais:
Assim que aprender um pouco mais a respeito disso te aviso!


segunda-feira, 8 de outubro de 2012

Erro com.genexus.reports.PDFReportItextSharp.GxDrawText

O IIS é famoso por apresentar mensagens indecifráveis, principalmente quando situações ocorrem de forma totalmente inesperada, sem uma explicação que parece plausível, como por exemplo um relatório que de repente não funciona mais.

Vamos a um exemplo:



Que fazer numa situação dessas onde a informação apresentada não traz nenhuma pista? A situação trata-se apenas da geração de um relatório PDF, que estava funcionando corretamente até então, e a mensagem não traz nenhuma informação útil.

Algo novo deve ter acontecido, a formatação do HD, a criação de uma nova KB, ou seja, se parar pra pensar verá que algo novo aconteceu na aplicação, que no meu caso foi a criação de um novo environment, portanto, trata-se de algo relacionado com a configuração desse novo ambiente.

A busca pela solução levou a várias ações:

  1. Se o erro estiver ocorrendo apenas em um relatório PDF, e nos demais a impressão está correta, então o problema não é devido a privilégios de gravação do documento na pasta Web.  Essa situação pode ocorrer, e para se corrigir voce deve designar privilégio de escrita para os usuários ASP, IUSR, Todos, ou seja, se a execução for local não precisa se preocupar com consequencias.
  2. Se o erro ocorre em um relatório especifico, então tem a ver com o conteúdo do próprio relatório em questão.  Nesse caso deve-se recorrer a uma leitura do PDFREPORT.INI, e verificar no próprio se existe algum conteúdo que é diferente dos relatórios que funcionam. Em meu caso havia a configuração para uma fonte 3 of 9 (barcode).
A solução foi observada verificando-se a referencia ao endereço da fonte, Fonts Location (MS), que se removido fazia com que o relatório voltasse a funcionar, mas sem a impressão do código de barras, portanto, esse era o problema!
 
[Fonts Location (MS)]
3 of 9 Barcode= C:\Windows\Fonts\3OF9.TTF
 
[Embeed Fonts]
3 of 9 Barcode= true

O que ocorreu é que estava utilizando um PDFReport.INI de outra máquina que não refletia o caminho correto da fonte.

Portanto, a conclusão não pode ser classificada de simples, porque numa situação em que temos nada para se chegar a uma conclusão não é uma coisa simples de se fazer, mas é lógica e nesse assunto todos somos craques, não? Boa depuração!



segunda-feira, 17 de setembro de 2012

Acentuacao ou Acentuação, eis a questão? ou questao?


Pois é nossa língua portuguesa continua riquíssima, e apesar de todos os esforços para torná-la mais simples, ainda temos que estudá-la por longos anos, para que no final, ainda cometermos muitos erros gramaticais. Tem gente que passa a vida estudando-a, e em profundidade seus advérbios, particípios, pleonasmos, e vamos parar por aqui, pois me lembrei da Dona Cristina, minha querida professora.  Isso sem contar os 'idiomas' regionais que também nos ajudam, como por exemplo: o piá da prenda gostar de comer macaxeira, ou ainda assei o vazio na herdade para comer com a fuleragem.

De fato trata-se de um dos nossos maiores patrimônios, mas quem não se sente tentado a passar o texto pelo corretor do MS-Word para descobrir aqueles acentinhos faltantes, antes de cometer a gafe de publicar algo errado.  Mesmo com todo esse esforço ainda cometo essas gafes com grande frequência aqui no Genexando, mas fazer o que, os que não tiverem pecados que atirem a primeira caneta.

Mas voltemos ao nosso problema original que é acentuação, usá-la ou não, e o grande esforço que tal detalhe ocasiona na questão das pesquisas no banco de dados, pois, agora mesmo no search do Genexando tive que escrever frases acentuadas e sem acento para tentar encontrar um artigo mais antigo, e que inclusive não achei.

O que fazer?
Em primeiro lugar temos os campos de entrada sujeitos a serem utilizados como filtros, podem representar um problema, pois muitos Joãos registram seus nomes como Joaos, e a falta de padrão traz consigo grandes dificuldades para achá-los depois.

Recentemente passamos por uma dificuldade dessas, e resolvemos duplicar um certo atributo na tabela removendo seus acentos de forma a possibilitar pesquisas por esse campo de forma mais 'neutra'.

E desta forma um pequeno trecho de codigo foi criado, com a ajuda do ReplaceRegEx para remover os caracteres com acentuação.

&TXT   = &Texto.ReplaceRegEx("[áàâãäª]","a")
&TXT   = &TXT.ReplaceRegEx("[éèêë]", "e")
&TXT   = &TXT.ReplaceRegEx("[íìîï]", "i")
&TXT   = &TXT.ReplaceRegEx("[óòôõöº]","o")
&TXT   = &TXT.ReplaceRegEx("[úùûü]", "u")
&resposta  = &TXT.ReplaceRegEx("[ç]", "c")

Acho que não preciso nem explicar o que ele faz né, (não é)?

O dia que o banco de dados falar português talvez não tenhamos que recorrer a esses métodos brasileiros.

Conclusão
Só pra abrir um pequeno parenteses, o Brasil, de fato é uma terra diferenciada, além da nossa lingua temos também os nossos próprios padrões que nos diferenciam do 'resto' do mundo, e só pra citar alguns exemplos vejam o nosso mais recente padrão 4G que somente funcionará aqui, e não adianta querer utilizar aquele iPhone 5 pois não vai funcionar, a própria Apple ficou meio revoltada com o Brasil, acho que por causa disso, o nosso sistema de TV digital que também só funciona aqui, as nossas belas e novas tomadas que também somente funcionam aqui e que por sinal exigem um montão de adaptadores, e por ai vai.

Direitos autorais a parte, fiquemos felizes com nossos irmãos de lingua portuguesa no mundo: Angola, Moçambique, Cabo Verde, Guiné-Bissau, São Tomé e Principe, Ilha da Madeira, Arquipélago dos Açores, e claro nossos patrícios, pois, pois.  Ah, já estava me esquecendo, tem também os que falam mas não oficialmente: Macau, Goa e Timor Leste. Percebeu que quase todos tem acento até no nome!


sábado, 15 de setembro de 2012

GeneXus Xev2 Integrado ao IIS7

O fato é que você vem utilizando suas aplicações Ev1 e Ev2 no IIS  já faz tempo, e talvez não tenha notado uma pequena mudança de comportamento. A boa noticia, é que o Genexus Ev2 opera agora de forma totalmente integrada ao IIS7 no modo Managed Pipeline Mode = Integrated.

Discutimos as restrições que tinhamos na execução de aplicações completamente integradas ao IIS no post (http://www.genexando.com/2011/01/migrando-aplicacoes-para-o-iis70.html), e esta deficiência foi corrigida no Genexus Ev2..

Até o Ev1 o que tinhamos era apenas o modo Classic, ou seja, o Asp.Net rodava em modo compatibilidade com o IIS6.  Atualmente ao criar uma aplicação .Net o padrão é associar o diretório virtual ao Default App Pool que já opera com o modo Integrated, portanto, compativel com as aplicações Ev2.
 
Para Saber mais:

quinta-feira, 6 de setembro de 2012

Como não render-se ao Submit

Submit traduzido para o português significa submeter, submeter-se, ceder, sujeitar-se, render-se, entregar-se, e não poderia haver sinônimos mais claros e eficientes para representar esse interessante comando Genexus, pois de fato não existe aplicação que possa ceder a esse recurso.

Trata-se de um mecanismo bastante antigo na ferramenta, lá pelos idos da versão 7.0, RPG/AS400, ou seja, a turminha mais madura com certeza conhece e utiliza esse recurso, já os bebezinhos (me incluo aqui, rs), nem imaginavam que algo tão surpreendente pudesse estar tão próximo ao nosso alcance.

Chega de suspense, então, pra que serve isso mesmo?

1) Situação 1: Com certeza em sua aplicação você necessita enviar algum email, ou vários, e deve ter programado um botão, que ao pressionado com certeza faz com que seu usuário espere por alguns instantes (indeterminado diga-se de passagem), até que ocorra a conexão com o servidor SMTP, em seguida o login, o envio da mensagem, finalmente o encerramento da sessão.  Algo como uma tela cinza e uma imagem de um circulo que fica animadamente circulando, meio sem significado se pararmos para pensar, mas que nos instiga a contar o tempo que estamos perdendo, e com certeza testando a nossa paciência e principalmente a do usuário.

2) Situação 2: Levou um certo tempo pra programar, tendo em vista que foram incluídos muitos dados estatísticos importantes, vários cálculos, agrupamento de informações, ou seja, um relatório que, em algumas situações, podem levar minutos para ser concluído.  Já ouvi falar de relatório de 3 horas, mas sinceramente, nunca enfrentei um monstro desses. E novamente, um botão que chama esse relatório, e novamente a tela cinza retorna feliz para nos brindar com o circulozinho alegre. Nesse momento lá vai o nosso usuário cortar as unhas, algumas mais afoitas iniciam uma animada rodinha pra falar dos novos sapatos, do namorado da vizinha, do Palmeiras que ta uma lástima, e por ai vai.

O culpado! Call e Udp, que são métodos de chamada que são os vilões da interrupção do fluxo de processamento, que faz chamadas de forma que o objeto chamador tenha que aguardar até o retorno do processamento.

Submit
Segundo a própria documentação, até a versão do Gx7.0, esse comando executava chamadas a processos AS400 de forma síncrona, a partir da 7.5 passou a ser disponibilizado para Web para executar processos assíncronos, ou seja, processos executados de forma paralela.

Em outras palavras, o comando permite gerar um novo processo em execução no servidor, de forma paralela ao atual, e o melhor é que o atual não aguarda o retorno da execução do processo em paralelo. O que resolveria de forma elegante nossas duas situações, ou seja, dispararíamos o processo para enviar o email ou gerar o relatório e o usuário ficaria confortavelmente na tela de seu sistema, continuando sua operação normalmente.

Claro que isso exigiria um pouco de Engenharia para informar ao usuário que seu relatório foi gerado, que o email foi enviado, mas isso é tema para outra história interessante.

Na Sintaxe o Segredo
Sinistro isso, pois o submit exige uma sintaxe meio esquisita, mas tem explicação.  Em seguida ao nome do processo a ser disparado segue-se um '' cujo significado seria a passagem de parâmetros de segurança (usuário/senha), mas que na chamada a uma procedure não teria funcionalidade.

 
      1) submit('sendmail','',&email)

      2) sendmail.submit('',&email)

O submit aceita parâmetros assim como quaisquer chamada Call ou Udp.

Quanto à procedure, apesar da documentação exigir um Main Program e o protocolo de chamada  do tipo Command Line, em meus testes no EV2, .Net, Web, não houve necessidade de nada disso.  Qualquer procedure funciona. Em um WebPanel ocorre a chamada ao objeto mas na mesma janela que a atual, portanto, não causa muito efeito.

Conclusão
Na minha humilde visão (miope) acredito que esse recurso seja uma excelente solução para reduzir o impacto de processos lentos na interface do usuário, pois permite a possibildade de execução em paralelo.  No caso do email cheguei a criar uma kb de gerenciamento de envio de emails, chamada com webservices para resolver o problema da espera, ficou muito interessante, gerenciável, mas analisando bem, uma palavrinha só seria necessária para acabar com o problema: submit. E não é isso que buscamos? simplicidade?


Para saber mais:
• http://www.gxtechnical.com/gxdl/pub/genexus/devenv/docum/releasenotes/7.5/submit.htm
• http://wiki.gxtechnical.com/commwiki/servlet/hwiki?Submit+Command,

terça-feira, 21 de agosto de 2012

FCkEditor

Um controle muito interessante disponibilizado pelo Genexus é o CkEditor (ou FCkEditor), que pode ser aplicado sobre atributos ou variáveis do tipo texto, caso se seleciona a propriedade Control Type como FCK Html Editor.

Salvo os problemas relacionados com segurança envolvidas na inclusão de codigo Javascript (leia as recomendações da OWASP - https://www.owasp.org), o controle, se utilizado com juizo pode produzir grandes beneficios para o usuário. Pois permite que o mesmo gere um texto vinculado com atributos visuais, escritos na linguagem HTML.  Olha que já vi sistemas jurássicos por ai que exigia que o singelo usuário escrevesse o texto na linguagem HTML.

Melhor ainda é poder otimizar o aspecto do editor, que é muito bem documentado no site http://docs.cksource.com/, e um dos aspectos mais interessantes é o ajuste do Toolbar, removendo-se incluindo-se novos controles. A imagem abaixo é resultado dessa configuração, com uma barra que eliminou controles desnecessários e perigosos.


Esse POST é um desejo antigo de explorar essa capacidade e de quebra te passar os caminhos das pedras para criar seu próprio Toolbar.


  1. Inclua uma variável Varchar(1M) na interface e em seguida mude sua propriedade para FCK Html Editor.
  2. Na propriedade do FCKEditor programe as propriedades Toolbar=Custom e
    CustomToolbar=MyToolbar, conforme indicado a seguir.

  3. Aqui vem a parte mais complexa, pois voce deve localizar no diretório Web\CKEditor um arquivo chamado config.js
  4. Para finalizar inclua nesse arquivo o código apresentado em Negrito (abaixo)
 /*
Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or
http://ckeditor.com/license
*/
CKEDITOR.editorConfig = function( config )
{
 config.toolbar = 'MyToolbar';

 config.toolbar_MyToolbar =
 [
  { name: 'clipboard', items : [ 'Cut','Copy','Paste','PasteText','PasteFromWord','-','Undo','Redo' ] },
  { name: 'editing', items : [ 'Find','Replace','-','SelectAll','-','Scayt' ] },
  { name: 'insert', items : [ 'Image','Table','HorizontalRule','Smiley','SpecialChar','PageBreak' ] },
                '/',
  { name: 'styles', items : [ 'Styles','Format' ] },
  { name: 'basicstyles', items : [ 'Bold','Italic','Strike','-','RemoveFormat' ] },
  { name: 'paragraph', items : [ 'NumberedList','BulletedList','-','Outdent','Indent','-','Blockquote' ] },
  { name: 'links', items : [ 'Link','Unlink','Anchor' ] },
  { name: 'tools', items : [ 'Maximize' ] }
 ];

};

Ao executar o WebPanel, o controle ficará configurado conforme os comandos incluídos nessa Toolbar. Interessante e simples.  E em caso de não ver a mudança imediatamente, não entre em desespero, de um F5 ou Refresh no navegador, que o bixo deve aparecer direito.




quinta-feira, 9 de agosto de 2012

Invite Message

O Genexus Evolution 2 realmente traz belas surpresas quando começamos a usar seus recursos. Um deles, muito simples, mas de grande valia, é a propriedade Invite Message, que não requer muito esforço para uma postagem mais elaborada, isso a menos que você queira simular algo semelhante.

Invite Message não precisa nem de explicação, veja a imagem ao lado e você entenderá seu propósito. Isso mesmo, ao abrir o formulário, a propriedade define um valor de orientação ou de ajuda no próprio controle, que no inicio da digitação do usuário, é substituída pelo valor definido pelo usuário.

Evolution 1?

Ainda no Genexus Evolution 1, então ai meu filho você tem duas opções: chupar o dedo ou meter a mão na massa e programar a coisa na unha, que pode ser feito com Javascript ou mesmo em Genexus utilizando o Notify Context Change. Quer fazer isso?

1)  Defina no Start os títulos que deseja apresentar, no próprio controle

Event Start
     &PessoaNome = 'Forneça o nome...'
EndEvent

2) Programa o evento TrackContext que intercepta o inicio da digitação e apaga o conteúdo para que o usuário possa colocar seu próprio conteúdo.

Event TrackContext(&PessoaNome)
     if &PessoaNome = 'Forneça o nome...'
          &PessoaNome =''
     endif
EndEvent


Só isso também.

sábado, 2 de junho de 2012

Þessi er dýrið jafnvel Google! a forvitinn og þú! mun standa nef þeirra á röngum stað ha

O Genexando agora tem a tradução Google automatica disponível para os posts, assim nossos amigos que falam gales, catalão, gurajatis, suati, tagalo, tâmil, telugo, urgo e yiddish, entre muitas outras, poderão se deliciar nos posts, :)

Fala sério, essa turminha do Google não estão para brincadeira!

Ps. Descubra o que está escrito no titulo e ganhe seu dia!!

quinta-feira, 31 de maio de 2012

=.+

Calma, não se trata de nenhum palavrão, na verdade é uma frase muito útil. Quem me ensinou isso foi o Daniel Krueger, e veja como ele é um poliglota!!  Sabe do que se trata?

Pois é, de um assunto muito interessante, mas tal qual o Mandarin, tem lá suas dificuldades.  Trata-se de uma expressão regular cujo propósito é remover o indesejavel   = /* Algum comentario */ que é inserido automaticamente pelo Genexus ao se arrastar um SDT para um Data Provider.

Ao arrastar um SDT para um objeto Data Provider o Genexus inclui, além da estrutura com seus elementos propriamente ditos, um sinal de = e um espaço para comentários, para que se realize a atribuição do valor ao elemento e claro, se inclua uma descrição da operação.


O problema é que sabemos que um elemento do SDT que tenha o mesmo nome de um atributo não necessita da atribuição, portanto, o sinal de igual seria totalmente dispensável na maioria das situações.  Portanto, NotaFiscalId = NotaFiscalId, poderia ser simplesmente registrado no DataProvider como NotaFiscalId, visto que trata-se de um atributo da tabela. Desta forma, o que seria um facilitado torna-se um pequeno problema de edição.

Ai é que entra o Daniel com sua invenção! Uma expressão regular que limpa além da atribuição o próprio comentário automático. Para que funcione abra uma janela de Replace, defina o Find What como =.+ e marque a opção Use: Regular Expression.


Resultado? O data provider limpo e claro.


Para os interessados em aulas de Mandarin recomendamos:



sexta-feira, 25 de maio de 2012

Quero vender! Quer comprar?


Recentemente assisti uma série americana muito interessante onde as principais capitais do país foram destruidas por terroristas e algumas pequenas cidades começaram a se reerguer após a crise, a luta consistia em redefinir os elementos essenciais para a sobrevivência em comunidade: (1) o reestabelecimento da politica (liderança forte para conter os mais exaltados), (2) da segurança (armada para evitar o roubo e saques entre as cidades sobreviventes) e finalmente (3) o comércio, este último foi bastante interessante porque com o fim do valor da moeda impressa as pessoas trocavam coisas, o chamado escambo. Então deixando a politica de lado nesses tempos de muitas Cachoeiras, vamos tratar de um assunto que acredito ser do interesse de todos, vender! e não precisa esperar o fim do mundo para isso.

A internet é o canal necessário para se vender coisas, e além de bons produtos, precisamos também de recursos que facilitem a compra das pessoas, GeneXus permite o desenvolvimento de interfaces bem interessantes para fazer isso, e aqui vai minha pequena contribuição para seu sucesso comercial, um carrinho de compras.  Vou tentar fazer isso o mais simples possível, mas com recursos muito avançados como Drag&Drop, Websessions, Blob's, e por ai vai.

Planejando o Carrinho
Um sistema de compras deve possuir alguns itens essenciais:
  1. Uma lista de produtos
  2. Uma cesta de compras onde a pessoa coloca os produtos desejados
  3. Uma lista de compras para que a pessoa possa incluir ou remover itens
  4. A finalização da compra com o pagamento, ..., mas isso deixemos para outra ocasião
Lista de Produtos

Uma simples transação de Produtos é suficiente para simular uma lista de produtos, se tiver uma (ou mais) fotos, também é um bom recurso para se vender.



Precisamos também de um painel para o cliente realizar a operação de escolha dos produtos que deseja, e um detalhe que podemos incluir nessa lista é a possibilidade de executar operações Drag&Drop (já explorada aqui no POST: http://www.genexando.com/2011/01/drag-drops.html)


E também um botão para realizar a compra, caso não seja possível realizar o Drag.

Finalmente, ao pressionar a cesta de compras, uma interface para finalizar a compra, no qual o cliente pode determinar a quantidade de produtos, e também realizar o login no sistema, para que a compra seja finalizada. Algo similar a imagem apresentada a seguir.

Cesta de Compras
Uma cesta de compras pode ser representada por uma imagem com aparência de cesta, ou mesmo por botões que executem a operação de incluir um item na lista.  As duas opções sáo importantes, para reforçar o conceito das paginas Drag & Drop, vamos implementar o recurso com uma imagem, e também um botão, caso esta não esteja visivel.

Utilizamos uma imagem para representar a cesta (ver acima), cujo nome ficou o padrão (Image1), e programamos o evento Drop no seguinte modelo.

Event Image1.Drop(&ProdutoId, &ProdutoPrecoValor)
    do 'comprar'
EndEvent

As variáveis &ProdutoId e &ProdutoPrecoValor devem ambas estarem no grid de produtos, e serão transportadas no evento Drag para a imagem do carrinho.  Portanto no grid de produtos é necessário marcar a opção Allow Drag = true, e carregar essas variáveis com valores.

O botão Comprar que aparece na interface pode executar a mesma subrotina 'comprar' que estaremos programando logo a seguir.

Event 'Comprar'
    do 'comprar'
EndEvent

A Operação de Compra

A operação de compra consiste em incluir o item selecionado a uma lista de produtos. O diferencial aqui foi que criamos um SDT para armazenar a coleção de itens comprados.

Bem simples, com três itens, o código do produto, a quantidade e o valor unitário.

A operação de compra então acrescenta na coleção ListaCompras um item, com uma operação Add.

    &Item = new()
    &Item.ProdutoId         = &ProdutoId
    &Item.ProdutoValor      = &ProdutoPrecoValor
    &Item.ProdutoQuantidade = 1
    &ListaCompras.Add(&Item)
   
O esquema interessante desse exemplo,  é onde escolhemos armazenar essa lista, que poderia ser em uma tabela num formato mais tradicional, mas optamos por guardar essa lista na própria sessão web criada para o usuário.
    &websession.Set("CARRINHO", &ListaCompras.ToXml() )   
Somente devemos transformá-la em texto para que possa ser armazenada, tendo em vista que variáveis de sessão somente são do tipo String.

Desta forma, toda vez que necessitamos acrescentar um item na lista devemos lê-la da websession, acrescentar o item e salvá-la novamente. A operação abaixo realiza a leitura da lista de compras na sessão e a converte novamente em uma coleção na memória.

    &ListaCompras.FromXMl(&websession.Get("CARRINHO"))
Portanto nossa operação de compra completa ficou assim.

Sub  'comprar'
    &ListaCompras.FromXMl(&websession.Get("CARRINHO")) 
    &Item = new()
    &Item.ProdutoId         = &ProdutoId
    &Item.ProdutoValor      = &ProdutoPrecoValor
    &Item.ProdutoQuantidade = 1
    &ListaCompras.Add(&Item)
   
    total.Caption = &ListaCompras.Count.ToString()+' itens'
    &websession.Set("CARRINHO", &ListaCompras.ToXml() )   
EndSub

Muito interessante isso hein!

Carregando a Lista de Produtos
Agora fica mais simples entender o funcionamento do Grid de produtos, que inicialmente faz a leitura da lista na sessão web, no evento Refresh.

Event Refresh
    &ListaCompras.FromXMl(&websession.Get("CARRINHO"))
    total.Caption = &ListaCompras.Count.ToString()+' itens'   
EndEvent
E em seguida, para cada produto, obtém seu preço, e o apresenta na interface. Uma observação apenas, para dar um ar de requinte ao processo, fizemos uma operação que somente apresenta os itens que ainda não foram comprados na lista, ou seja, comprou some da lista.  Isso é o que está implementado através da variável &flag.

Event Load
    for each
        &ProdutoPrecoValor=ProdutoPrecoValor
    endfor
    &flag=0
    for &item in &ListaCompras
        if &Item.ProdutoId=ProdutoId
            &flag=1
        endif
    endfor   
    if &flag =0
        &ProdutoId = ProdutoId
        load
    endif
EndEvent

Claro que você vai ser inteligente e tratar a questão do preço de forma mais profissional, lembre-se que aqui o objetivo é ser didático e não preciso.

Finalizando a Compra
Muito simples também, um click sobre a imagem da cesta de compras, chama o painel de finalização.

Event Image1.Click
    FinalizaCompra.Call()
EndEvent

Esse novo painel recupera a lista da sessão Web, e permite que o usuário determine a quantidade de itens comprados.  Programamos a carga no próprio Evento Load do Grid

Event Load
    &ListaCompras.FromXMl(&websession.Get("CARRINHO"))
    total.Caption = &ListaCompras.Count.ToString()+' itens'   
    for &item in &ListaCompras
        &ProdutoId             = &item.ProdutoId
        &ProdutoQuantidade     = &item.ProdutoQuantidade
        &ProdutoPrecoValor     = &item.ProdutoValor

        for each
            where ProdutoId     = &ProdutoId
            &ProdutoDescricao     = ProdutoDescricao
            &ProdutoFoto         = ProdutoFoto
        endfor

        &ProdutoPrecoTotal = &ProdutoQuantidade * &ProdutoPrecoValor
        &Total += &ProdutoPrecoTotal
        load
    endfor
EndEvent


Para tratar do login da pessoa no sistema antes da finalização, optamos por um webcomp que faz o tratamento do username e senha.

    // usuario ta logado?
    &UsuarioId = &websession.Get("USUARIO")
    if &UsuarioId.IsEmpty()
        WebComp1.Object = Login.Create()
    else
        WebComp1.Visible= 0
        // finaliza o pedido
        // inclui os produtos na nota fiscal   
        msg('finalizar o pedido do usuario '+&UsuarioId)
    endif


Esse código pode ser posicionado no evento Refresh do segundo painel.

O botão Finalizar nessa interface apenas mostra os produtos comprados, mas poderia muito bem continuar o processo de cobrança e em seguida emissão da nota fiscal eletrônica. Vou deixar essa parte para você.

Event 'Finalizar'
    for each line in Grid1
        msg('comprando'+&ProdutoDescricao)
    endfor
EndEvent

Conclusão

Esse exemplo eu sempre quis publicar no Genexando, mas sempre relutei devido à sua complexidade.  Acho que chegamos a um modelo bem simples e que possibilita a aprendizagem de muitas coisas interessantes como a manipulação de coleções, sessões web, além do recurso de Drag & Drop.

Espero que você faça um bom uso desse modelo, só peço uma coisa, por favor não desenvolva nenhum sistema de Compra de Votos para instalar nas assembléias, câmara de vereadores, prefeituras, governos, e por ai vai, hein...


(fonte: http://1ipbresplendor.blogspot.com.br/2010/08/igreja-e-compra-de-votos.html)
 

domingo, 29 de abril de 2012

Transação exposta como Web Service

Um dos recursos interessantes que podemos utilizar no Genexus são os webservices, que tem por finalidade permitir um mecanismo de comunicação entre duas aplicações distintas.  O processo mais comum de utilizar esse mecanismo é mediante o objeto Procedure, mas Gx também permite que Data Provider e Transação também sejam expostas desta forma.   Esse post tratará de desenvolver webservices de transações.

Por que WebService é interessante?
Um dos nossos maiores problemas é o avanço tecnológico, e por que isso gera problema? Os sistemas vão ficando obsoletos com o passar do tempo e aquela tecnologia que foi selecionada na época e foi tão eficaz durante certo tempo, deixa de ser suficiente para atender às novas demandas das pessoas e processos.  Por exemplo, um ótimo sistema programado lá atraz com dBase ou Clipper, atualmente não funciona em uma camada web ou mesmo smartdevice, simplesmente porque essas tecnologias morreram no meio do caminho, e muitas outras também como Visual FoxPro, Visual Basic, Cobol.  Algumas inclusive se adaptam melhor a evoluções, como Java que foi se adaptando com o passar do tempo, mas também essa está fadada há acabar um dia.

Então o que ocorre com essa proliferação imensa de sistemas obsoletos de distintas tecnologias rodando em uma empresa, sendo que muitos dos quais ainda operam de forma eficiente em seus processos. A resposta: ficam isolados em seus processos, ou mesmo, sofrem atualizações tecnológicas (são reprogramados).

Uma solução mais simples seriam interligar novos sistemas (mais tecnológicos) aos bancos de dados dos sistemas antigos (obsoletos) para se buscar uma conexão entre eles.  Esse mecanismo é provido por Data Views, que também é um método de conexão entre sistemas, mas com a desvantagem de que a base de dados deve estar disponível para acesso, não apenas read-only, por outros sistemas.

Uma solução mais inteligente seria interligar os novos sistemas aos sistemas obsoletos por meio de uma camada de comunicação, fazendo com que o sistema novo consuma uma informação do sistema antigo, sem o conhecer, ou seja, não interferem em suas regras de negócio, estrutura funcional, tabelas, campos, ou seja, apenas solicita uma informação e o sistema antigo a devolve para ser processada no sistema novo.  Esse mecanismo é chamado de Web Service e essa funcionalidade é apenas uma visão simples de sua utilidade.

Transação como WebService
Então imagine estar em um sistema de Faturamento e ter acesso a um formulário do sistema de Custos, mas sem acessar diretamente as tabelas do sistema de Custos. Desta forma poder-se-ia ajustar certos valores (controlados) no sistema de Custos na interface do sistema de Faturamento.  Interessante hein?

Esse recurso é interessante porque normalmente consideramos webservices não diretamente sob o ponto de vista de interfaces para usuários, mas procedures e mecanismos que rodam de forma oculta dos usuários.

Considerando que já temos à nossa disposição um objeto que já realiza insert, update e delete, que é a transação, é sobre ele que trabalharemos. E no melhor estilo GeneXus o que precisamos apenas é definir uma propriedade na Transação: Export as WebService.  Isso possibilita que um Business Component (Transação marcada como BC), possa ser acessado por qualquer usuário de outro sistema, bom, não se esqueça de integrar nisso tudo um mecanismo de segurança.

Exemplinho
Então vamos a um exemplo simples, imagine uma transação de Pais que se encontra em uma determinada Kb qualquer, que definimos com um papel de produtor de informação, ou seja, tem a funcionalidade de criar países em sua própria Kb e também permitirá o acesso remoto desta operação em outras kb´s.



Sem muita complicação na estrutura, mas que foi marcada como Business Component e com a propriedade Expose as WebService=True.


Ao executar essa aplicação, o objeto Pais_BC passa a ser acessível no browser como um arquivo WSDL.  Ou seja, responde a uma chamada web service.
 
Desta forma, podemos em um sistema consumidor, definir certa interface para acessar esse objeto para realizar operações, como falamos de transação, de inserção, atualização e remoção de registros de certa tabela. Nessa nova Kb o que teríamos é um objeto externo, obtida pela operação Tools->Application Integration->WSDL Import, que apontado para o endereço do WDSL exemplificado na imagem anterior, nos devolveria três objetos:
 
Um External Object chamado de Pais_BCBC, e dois SDT´s denominados Pais_BCBCPais e Pais_BCBCMessages_Message.  O primeiro SDT traz a estrutura da transação mais alguns atributos de controle e o segundo as mensagens devolvidas pelas operações.

A partir do External Object teríamos a possibilidade de criar variáveis (ou objetos) do tipo Pais, e operar as três operações essenciais: Insert, Update e Delete, ou na linguagem de Business Component: Load, Save e Delete.
 
Apesar de termos agora a possibilidade de operar remotamente a transação em qualquer objeto Gx desta nova kb, poderíamos inclusive, gerar um formulário de Pais e inserir registros nessa tabela remota, que podemos fazer por meio de um webpanel.

Nesse nosso teste é carregar o pais 1, por meio deste objeto externo e apresentá-lo na interface, o método LoadKeySvc realiza a carga de um registro no WebService.  Um evento Enter faz o papel de atualizar a informação, por meio do método SaveSvc.

Event Start
    &Messages = &Pais.LoadKeySvc(1, &Pais_SDT)
    do 'MessagesShow'
EndEvent

Event Enter
     &Messages = &Pais.SaveSvc(&Pais_SDT)
    do 'MessagesShow'
EndEvent

Sub 'MessagesShow'
    for &Message in &Messages
         msg(&Message.Description)
    endfor
EndSub

Se você tem dificuldades em determinar os tipos das variáveis, ai vai uma ajudinha.

A interface mais simples é inserir a variável &Pais na tela, que é apresentada no formato de uma tabela com campos. Se quiser simplificar, arraste a variável &Pais_SDT, para a interface que o GeneXus monta o formulário.



Finalmente, ao executar o formulario remotamente verá que é possível alterar um registro de Pais estando em outro sistema. A operação remota produz o mesmo efeito da manipulação do formulário da transação na Kb original. 

Conclusão
Se você tem por objetivo dividir seu projeto em kbs isoladas, e se a quebra de intregridade referencial provocada por essa divisão não afetar significativamente seu modelo, então temos aqui um recurso excepcional para trabalhar com informações que não precisam estar em uma mesma base de dados, ou sistema, enfim, temos em nossa mão um mecanismo para acessar e operar informações de tabelas distantes.

Observe o quão simples foi fazer tudo isso em GeneXus, visto que a complexidade envolvida no processo limitou-se a compreensão de meras propriedades e objetos.  Portanto, com um pouco de investimento cerebral é possível pensar em sistemas mais modularizados, melhores e mais eficientes, e também reaproveitar o que está pronto sem ter que reprogramar tudo.

Controle remoto? sim, eficiente, interessante e muito simples.

Maiores informações em: