Exercícios práticos GeneXus 15
Copyright GeneXus S.A. 1988-2017. Todos os direitos reservados. Este documento não pode ser reproduzido em qualquer meio sem o consentimento explícito de GeneXus S.A. A informação contida neste documento é exclusivamente para uso pessoal. Marcas Registradas GeneXus é uma marca registrada ( ) em diversos paises e regiões, incluindo, entre outros, América Latina, EEUU, Japão, a UE e Uruguai. Todas as demais marcas mencionadas neste documento são propriedade de seus respectivos donos. Página 1
O PROBLEMA... 3 1. NOVO PROJETO, NOVA BANCO DE CONHECIMENTO... 3 2. PRIMEIRAS TRANSAÇÕES... 4 TRANSAÇÃO CUSTOMER... 4 TRANSAÇÕES ATTRACTION E COUNTRY, RELACIONADAS... 6 Dados relacionados: como a integridade é mantida?... 8 TRANSAÇÃO CATEGORY... 8 ADICIONANDO AS CIDADES NA TRANSAÇÃO COUNTRY... 10 TRANSAÇÃO ATTRACTION : ADICIONANDO A CIDADE.... 11 3. ADICIONANDO COMPORTAMENTOS ÀS TRANSAÇÕES (RULES)... 12 4. PATTERNS: MELHORANDO A INTERFACE PARA TRABALHAR COM A INFORMAÇÃO... 13 5. TRANSAÇÕES FLIGHT E AIRPORT E NECESSIDADE DE DEFINIR SUBTIPOS... 17 6. FÓRMULAS... 17 7. RELATÓRIOS PDF... 19 8. PASSAGEM DE PARÂMETROS... 23 RELATÓRIO DE ATRAÇÕES EM UMA DETERMINADA FAIXA... 23 9. BUSINESS COMPONENTS... 24 AUMENTO DE PREÇO DOS VÔOS... 24 TELA PARA EXCLUSÃO DE TODOS OS VÔOS... 26 CRIAÇÃO DE CARTÕES PARA ACUMULAR PONTOS... 27 10. PROCEDIMENTOS PARA ATUALIZAR REGISTROS... 28 AUMENTO DE PREÇOS DOS VÔOS... 28 EXCLUSÃO DE TODOS OS VÔOS... 28 INICIALIZAÇÃO DE INFORMAÇÕES NO BANCO DE DADOS [OPCIONAL]... 30 11. WEB PANELS... 33 TELA COM FILTROS... 33 TODOS OS PAISES, TODAS AS ATRAÇÕES... 35 12. EXTENDED CONTROLS... 35 13. OBJETO QUERY... 36 14. WEB SERVICES... 36 15. É PRECISO TER UMA PARTE PARA SMART DEVICES... 37 16. GENEXUS SERVER... 38 17. DEFINIÇÃO DE UM MODELO DE PROCESSO DE NEGÓCIOS (BPM) PARA A RESERVA DE UMA ATRAÇÃO [OPCIONAL]... 39 18. TESTAR A APLICAÇÃO COM GXTEST [OPCIONAL]... 41 Página 2
O problema Uma agência de viagens contrata você para desenvolver um sistema que armazene e manipule a informação com que trabalha. Imagine que o sistema é composto de dois módulos: Backend: parte da aplicação que deverá estar em um servidor web, de modo que os empregados da agência possam manipular a informação de qualquer lugar que tenha conexão com a internet. Aplicação simples para dispositivos móveis: parte da aplicação que será baixada pelos clientes da agência de viagens, que lhes permitirá consultar as excursões disponíveis assim como as principais atrações turísticas que cada cidade oferece. 1. Novo projeto, nova base de conhecimento Entrar no GeneXus e criar uma base de conhecimento chamada TravelAgency para começar o desenvolvimento da aplicação. Sugerimos: Escolher C# como ambiente de desenvolvimento. Garantir que tenha instalado todo o necessário (incluindo SQL Server). Se estiver usando GeneXus Trial, o ambiente de geração com C# e SQL Server já é padrão, prototipando na nuvem da Amazon. Não criar a base de conhecimento na pasta Meus Documentos ou qualquer outra pasta que fique abaixo de Documents and Settings, porque estas pastas têm permissões especiais concedidas pelo Windows. Dedique uns minutos para familiarizar-se com o IDE (ambiente de desenvolvimento integrado do GeneXus). Experimente mover janelas, visualizar janelas específicas que desejar (View e View/Other Tool Windows) e observe com cuidado o conteúdo da janela KBExplorer (Knowledge Base Explorer). Verá que aparecem domínios já inicializados, alguns objetos, imagens, etc. Sugestão: mantenha a janela de propriedades aberta (F4), pois irá utilizá-la continuamente. Dentro da janela Preferences é onde configura-se o Environment. Página 3
2. Primeiras transações Nas reuniões com a agência de viagens, é dada a seguinte informação: Nós registramos os dados de nossos clientes, e lhes oferecemos viagens para diferentes cidades de diferentes paises, nas quais registramos também suas atrações turísticas. Para começar a construir a aplicação, devemos primeiro identificar os atores da realidade, ye representá-los através das transações. Então, quais transações devemos criar na base de conhecimento (KB)? Transação Customer Perguntamos aos empregados da agência de viagens: Quais informações dos seus clientes são registradas? Sabendo que a resposta é: O nome (que não seja maior que 20 caracteres), apellido (do mesmo tamanho), direção, telefone e e-mail. Já pode criar a transação Customer. Lembre-se que: Para criar objetos, existem várias alternativas: o Acessando o menu: File/ New Object o Ctrl+N o Ícone da barra de ferramentas É preciso definir um atributo que identifique cada cliente (CustomerId). Digitando ponto (. ) quando for criar um novo atributo, este será inicializado com o nome da transação. Address, Phone e Email são dominios semânticos que são atribuidos automaticamente nos atributos que contém, em seu nome, os textos Address, Phone ou Email respectivamente. A estrutura da transação deve ficar como mostrado abaixo: O próximo passo é colocar a aplicação em execução. Garantir que a janela Output do GeneXus esteja habilitada e visível. (View/Other Tool Windows /Output) Página 4
Agora sim, podemos executar a aplicação, pressionando F5. O que vai acontecer? Solução Se escolher criar o banco de dados e os programas localmente, será aberta uma janela como abaixo, para definir as informações de Banco de Dados, Servidor e Método de conexão. Lembre-se que, se não existir, nesse servidor, um banco de dados com o nome indicado, GeneXus irá criá-lo. Em vez disso, se o banco de dados e os programas forem criados na nuvem, a janela anterior não vai aparecer, porque GeneXus conhece os dados do servidor da nuvem e configura automaticamente o nome do banco dados e as informações de conexão necessárias. Depois disso, é exibida uma Análise de Impacto informando que será criado o banco de dados e a tabela CUSTOMER dentro do mesmo: Página 5
Ao pressionar o botão Create, GeneXus irá executar o programa encarregado de realizar essas criações. Ao finalizar o processo, um menu com links para executar os objetos criados será aberto no navegador definido como padrão pelo usuário. Neste caso, aparecerá somente um objeto: a transação Customer. Cadastre alguns clientes no sistema. Modifique alguma informação de algum cliente previamente cadastrado e, por último, elimine algum cliente. Tente também usar as setas disponíveis para navegar pelos registros de clientes. Entre os ícones, ao clicar na imagem da lupa, aparece uma lista de seleção para ver os clientes registrados e selecionar um deles. Agora vamos identificar e criar a próxima transação. Vamos lembrar o que nos pediram: Nós registramos os dados de nossos clientes, e lhes oferecemos viagens para diferentes cidades de diferentes paises, nas quais registramos também suas atrações turísticas. Transações Attraction e Country, relacionadas Vamos a criar uma transação para registrar as atrações turísticas e outra para registrar os paises a que estas pertencem. Quais informações a agência de viagens deve guardar de cada atração? Nome, pais, imagem da atração e a categoria a que pertence. Já pode criar as transações. Vamos começar por Country. Lembre-se que: pressionando ponto (. ) quando estiver definindo o nome de um atributo na estrutura da transação, este é inicializado com o nome da transação. será necessário criar um atributo identificador, CountryId. Quando estiver definindo o tipo de dados do atributo identificador, em vez de utilizar Numeric(4.0) diretamente, crie o domínio Id, com esse tipo de dados. Configure a propriedade Autonumber desse domínio como True, para que todos os atributos baseados nele também sejam automaticamente autonuméricos, sem que o usuário precise se preocupar com isso. Observe todos os domínios que já vêm pré-definidos no GeneXus. Em particular, Address, Email e Phone que apareceram automaticamente quando criou os atributos CustomerAddress, CustomerEMail e CustomerPhone na transação Customer. Defina o atributo CountryName e, no tipo de dados, crie um novo domínio: Name=Character(50). Agora, vamos criar a transação Attraction. Por enquanto, defina somente o identificador, o nome e o pais. Página 6
Observe que, ao definir AttractionId, ele automaticamente assume o domínio Id. Da mesma forma, quando definir o atributo AttractionName, este assumirá automaticamente o domínio Name. Por que colocar, além de CountryId, o atributo CountryName em Attraction? Resposta: é importante que o atributo CountryName esteja na tela da transação, para mostrar o nome do pais, porque é uma informação que identifica melhor o pais, em vez de mostrar somente seu identificador. Também é necessário definir o atributo na estrutura da transação para podermos utilizá-lo, por exemplo dentro de uma regra. Execute a aplicação (F5) e irá aparecer o relatório de Análise de Impacto abaixo: CountryName? Página 7
Por que não aparece o atributo CountryName na tabela Attraction que GeneXus irá criar no Banco de Dados, quer dizer, por que a tabela física não irá contê-lo, sendo que ele está na estrutura da transação? Depois de analisar o relatório, se estiver tudo certo, pressionamos Reorganize para que execute as alterações apresentadas. O navegador será aberto com um menu contendo links para 3 programas que correspondem a cada uma das transações ( Customer, Country e Attraction ). Cadastre os paises: Brasil, França e China. Observe que, se deixarmos o valor do identificador como 0, quando gravar o registro, seu valor será automaticamente definido com o número posterior ao último pais cadastrado previamente (comprovando que é auto-numérico). Cadastrar as atrações turísticas: Louvre Museum, que está na França. Se não lembrar o identificador da França, como fazer para informar o pais? Do lado de CountryId, aparece um ícone com uma flecha, criado automaticamente pelo GeneXus, para abrir uma Lista de seleção de paises. Isso acontece porque CountryId é uma chave estrangeira (foreign key) nesta transação (ou seja, está apontando para outra tabela). Dados relacionados: como a integridade é mantida? Attraction e Country estão relacionados. Ao colocar CountryId na estrutura de Attraction, por ter o mesmo nome do atributo que é chave primária na transação Country, GeneXus entende que CountryId é chave estrangeira em Attraction e mantém automaticamente a integridade da informação. Por exemplo: Tente cadastrar uma atração com um id de pais que não existe. Ele permite gravar a atração turística? Escolha uma atração cadastrada previamente (por exemplo, Louvre Museum) e altere o pais, para um que não exista. Permitiu gravar a modificação? Tente excluir um pais (usando a transação Country) que esteja associado a alguma atração (por exemplo, França). Foi possível? Conclusão: os programas correspondentes às transações garantem a integridade dos dados. Transação Category Ainda falta completar a informação da transação Attraction. Os empregados da agência de viagens descreveram que registram a categoria (monumento, museu, parque, etc.) a que pertence cada atração turística. Dessa forma, vamos precisar criar uma transação para registrar esta informação, e acrescentar a categoria na transação Attraction. Porém, quando estiver manipulando os dados de uma atração, nos disseram que não é obrigatório registrar a categoria a que ela pertence. É possível deixá-la vazia. Sabendo que GeneXus controla automaticamente a integridade, como podemos fazer isso? Página 8
Solução: Para terminar a definição da transação Attraction, falta ser criado o atributo que armazena a sua foto. Para isso, crie o atributo AttractionPhoto e defina seu tipo de dados como Image. Execute a aplicação, pressionando (F5). Observe o que o relatório de Análise de Impacto está mostrando. Deverá criar a tabela Category, e converter a tabela Attraction já existente, adicionando três elementos de informação (um para o atributo CategoryId e dois para o atributo AttractionPhoto. Não se preocupe em entender porque é preciso armazenar dois valores para a imagem). Página 9
Clique em Reorganize e execute. Cadastre categorias (como museu e monumento) e acesse as atrações turísticas já cadastradas para completar as informações (categoria e foto). Observe que, neste caso, podemos deixar a categoria vazia (porque configuramos a propriedade Nullable como Yes na estrutura da transação). Porém, se tentarmos atribuir, na atração turística, um valor de CategoryId que não existe, não deixará gravar. 2.1. Adicionando as cidades na transação Country Além dos paises com que a agência de viagens trabalha, necessitamos registrar a informação de suas cidades. Portanto, devemos acrescentar um segundo nivel na transação Country, com um identificador e o nome da cidade. Página 10
Lembre-se que: Posicionado no atributo CountryName, com botão direito, clique em / Insert Level para criar o subnível. Depois de definirmos um nome para o nível, quando estiver criando os atributos do nivel, se digitar aspas duplas ( ) no lugar de ponto, o nome do atributo iniciará com o nome do nível. As cidades serão identificadas pelo seu próprio id combinado com o do pais. Ou seja, não será possível identificar uma cidade sem antes infomar o pais a que pertence. Então, poderia existir uma cidade 1 Rosario tanto para o Uruguai como para a Argentina: Pais: 1 (Uruguai) Cidade: 1 (Rosario) Pais: 2 (Argentina) Cidade: 1 (Rosario) Ou ainda, pode ser que Rosario para Argentina seja identificada com outro número: Pais: 2 (Argentina) Cidade: 4 (Rosario) Reorganize e execute (F5). Observe que o Relatório de Navegação apresenta o seguinte: A propriedade autonumber para o caso de CityId será ignorada. Isso significa que, em execução, o usuário deverá informar manualmente os identificadores da cidade. A explicação é que a propriedade Autonumber somente autonumera chaves primárias simples e, neste caso, CityId é o segundo componente de uma chave composta. Será criada uma nova tabela CountryCity para armazenar a informação correspondente às cidades. Cadastre cidades para os países que já estão registrados. Transação Attraction : vamos adicionar a cidade. Na transação Attraction, vamos adicionar a cidade do pais a que a atração pertence. O que deve ser feito já que a agência de viagens nos informou que esse valor não é obrigatório? Execute a aplicação e teste (F5 e Reorganize). Página 11
Solução: Antes de seguir, abra a transação Customer e modifique o tipo de dados de CustomerId para que tenha o domínio Id (e, assim, seja auto-numérico). Modifique também os tipos de dados de CustomerName e CustomerLastName para que assumam o domínio Name. Reorganize. 3. Adicionando comportamento nas transações (Rules) Depois de testarmos a aplicação que estamos desenvolvendo para a agência de viagens, eles nos informam que existem alguns comportamentos específicos para os clientes que o sistema deve validar quando o usuario estiver manipulando a informação através da transação Customer. Quais são estes comportamentos? Foi pedido: O sistema não deve permitir cadastrar clientes sem nome, nem sem apelido. Deve advertir o usuário se o telefone não for informado, caso tenha se esquecido. O sistema deve permitir registrar a data de cadastro do cliente (CustomerAddedDate), sugerindo que o valor padrão para esse atributo seja a data de hoje, podendo ser alterada pelo usuário. Especifique esses comportamentos e teste (F5 e Reorganize). Lembre-se que: As regras são finalizadas com ponto e vírgula ;. O método IsEmpty() aplicado a um atributo, devolve True quando o atributo está vazio e False, caso contrário. A variável &today é de sistema e traz o valor da data do dia. Para escrever uma variável dentro da aba Rules, ao digitar & são mostradas todas as variáveis definidas até o momento. A outra possibilidade é utilizar Insert / Variable. Página 12
Experimente cadastrar um novo cliente deixando o seu nome vazio. Foi possível gravar ou passar para o campo seguinte? Ídem com o apelido. Acontece o mesmo com o telefone? Se depois, pedirem que a data de cadastro não possa mais ser manipulada pelo usuário, mas somente visualizada, como estabelecer este comportamento? Especifique e teste em execução. 4. Patterns: melhorando a interface para trabalhar com a informação Quando mostramos para o cliente o que foi feito até agora, ele nos disse que gostaria de manipular as informações de paises, categorias e atrações turísticas de uma maneira mais organizada e agradável (que ofereça uma consulta com a possibilidade de filtrar, assim como inserir, modificar e excluir dados, etc.). Para isso, debe-se aplicar os patterns Work With for Web nas três transações. Execute. Observar que: existe um Work With para Smart Devices también. Porém, o que você deverá aplicar é o correspondente à aplicação web que está sendo desenvolvida. GeneXus irá criar automaticamente vários objetos para cada transação, implementando o Trabalhar com dessa entidade. Página 13
Solução: Por que as transações Category, Country e Attraction não aparecem mais no Developer Menu? Experimente: 1. Cadastrar um novo pais. 2. Modificar um pais existente (por exemplo, adicionando uma cidade). 3. Excluir um pais existente. 4. Visualizar a informação de um pais. 5. Realizar uma busca por nome de pais. Página 14
6. Cadastrar um par de atrações turísticas (Ex: A muralha China, de China/Beijing, Eiffel Tower da França/Paris) 7. Filtre as atrações turísticas cujo nome comece com F. E se quisermos poder filtrar todas as atrações turísticas da França? Esta possibilidade ainda não existe. Então, devemos personalizar o pattern Work With desta transação, para criar o novo filtro. Faça isso no GeneXus e execute. Solução: Para isso, primeiro observe como está especificado o filtro já existente, pelo nome da atração turística: 8. Agora remova os identificadores de pais, cidade e categoria da tela do Work With e veja em execução. Página 15
9. Agora, se quiser possibilitar que o usuário escolha ordenar as atrações pelo nome da atração ou pelo nome do pais, implemente e teste. Não deve permitir que o usuário exclua paises a partir da tela principal gerada com a aplicação do pattern. Edite a instância do pattern e modifque as propriedades necessárias. Página 16
5. Transações Flight e Airport e necessidade de definir subtipos Agora, é preciso registrar os vôos que a agência de viagens oferece. Cada vôo tem um identificador e vai de um aeroporto até outro. Cada vôo também tem um preço. Para o preço, crie um domínio chamado Price, do tipo Numeric(10.0). Crie uma transação para registrar aeroportos. Cada aeroporto tem um identificador, um nome, um pais e uma cidade em a cual se encontra. Como definimos que cada vôo irá ter um aeroporto de origem e outro aeroporto de destino? Lembre-se 1) Na estrutura da transação: um ícone representado por uma flecha para cima informa que o atributo é chave estrangeira (Foreign Key), ou seja, aponta para outra tabela. Um ícone representado por uma flecha para baixo informa que o atributo é inferido de outra tabela. Um ícone representado por um indica que o atributo é um subitpo. 2) Sobre os grupos de subtipos: São definidos da mesma maneira que qualquer tipo de objeto. Cada grupo de subtipos obrigatoriamente deve conter um subtipo de um atributo primário (que é chave primária de uma tabela) ou um conjunto de atributos que formam uma chave primária. Em cada grupo de subtipos, é preciso incluir todos os atributos subtipos que se deseja relacionar, pertencentes à tabela base e/ou estendida da chave primária do grupo. Execute e verifique que ao tentar cadastrar um vôo, será disparado um erro caso o aeroporto de partida informado no vôo não existir. Ídem para o aeroporto de destino. Não deve ser permitido cadastrar um vôo cujo aeroporto de partida seja o mesmo do aeroporto de destino. Implemente esse comportamento e teste em execução. 6. Fórmulas É necessário registrar o desconto atual que tem cada vôo. Defina um novo atributo na transação Flight para armazenar esta informação. Coloque o nome do novo atributo como: FlightDiscountPercentage e defina seu tipo de dados com um domínio Percentage, numeric(3). Deseja-se visualizar o preço final do vôo já com o desconto aplicado. Para resolver isso, defina mais um atributo, chamado FlightFinalPrice, com uma fórmula global que calcule automaticamente o preço final do vôo: Página 17
Pressione F5, observe na Análise de Impacto, qual atributo será criado fisicamente e qual não, reorganize e teste a aplicação em funcionamento. Crie um segundo nivel na transação Flight chamado: Seat, para registrar seus assentos. Dado que os assentos geralmente são identificados por um número e uma letra, a chave primária (ou identificador único) do segundo nivel, deverá ser composta de 2 atributos: FlightSeatId: para registrar o número do assento FlightSeatChar: para cadastrar a letra Defina um domínio SeatChar, do tipo: character(1) e relacione-o ao atributo FlightSeatChar. Delimite as letras possíveis para o domínio: são válidas somente as que estão entre A e F (editando a propriedade Enum Values do mesmo). Criar outro atributo no 2do nivel da transação Flight: FlightSeatLocation. Definir um domínio Location associado ao mesmo, do tipo Character(1). No nodo Domains do KBExplorer, editar a propriedade Enum Values do domínio Location e definir os 3 valores abaixo: Window (valor que se armazenará: W ) Middle (valor que se armazenará: M ) Aisle (valor que se armazenará: A ) Se observarmos o form da transação Flight, veremos que, para cada assento, será possível indicar a localização do mesmo através um combobox contendo os valores Window, Middle o Aisle. Lembre-se: para definir que determinado atributo será parte da chave primária, deve-se pressionar o botão direito do mouse sobre o atributo e, no menu contextual, aparecerá a opção Toggle Key. Página 18
Para saber a capacidade de passageiros que o vôo comporta, crie um atributo novo no primeiro nivel da transação Flight: FlightCapacity, tipo: Numeric(4.0) e defina-o uma fórmula global que conte a quantidade de assentos que o vôo possui. É necessário visualizar a capacidade do vôo no formulario web e validar para que não seja registrado nenhum vôo com menos de 4 assentos. Este controle deverá ser disparado depois que o usuario terminar de cadastrar todos os assentos e depois de ter pressionado o botão Confirm. 7. Relatórios pdf Agora, vamos supor a aplicação deva oferecer ao usuário a possibilidade de emitir relatórios pdf com a informação desejada. Por exemplo, suponha que é necessário emitir um relatório mostrando todas as atrações turísticas armazenadas no banco de dados, em ordem alfabética. O resultado final deve ser mais ou menos como mostrado abaixo: Sugestão: Utilizar o controle Image disponível na Toolbox para implementar uma imagem do lado do título do relatório. Essa imagem deverá ser integrada à base de conhecimento (KB). Para isso, selecionar a opção Import from File, buscar a imagen desejada e atribuir-lhe um nome. Página 19
Implemente isso no GeneXus. Lembre-se: para poder visualizar um relatório diretamente no browser, o mesmo deve ser gerado como PDF. Para isso, deve-se configurar as seguintes propriedades do objeto procedimento: Main program = True Call Protocol = http Report output = Only to File E a seguinte regra: Output_file( nome-arquivo.pdf, PDF ) Para executar o relatório, clique sobre a aba do objeto com o botão direito e depois escolha / Run with this only Reparou nas informações do relatório de navegação do procedimento? E se agora for preciso que o relatório saia ordenado pelo nome do pais? Implemente, observe o relatório de navegação e teste. E se agora for preciso mostrar somente as atrações da França? Teste (observando o relatório de navegação) Página 20
Em cada caso, analise qual tabela do banco de dados está sendo percorrida para realizar a consulta do for each. Também é necessário criar um relatório como está sendo mostrado abaixo (que mostre cada categoria e, para cada uma delas, suas atrações turísticas). Implemente e teste. Sugestão: Para reutilizar parte do primeiro relatório criado, clique com o botão direito sobre o nome do procedimento e selecione a opção Save as... Salve-o com outro nome. Adicione uma nova categoria no sistema, por exemplo Art Gallery (galeria de arte). Execute o relatório novamente. Essa nova categoria apareceu na lista? Modifique o relatório para que não sejam listadas categorias que não tenham atrações turísticas relacionadas. Qual diferença é possível observar no relatório de navegação? Resposta: A aparição da palabra break indicando que está sendo realizado um controle de corte. Nesses casos, como o relatório de navegação demonstra, a tabela base do for each externo é igual à do for each aninhado. A agência solicita adicionar um botão na tela principal do WWCountry para fazer a chamada do relatório. Página 21
Outra solicitação da agência de viagens é um relatório que mostre todos os países e, para cada pais, a quantidade de atrações turísticas que oferece: Depois, nos pedem outro relatório que mostre todos os paises que possuem mais de 2 atrações associadas: Página 22
8. Passagem de parâmetros Muitas vezes um objeto precisa receber alguns parâmetros que serão utilizados dentro da sua lógica. Por exemplo, uma coisa é emitir um relatório pdf com todas as atrações turísticas do banco de dados, e outra é gerar um relatório somente daquelas cujo nome está dentro de uma determinada faixa. Relatório de atrações em uma determinada faixa Grave com outro nome o procedimento que havia criado anteriormente para listar as atrações turísticas, e modifique-o para que agora liste somente as atrações cujo nome se encontre dentro de uma faixa recebida por parâmetro (o valor inicial e o final da faixa serão os parâmetros recebidos). Implemente uma tela que para que o usuário informe esses valores e chame o relatório, pasando-lhe esses valores por parâmetro. Experimente em execução. Lembre-se que: Se definirmos uma variável baseada (based on) em um atributo, esta ficará ligada ao tipo de dados do atributo, ou seja, se o tipo do atributo for modificado, o da variável também será. As variáveis utilizadas para receber as informações do usuario na tela que chama o relatório e as utilizadas como parâmetros que recebem os valores no objeto chamado, não precisam ter o mesmo nome, porém devem ter tipos de dados compatíveis. Solução: No procedimento (chamado AttractionsFromTo ) acrescentamos a regra parm (e definimos ambas variáveis no procedimento): parm( in: &fromname, in: &toname ); No Source: print Title print ColumnTitles for each Attraction where AttractionName>= &fromname where AttractionName <= &toname print Attractions endfor E depois criamos um web panel, no qual definimos duas variáveis, que podem ter qualquer nome, por exemplo A e B, porém devem ter tipo de dados compatíveis com os das variáveis &fromname e &toname do procedimento. Por que? Porque serão nestas variáveis que o usuário informará os valores. No evento que programamos, serão enviadas por parâmetro para o procedimento, da seguinte forma: AttractionsFromTo( &A, &B) Página 23
9. Business Components Realizaremos algumas operações na banco de dados, através de business components. Aumento de preço dos vôos De vez em quando a agência de viagens precisa incrementar os preços dos vôos de acordo com um percentual determinado. Para isso, deveremos implementar uma tela para que o usuário informe esse percentual de aumento, e mande aplicá-lo a todos os vôos do banco de dados. Implemente isso e teste. Lembre-se que: O objeto web panel permite implementar telas flexíveis para entrada e saída de dados. Para o cadastro de dados (onde o usuário possa cadastrar valores pela tela), através da Toolbar, pode inserir um controle Attribute/Variable no form e atribuir-lhe uma variável. Se quiser editar a barra de menu principal do GeneXus, clique com botão direito sobre ela e poderá inserir, por exemplo, a barra Formatting. Para que o web panel tenha alguma ação determinada, é possível inserir botões e programar o evento associado. Os business components são tipos de dados criados quando setamos a propriedade Business Component do objeto transação como Yes. Quando fazemos isso, para inserir, alterar ou excluir registros nas tabelas correspondentes, é possível utilizar, além da transação, uma variável do tipo de dados Business Component em qualquer outro objeto (por exemplo, um web panel) e realizar as mesmas operações através dos métodos Load(), Save() e Delete(). Para que as operações realizadas através do Business Component sejam efetuadas de maneira permanente, debe-se executar o comando Commit. Se quisermos incrementar 20% em um valor X, devemos escrever X = X*(1+20/100) = X*1,20 Solução: Uma solução possível (tente implementar primeiro sem ver o que está abaixo): criamos um Web panel, com uma variável &percentage, com o tipo de dados: Numeric(3.0) Página 24
Quando damos duplo clique sobre o botão, acessamos a aba Events, editando o evento associado ao botão. Em nosso exemplo é o evento Confirm. Nele, programaremos a lógica que queremos executar quando o usuário pressionar o botão. Precisamos percorrer todos os vôos e alterar o preço que tinham, aumentado seu valor de acordo com o percentual indicado pelo usuário na variável da tela. Para percorrer todos os vôos do banco de dados, usamos o comando For each. E, em cada vôo, como fazemos para modificar o valor de FlightPrice? Precisaremos de uma variável para isso, que tenha toda a estrutura da transação Flight, e depois nos permita gravar no banco de dados. Que tipo de dados essa variável debe ter, então? O Business Component Flight (observe que o tipo de dados business component tem o mesmo nome da transação). Porém, GeneXus não cria esse tipo de dados automaticamente para cada transação. Como fazemos para cria-lo? Alterando a propriedade correspondente da transação. Depois disso, então: Como as operações de gravação ou exclusão do banco de dados (através dos métodos Save() e Delete()) podem provocar erros, é importante saber se estes ocorreram. Para isso, temos o método Success() que devolverá True se não houveram erros, e False, caso contrário. Ao inserir, alterar ou excluir registros de uma tabela do banco de dados, enquanto não mandarmos que aquilo que foi feito fique gravado permanentemente, essas modificações serão provisórias. O que isso quer dizer? Que, por exemplo, se houver uma queda de energia, essas modificações se perderão. A forma de definir que tudo fique gravado permanentemente é executando o comando Commit. Se, ao contrário, quisermos que tudo seja desfeito, executamos o comando Rollback. Página 25
Tela para exclusão de todos os vôos Grave o web panel anterior com outro nome (botão direito sobre a aba do objeto e escolha Save as) e modifique o Form para que contenha somente um botão com o texto Delete all flights, de modo que, em execução, este web panel fique assim: Quando o usuário presionar o botão, todos os vôos da banco de dados deverão ser eliminados. O que deve ser modificado no evento Confirm que programamos anteriormente? Nota: nas propiedades do botão, é possível modificar o seu texto, alterando a propriedade Caption. Solução: O Msg fará com que apareça essa mensagem na tela do web panel. Página 26
Criação de cartões para acumular pontos A agência deseja ter um processo que permita criar automaticamente um cartão para acumular pontos de cada um de seus clientes. Somente uma cartão por cliente. Para isso, crie uma nova transação chamada Card, e declare as seguintes regras: - Por padrão, um cartão tem a seguinte descrição : Points card. - Por padrão, um cartão é criado com a data de hoje. - Por padrão, um cartão é criado com um total de 500 pontos. Solução: a) Declarar a transação Card como Business Component. b) Criar um novo web panel WPGenerateCards, com um botão que irá disparar o processo automático de criação de cartões. c) Criar o data provider DPCards que será o responsável por devolver o conjunto de cartões a serem criados. d) Lembre-se que somente deverão ser criados cartões para os clientes que ainda não possuem nenhum. Qual é a definição da variável &Cards? Como é o output do Data Provider? Como os atributos restantes são inicializados? Página 27
e) Aplique o pattern Work With na transação Card. f) Execute a aplicação, crie os cartões e verifique se foram criados corretamente. 10. Procedimentos para atualizar registros Aumento de preços dos vôos Suponha que existem milhares de vôos que devem ter seus preços aumentados de acordo com um percentual informado (volte ao primeiro exercício do ponto 9). Sabendo que o aumento de preço é um procedimento simples que não causará nenhum erro ou falha na integridade dos dados, tente resolvê-lo com um procedimento, sem utilizar business components. Lembre-se que: Com o comando For each dentro de um procedimento, é possível atualizar os atributos de sua tabela estendida através de simples atribuições. A atualização direta através de procedimentos não controla a integridade da informação. Todo objeto deve declarar os parâmetros que recebe e os parâmetros que devolve. Se não forem declarados, não receberá nem devolverá valores. Os parâmetros são declarados através da regra parm. As variáveis são locais para o objeto que as utiliza. Isso significa que, se quiser receber um valor como parâmetro em uma variável &X, devo declara-la no objeto. Exclusão de todos os vôos E se agora quisermos eliminar todos os vôos, como fizemos no ponto 9 do exercício, porém através de um procedimento? Solução: Criar um procedimento FlightsDeletion que não recebe parâmetros, com o seguinte código: for each Flight for each Flight.Seat delete endfor delete endfor Faça um Save as no web panel que tinha implementado no ponto 9 (o que fazia a exclusão através de Business Component), e altere o evento Enter: Event Enter FlightsDeletion() EndEvent Página 28
E se, finalmente, quiser apagar toda a informação do banco de dados? Solução Criar um procedimento DeleteAll com o Source: for each Flight for each Flight.Seat delete endfor delete endfor for each Airport delete endfor for each Attraction delete endfor for each Category delete endfor for each Customer delete endfor Lembre-se: os procedimentos não validam a integridade dos dados, porém o banco de dados sim. Quer dizer, o banco de dados valida a integridade dos dados interrelacionados, portanto, a ordem que você irá excluir os dados é importante. Por exemplo, se tentar excluir os países antes das atrações, o banco de dados irá impedir isso, o programa será cancelado e não será amigável para o usuário. for each Country for each Country.City delete endfor delete endfor No mesmo web panel utilizado para excluir todos os vôos com Business Components, acrescente um novo botão, no qua iremos associar um evento de usuário, e faremos a chamada do procedimento. Arraste um controle button para o form, e defina o novo evento Página 29
Depois, pressionando o botão direito do mouse sobre o botão e selecionando Go To Event, seremos posicionados no evento associado ao botão. Dentro dele, fazemos a chamada do procedimento. Execute. Desta forma, o banco de dados ficará vazio. Inicialização da informação do banco de dados [opcional] Quando a aplicação que você está desenvolvendo for colocada em produção (ou seja, comece a ser utilizada pela agência de viagens) todos os dados de paises, categorias e atrações devem ser carregados. Inicialize essas tabelas com a informação que a agência de viagens solicitar e teste. Considere que: É possível povoar as tabelas com dados utilizando o comando new (insere um registro em uma tabela), um data provider que devolva o conjunto de business components a serem carregados, ou a propriedade Data Provider das transações. Se não for atribuido um valor para um atributo da tabela, então: o Se o atributo é auto-numérico, quando gravar o registro no banco de dados (chegar no endnew ), o valor dado para este atributo no banco de dados ficará guardado em memoria para ser utilizado. Por exemplo, se estiver gravando uma categoria: New CategoryName = Monument Endnew Sabemos que, depois do Endnew, se utilizarmos o atributo CategoryId, este terá o valor que o banco de dados atribuiu a ele após a inserção. É preciso inserir a imagem da Torre Eiffel na KB para poder utilizá-la. Uma forma de fazer isso é através da janela Folder View, acessar a pasta Customization e escolher Images, onde serão mostradas todas as imagens armazenadas atualmente na KB, inserir uma nova (de um arquivo) e dar-lhe um nome. Página 30
Solução Para utilizarmos diferentes formas, povoaremos os paises e as categorias utilizando a propriedade Data Provider das transações. Abra a transação Country e configure o valor True na propriedade Data Provider: Carregue os dados desejados em Country_DataProvider (pode vê-lo abaixo da transação Country na janela KBExplorer). Quando for criado, a tabela será carregada com os dados indicados. Lembre-se: O DP associado à transação disparará novamente Cada vez que a tabela correspondente é reorganizada. Cada vez que o conteúdo do DP é editado. Portanto, é necessário controlar para que a informação não seja duplicada. Isso pode ser alcançado: Se a chave primária for autonumerada, pode ser definido um índice unique no atributo descritor. Deixando a chave primária sem autonumerar. Desta forma, seu valor será atribuído de forma fixa ao definir o DP e não será duplicado. Da mesma forma, carregue as categorias Monument, Museum e Famous Landmarks. Defina a transação Attraction como Business Component. Crie o Data Provider DPAttractions, e arraste a transação para dentro do Source Página 31
Observe as propriedades do Data Provider: A transação Attraction representa uma atração. Porém, desejamos que o Data Provider devolva um conjunto de atrações. Portanto, a propriedade Collection deverá estar como True Crie um web panel chamado WPInitializeAttractions. Adicione um botão InitializeAttractions, e codifique seu evento: Ele deverá chamar o Data Provider DPAttractions e inserir, no banco de dados, o conjunto de atrações que ele devolve: Página 32
Nota: Lembre-se que o método Insert aplicado a uma coleção de Business Components (neste caso, uma coleção de atrações) permite inserir todas as atrações daquela coleção. Criar um procedimento DBInitialize com o Source abaixo e chamá-lo de um web panel: //customer: John Cage new CustomerName = 'John' CustomerLastName = 'Cage' CustomerEMail = 'jcage@gmail.com' CustomerAddress = '11235 NE 4 Ave, Miami' endnew //country: China new CountryName = 'China' Endnew new CountryId = CountryId CityId = 1 CityName = 'Beijing' Endnew new CountryId = CountryId CityId = 2 CityName = 'Shangai' endnew Execute a aplicação e verifique se os dados foram carregados corretamente. 11. Web panels A agência de viagens solicita uma página que mostre todos os paises e para cada um deles, a quantidade de cidades que ele oferece. Lembre-se que o evento Load de um web panel que tem uma grid (com tabela base), é executado antes de carregar cada linha da grid. Este evento é adequado para atribuir, em uma variável, o cálculo da quantidade de cidades de cada pais que se está navegando antes de carregar uma linha do grid. Adicione ao web panel definido, duas variáveis (&CountryNameFrom e &CountryNameTo) e defina as condições necessárias para filtrar os paises incluidos em determinada faixa. Tela com filtros A Agência solicita uma tela interativa que permita filtrar as atrações por pais e por categoria. É preciso visualizar o nome da atração, sua foto e a cidade onde se encontra. Página 33
Solução Crie um web panel chamado WPAttractionsByCountryCategory e defina as variáveis correspondentes (&CountryId e &CategoryId). Declare-as como combos dinâmicos. Declare a transação base, e as condições necessárias na grid. Nota: Lembre-se que é possível adicionar nos combos dinâmicos um elemento vazio, permitindo que seja possível visualizar todas as atrações caso não se especifique nenhum pais ou categoria. Página 34
Todos os paises, todas as atrações A agência solicita uma tela que mostre todos os paises, cada um deles com seus respectivas atrações turísticas (nome, foto, cidade e categoria). Lembre-se que o FreeStyleGrid permite alinhar controles de uma forma mais livre. Configurando sua propriedade Columns é possível indicar a quantidade de colunas que serão visualizadas. 12. Extended controls Utilizando o extended control ImageGallery, desenhe um web panel que mostre a galeria de fotos de todas as atrações turísticas. Personalize as propriedades do extended control, estabelecendo Width=1000, Height= 500, e Type=Slider: Página 35
13. Objeto Query Defina um objeto Query que devolva somente as cidades da França, em ordem alfabética, cada uma delas com sua respectiva quantidade de atrações turísticas. Defina um web panel e, utilizando o extended control QueryViewer, visualize a consulta anterior em forma de gráfico. 14. Web services A agência de viagens nos solicitou uma nova funcionalidade: deseja oferecer aos clientes um relatório de todos os paises, mostrando, para cada um deles, sua capital, sua moeda e sua bandeira: Página 36
Para resolver isso sugerimos importar e utilizar um Web Service específico: CountryInfoService, que devolve essas informações e outras mais. A localização do web service é: http://www.oorsprong.org/websamples.countryinfo/countryinfoservice.wso Lembre-se que, ao selecionar o menu de GeneXus: Tools / Application Integration / WSDL Import, será aberto um wizard, que importará todas as especificações, métodos e parâmetros do web service em um objeto externo (external object), além de criar SDTs quando necessário. Lembre-se que, definindo variáveis do tipo do objeto externo, poderá executar os métodos previstos pelo web service. 15. É preciso ter uma parte para Smart Devices A agência deseja oferecer também uma pequena aplicação para dispositivos inteligentes que será utilizada pelos usuários finais. O objetivo é que qualquer pessoa, com seu smart device, possa consultar todos os paises que a agência oferece e, para cada um deles, suas cidades e atrações turísticas. Para isso, é preciso aplicar o pattern Work With for Smart Devices na transação Country: E então, é só gravar. Depois, criar um objeto Dashboard e associar o objeto WorkWithDevicesCountry gerado pelo pattern. Lembre-se que, dentro de nossa base de conhecimento, quando criamos objetos próprios para Smart Devices, ao pressionar F5, o emulador para Android será executado automaticamente, e continuamos podendo acessar também a nossa aplicação web com o Developer menu. Página 37
16. GeneXus Server Publique a base de conhecimento no servidor http://sandbox.genexusserver.com/v15, Crie um novo web panel (WPCustomers) que mostre a lista de clientes da Agência. Envie este novo objeto para o server para que se integre à base de conhecimento centralizada. Cadastre o console web e verifique o estado final da KB. Feche a base de conhecimento anterior, e crie uma nova, sincronizando-a com a KB previamente publicada. Desta forma, se feita uma cópia local da KB administrada pelo GeneXus Server. Nesta nova cópia local, edite a transação Country e defina o novo atributo CountryFlagImage, do tipo Image. Envie esta alteração para servidor. Feche esta KB e abra a KB inicial novamente. Realize a operação Update para receber a mudança realizada. Página 38
17. Definição de um modelo de processo de negócios (BPM) para a reserva de uma atração [opcional] O processo de reserva de uma atração turística consiste em uma série de tarefas que podem consideradas como um processo de negócio. Este processo começa quando uma pessoa vai até a agência de viagens para reservar um pacote turístico de uma determinada atração. A primeira coisa que o empregado da agência deve fazer é cadastrar uma reserva para esse pacote. Depois de cadastrar a reserva, tem que verificar se a pessoa que solicitou o pacote é um cliente da agencia. Caso não seja, deverá cadastrá-la como cliente e associá-lo à reserva. Uma vez completados estes passos, é necessário verificar se existem pacotes disponíveis para a quantidade de pessoas que desejam viajar. Se houverem lugares disponíveis, a reserva será efetuada e o processo de negocios é finalizado. Caso contrário, debe-se oferecer outro pacote para o cliente. Para implementar o modelo, deve-se criar um objeto Business Process Diagram, mas antes, crie uma transação Reservation com os seguinte atributos: ReservationId - Id ReservationDate - Date ReservationQty N(4) CustomerId CustomerName ReservationAvailable Boolean O atributo ReservationAvailable será utilizado para indicar se o pacote turístico está disponível ou não. Para o atributo CustomerId, definimos sua coluna Nullable com o valor Yes, para indicar que, quando cadastrar uma reserva, podemos não ter ainda o identificador do cliente, da pessoa que está adquirindo a reserva Defina o modelo de negócios para a reserva de uma atração turística e execute-o, testando todos os casos mencionados na descrição, de forma a percorrer todo o diagrama. Solução Crie a transação Reservation, de acordo com o que foi solicitado. Crie um objeto Business Process Diagram chamado AttractionReservation. Na toolbar, arraste para o diagrama um símbolo de NoneStartEvent. Localize a transação Reservation na janela Folder View e arraste-a para o diagrama. Para conectar o nodo de Start com a transação, clique na parte inferior do círculo verde e, sem soltar, arraste a conexão até que a ponta da flecha toque a borda superior do retângulo da transação. Página 39
Para representar no diagrama a decisão de verificar se a pessoa é cliente da empresa, arraste um nodo Exclusive Gateway sobre o diagrama e ligue-o com a transação Reservation. Agora, é preciso definir a condição do Gateway que fará com que o fluxo siga o curso normal (para baixo) quando não é necessário cadastrar a pessoa como cliente, ou o fluxo alternativo (para a direita), quando debe-se cadastrar a pessoa como cliente. Primeiro arraste a transação Customer para o diagrama e ligue-a à direita do Gateway. Depois, faça um duplo clique na flecha verde que une o Gateway com a transação Customer e escreva a expressão: Reservation.CustomerId = 0, para indicar que o fluxo deve tomar esse caminho quando, no momento de cadastrar a reserva, o atributo CustomerId ficou com valor 0. Observe que debe-se usar o nome da transação para qualificar o atributo CustomerId, distinguindo o atributo que é chave estrangeira na transação Reservation do atributo CustomerId que é chave primária da transação Customer. Para associar o cliente recém-criado na reserva, deve-se criar um procedimento chamado AssignCustomerToReservation e, na seção de regras, escreva uma regra parm, com os parâmetros &ReservationId e &CustomerId. No source do mesmo escreva um For each com uma cláusula Where filtrando o atributo ReservationId junto com a variável ReservationId recebida por parâmetro. Depois, atribua o valor da variável &CustomerId ao atributo CustomerId e encerre o For Each. Desta forma, será atribuido o cliente recém-criado na reserva cadastrada previamente. Agora arraste o procedimento recém-criado para o diagrama e ligue-o com a transação Customer. Continuando com o fluxo habitual (para baixo do Gateway), deve existir uma tela onde se possa confirmar ou cancelar a reserva. Para isso, pode utilizar novamente a transação Reservation e marcar a reserva como disponível ou não, mediante o atributo ReservationAvailable. Arraste a a transação Reservation da janela de Folder View para o diagrama. Renomeie a tarefa como ReservationAvailability e conecte-a com o Gateway. Para indicar que o fluxo para baixo é o fluxo habitual, selecione a conexão e, na janela Propriedades, defina a propriedade ConditionType com o valor Default. Observe no diagrama que o fluxo ficou sinalizado com uma listra de cor verde que cruza o mesmo. Aproveite agora para conectar a tarefa AssigntCustomerToReservation na tarefa ReservationAvailability. Para avaliar o valor informado no check box da transação Reservation, insira um Exclusive Gateway e conecte-o com a tarefa ReservationAvailability. Depois conecte o fluxo alternativo do mesmo (que desenhamos para a esquerda) na tarefa Reservation, para que se possa cadastrar uma reserva nova. Faça duplo clique sobre esse conector e adicione a condição ReservationAvailable=False. Observe que, neste caso não é necessário qualificar o atributo, porque está presente somente na transação Reservation. O que falta fazer agora é o caso em que a reserva seja confirmada, quando já não haverá mais tarefas e deverá finalizar o processo. Para indicar que deve terminar o diagrama, inclua um símbolo de NoneEndEvent e conecte-o com o Gateway. Esta conexão para baixo é o fluxo normal do Gateway, de modo que, quando a reserva se confirmar, finalizará o processo. Para indicar isso, selecione a conexão e, na janela Propiedades, defina a propriedade ConditionType com o valor Default. Agora execute o diagrama. Sobre a aba com o nome do diagrama, clique com botão direito e escolha Run. Será aberta uma tela com o Client GXflow. Selecione a tarefa Reservation e, para executa-la, pressione o botão de Execute, ou faça duplo clique sobre a tarefa. Cadastre uma reserva, deixando sem infomar o identificador do cliente. Pressione Confirmar e feche a janela. Para passar à tarefa seguinte, pressione Send. Como o cliente não foi infomado, a próxima tarefa pendente é a transação Customer. Execute a tarefa e informe a pessoa que solicitou a reserva, como cliente. Feche a janela e pressione Send. Observe que a próxima tarefa é ReservationAvailability, já que a tarefa AssignCustomerToReservation não é interativa e, por isso, foi executada em background. Execute a tarefa, marque o check box e pressione Confirmar. Feche a janela e pressione Send. Página 40
Note que agora a bandeja de entrada está vazia, indicando que não tem mais tarefas pendentes para executar já que chegou-se ao fim do processo. Execute novamente o diagrama, porém agora teste os outros caminhos do diagrama, por exemplo, informando um identificador de cliente na transação Reservation, ou deixando desmarcado o check box ao confirmar a reserva. Para ver o histórico das tarefas executadas, selecione My Processes na janela Navigator e faça duplo clique sobre o Proceso AttractionReservation, na janela da direita. Poderá ver em uma janela, todas as tarefas que foram executadas. Para ver a histórico em forma de animação, selecione More Actions, View Diagram e pressione o botão de Play. 18. Testar a aplicação com GXtest [opcional] Nota: Baixar aquí GXtest. E para mais informação http://abstracta.com.uy/ GXtest nos permite gravar sequências de operações para testar nossas telas e verificar se o sistema continua funcionando corretamente, depois de eventuais alterações. Neste caso, vamos verificar que o preço de um vôo é calculado sem erros. Este preço é representado pelo atributo FlightFinalPrice definido com uma fórmula global. Esta fórmula calcula o preço final do vôo, aplicando o desconto do vôo sobre o preço inicial. Utilizando GXtest, defina um caso de teste informando um vôo com os seguintes valores: Aeroporto de partida: 2 Aeroporto de destino: 1 Preço do vôo: 5000 Desconto do vôo: 50% O preço calculado do vôo será de 2500, já que, como o desconto do vôo é de 50%, a fórmula aplicará esse desconto para calcular o valor do atributo FlightFinalPrice. Continuando com o exemplo, informe os assentos do vôo e não pressione Confirmar. Defina no GXtest, que o valor correto para o texto que mostra o valor do preço do vôo, é de 2500. Pressione Confirmar e feche o navegador. Verifique no GXtest se o caso de teste foi criado corretamente. Verifique se foi criado o pool de dados com os valores informados. Depois, altere a fórmula do atributo FlightFinalPrice (por exemplo, altere o 100 do cosciente, para 10) e execute o caso de teste cadastrado anteriormente. Verifique se GXtest informa que encontrou um erro e veja o valor calculado incorretamente na tela da transação Flight, que é mostrado na janela de resultados do caso de teste. Depois corrija a fórmula (colocando o valor 100 no lugar de 10) e execute novamente o caso de teste. Verifique que, neste caso, GXtest não encontra erros e o resultado do teste mostra o valor do preço do vôo calculado corretamente. Página 41
Solução Abra a aplicação GXtest Designer, através do link na área de trabalho. Crie um projeto novo e atribua um nome. Agora pressione o sinal de mais (cor verde), escolha sua KB na pasta onde está armazenada, adicione uma descrição e pressione OK. Quando finalizar a importação de dados da KB, pressione OK. A URL que GXtest nos solicita é a da aplicação a ser testada. Volte ao GeneXus, execute a transação Flight, copie a URL da mesma e cole no campo URL da janela de Gxtest. Pressione OK. Na parte direita da janela de Design do GXtest, pressione botão direito sobre Test Cases e escolha Record Test Case. Defina um nome para o caso de teste, uma breve descrição e marque a caixa de seleção para que crie automaticamente o conjunto de dados de teste. Pressione o botão roxo, na parte superior direita da janela. Notará que será aberto o navegador e será ejecutada a transação Flight. Cadastre um vôo novo com os dados especificados no exercício, incluindo os assentos, porém não pressione Confirmar para terminar o cadastro do vôo. Antes, selecione o preço do vôo com o mouse (que mostra o valor 2500) e pressione o símbolo de check, na barra de ferramentas de GXtest do navegador. Escolha VerifyControlText e acrescente uma descrição. Pressione Aceitar e novamente Aceitar. GXtest avisará que adicionou corretamente a validação solicitada. Pressione OK. Volte à tela da transação Flight e pressione Confirmar. Feche o navegador e volte ao design de GXtest. Vea que foi criado um caso de teste. No diagrama, selecione o componente chamado Flight e veja que, na janela de comandos, são detalhados todos os passos realizados para cadastrar o vôo na transação Flight. No panel de Project, à direita da tela, embaixo de DataPools, clique no elemento do conjunto de dados. Verifique nessa janela, os dados usados para cadastrar o vôo. Volte ao GeneXus, edite a fórmula do atributo FlightFinalPrice e, na divisão, escreva um 10 no lugar do 100. Pressione F5 para atualizar a aplicação. Para executar o caso de teste definido, volte ao GXtest, selecione a aba do caso de teste e pressione o botão de Play, que se encontra acima, na parte esquerda da tela. Verá que será aberta a janela do navegador, é mostrada a tela da transação Flight e começa a execução automática do caso de teste, informando automaticamente os mesmos dados que você havia informado antes, como se fosse uma pessoa. Preste atenção nos valores e veja que o preço do vôo foi calculado incorretamente. Agora mostra o valor -20000. Quando finalizar o caso de teste, notará que é ativada novamente a janela do Design de GXtest. Abra o editor de leiaute. Notará que foi adicionada uma aba com os resultados do teste. Na coluna Result encontrará o símbolo de um inseto, representando um bug encontrado. No panel da esquerda, clique no símbolo de + ao lado do inseto, e serão abertas várias opções, sendo que à direita ficarão os testes realizados. Duplo clique em Flight, e se abrirá uma tela para poder ver a transação Flight, os passos que integram o teste realizado, o tempo que consumiu cada passo e seu resultado Baixando a barra, verá que aparece o erro de validação do preço do vôo, indicando qual foi o valor esperado e qual foi o valor real obtido. Se clicar sobre a fila do erro, abaixo será apresentada a tela do navegador, com o valor calculado incorretamente. Volte na transação Flight, deixe a fórmula como estava antes (coloque 100 no lugar de 10) e volte ao GXtest para executar novamente o caso de teste. Verifique que agora não aparece nenhum símbolo de erro e que o resultado do cálculo do vôo está correto, mostrando novamente o valor 2500. Verifique o valor, clicando na lista que mostra a validação desse preço e verifique na tela do navegador mostrada abaixo, se o valor mostrado também é 2500. Página 42