Ir para o conteúdo

Introdução ao App Builder - Apêndice B: A camada de negócios no App Builder (Avançado)

Este é o segundo apêndice da série de tutoriais Introdução ao App Builder. Esses apêndices complementam as lições da série e fornecem informações mais detalhadas sobre conceitos apresentados.

Nesta lição, exploraremos ainda mais a camada de negócios do App Builder, a área onde criamos regras.

Uniões

As associações, apresentadas na Lição 7, são usadas quando trabalhamos com regras que extraem dados de mais de uma tabela na camada de dados. Elas combinam dados horizontalmente, adicionando colunas de uma segunda tabela ao lado das colunas da primeira.

As uniões funcionam de forma diferente: em vez de adicionar colunas, elas empilham linhas. Uma união acrescenta os resultados de uma consulta sobre outra, produzindo uma lista combinada de registros extraídos de mais de uma tabela. Para que uma união funcione, ambas as consultas devem incluir pelo menos uma coluna com o mesmo nome, pois o App Builder usa essa coluna compartilhada como base para empilhar os resultados. É por isso que podemos combinar diretamente as colunas Country de nossas tabelas Customer e Supplier: ambas as colunas compartilham o mesmo nome.

Nota

Se você quiser combinar colunas com nomes diferentes, poderá usar uma subconsulta com um alias para renomear uma delas a fim de que ambos os nomes coincidam. Além disso, se os formatos de dados forem diferentes entre as duas colunas, você poderá convertê-los para um tipo de dados comum para garantir que a união seja bem-sucedida.

Para demonstrar como funciona uma união, vamos criar manualmente uma união que mostre todos os países que existem na fonte de dados Northwinds. Há duas tabelas, Supplier e Customer, que contêm uma coluna chamada Country, portanto combinaremos as entradas de ambas.

  1. Em App Workbench > Rules, clique em + Rule.

  2. Quando a tela de criação de regra aparecer:

    1. No campo Name, insira Supplier (Countries for Supplier and Customer).

    2. No campo Purpose, selecione Business Object.

    3. Certifique-se de que Supplier está selecionado no campo Target.

    4. Clique em Create.

  3. O App Builder criará a regra. Por padrão, ele adiciona a tabela de destino e seleciona sua chave primária. No entanto, nesta regra estamos interessados apenas nos países presentes nas tabelas, portanto desmarque SupplierID, selecione a coluna Country e marque-a como chave primária.

  4. Precisamos adicionar a outra tabela que contém informações de país, então clique em + Tables.

  5. Localize a tabela Customer e clique em Add. O App Builder adicionará a tabela Customer e você poderá vê-la na aba Tables ao lado de Supplier.

  6. Vá para a aba Joins.

  7. O App Builder criou uma associação, mas ajuste-a para ser do tipo que você deseja. Certifique-se de que Supplier está selecionado no campo Left e que o campo Type diz Union.

  8. Clique na aba SQL para ver a sintaxe da sua união:

    SQL union syntax

  9. Para ver seus resultados, clique no botão Results no painel Rule.

  10. Observe que os resultados contêm países duplicados. Isto é esperado: vários clientes e fornecedores estão baseados nas mesmas regiões, portanto cada país aparece uma vez para cada registro em cada tabela. Para produzir uma lista limpa e única de países, usaremos o botão Select Distinct.

  11. Navegue de volta para o Rule Builder.

  12. No painel Rule, clique em More > Edge Case. A caixa de diálogo Edge Case Settings é aberta. Esta caixa de diálogo oferece controle avançado sobre sua regra. Veja Opções avançadas em Aba Rules do App workbench para uma descrição completa de todas as opções disponíveis.

  13. Marque a caixa de seleção Select Distinct para remover linhas redundantes dos resultados, garantindo que cada registro na lista seja único. Clique em Save.

  14. Clique no botão Results novamente. A regra agora retorna uma lista distinta de todos os países representados nas tabelas Customer e Supplier.

Hora de praticar: Use sua regra de união como um controle de lista

Agora, vamos colocar sua nova regra de união em ação. Navegue até as páginas popup Customer e Supplier e altere o tipo de controle do campo Country para List. Na aba List Options, selecione o objeto de negócio de união que você acabou de criar e defina tanto a Key quanto o Title para a coluna Country.

Regras CRUD

Apresentamos regras CRUD em Lesson 7, mas agora vamos examiná-las com mais detalhes.

A sigla CRUD significa "Create, Read, Update, Delete" (Criar, Ler, Atualizar, Deletar). Isso significa que as regras CRUD são o que os desenvolvedores do App Builder usam para inserir, recuperar, alterar ou apagar registros das tabelas presentes na fonte de dados.

Camada de destino: negócio vs. dados

Quando você cria uma regra CRUD, deve selecionar uma camada de destino: a camada de negócio ou a camada de dados. Essa escolha é crítica e tem implicações significativas.

Direcionar a camada de negócio é a abordagem recomendada para a maioria das operações. Quando sua regra CRUD direciona a camada de negócio (por exemplo, o objeto de negócio Order (Source)), ela age como um usuário interagindo com a aplicação. Ela dispara todos os eventos intrínsecos (Save, Update, etc.) associados a esse objeto de negócio. Isso significa que todas as suas regras de validação configuradas, ações personalizadas e rastreamento de auditoria lite serão executados automaticamente. Essa abordagem garante a integridade dos dados e a consistência com a lógica da sua aplicação. Também permite que você use manipuladores de sucesso, falha e reversão para o evento.

Direcionar a camada de dados ignora toda a lógica de negócio. Quando você direciona a camada de dados (por exemplo, a tabela Order), sua regra interage diretamente com o banco de dados. Ela não disparará nenhum evento intrínseco, validações ou rastreamento de auditoria configurado no objeto de negócio. Essa é uma abordagem de "porta dos fundos", útil para operações em massa de alto desempenho quando você intencionalmente quer contornar a lógica de negócio.

Você pode ver essa diferença visualmente no fluxo de trabalho visual; uma regra direcionada à camada de negócio mostrará subprocessos para sua lógica de evento, enquanto uma direcionada à camada de dados não mostrará.

Nota

O App Builder também suporta regras CRUD XP, que são regras especializadas para gravar dados entre duas fontes de dados diferentes. Essas regras sempre são executadas pela camada de negócio para garantir que toda a lógica seja aplicada. Consulte CRUD (rule) para mais informações.

Atualização CRUD

Primeiro, vamos ver como criar uma regra de atualização CRUD. Isso significa modificar registros existentes em uma tabela. Para demonstrar, vamos criar uma regra que aumenta todas as quantidades dos produtos solicitados.

  1. Em App Workbench > Rules, clique em + Rule.

  2. No campo Name, digite OrderDetail (Quantity + 1).

  3. No campo Purpose, selecione CRUD.

  4. No campo Action, selecione Update.

  5. Em Target Layer, selecione Data Layer. (Para essa atualização em massa simples, vamos contornar a lógica de negócio).

  6. No campo Target, selecione OrderDetail.

  7. Clique em Create. O App Builder levará alguns segundos para criar a regra.

  8. Na aba Tables, a tabela OrderDetail aparecerá, com sua chave primária, OrderDetailID, selecionada. Selecione também a coluna Quantity clicando em sua caixa de seleção.

  9. Vamos adicionar uma nova coluna com um alias para nos ajudar a visualizar que a regra está funcionando. Vá para a aba Columns e clique em + Column. Quando a caixa de diálogo Column - Add Column abrir, digite as seguintes informações:

    1. No campo Column or Expression, digite OD.Quantity + 1.

    2. No campo Alias, digite um nome legível. Usaremos QuantityPlus.

    3. No campo Target, selecione Quantity. Isso diz ao App Builder para escrever o resultado dessa expressão na coluna Quantity.

  10. Clique em Save.

  11. Na guia Columns, você verá tanto Quantity quanto QuantityPlus. A coluna original OD.Quantity também será direcionada para Quantity por padrão. É necessário remover seu direcionamento para evitar ambiguidade:

    1. Localize a linha OD.Quantity na lista Columns.

    2. Clique no dropdown Target. Um botão X aparece ao lado. Clique nele para remover o direcionamento da coluna.

      Isso garante que apenas nossa expressão QuantityPlus seja usada para atualizar a coluna Quantity. Se ambas fossem direcionadas, aquela com o índice mais alto "venceria", levando a um comportamento imprevisível.

  12. A regra está pronta. No painel Rule, clique no painel Results para vê-la funcionando. Observe que a coluna extra que você adicionou aumenta todas as quantidades em uma unidade:

    OrderDetail results

Copy Rule

Pense em como você criaria uma regra de atualização CRUD semelhante à que criamos acima, mas com o efeito oposto, ou seja, uma regra que modifica todas as entradas na coluna Quantity da tabela OrderDetail subtraindo uma unidade. No entanto, em vez de construir essa regra do zero, vamos usar o recurso Copy Rule do App Builder, que duplica uma regra existente para que você a use como ponto de partida, economizando tempo ao criar regras semelhantes às que já construiu.

  1. Em App Workbench > Rules, localize a regra OrderDetail (Quantity + 1) e clique em More > Copy Rule.

  2. Clique em Copy.

  3. O App Builder cria a nova regra, nomeando-a OrderDetail (Quantity + 1) (New). Você é levado diretamente à sua tela de edição. No painel Rule, atualize o campo Name para OrderDetail (Quantity - 1) e navegue até a guia Columns.

  4. Localize a expressão OD.Quantity + 1 e edite-a. Altere a expressão para OD.Quantity - 1 e atualize o Alias de QuantityPlus para QuantityMinus. Clique em Save.

  5. Verifique se a regra está funcionando corretamente clicando em Results no painel Rule.

Hora de praticar: Adicione controles de quantidade

Agora que você tem ambas as regras de quantidade, conecte-as ao painel Order Details na página Orders.

  1. Abra o objeto comercial OrderDetail (Source) e crie um evento personalizado para a regra OrderDetail (Quantity + 1). Na caixa de diálogo de criação de evento, digite Quantity Plus no campo Name e defina Refresh Scope como Row. Isso garante que quando o evento dispara, apenas a linha afetada seja atualizada em vez de todo o painel.

  2. Repita a etapa 1 para criar um segundo evento denominado Quantity Minus, anexando a regra OrderDetail (Quantity - 1) e também definindo Refresh Scope como Row.

  3. Navegue até a tela de edição da página Orders. No painel Order Details, adicione dois controles Button: um que executa o evento Quantity Plus e outro que executa o evento Quantity Minus.

  4. Visite a visualização da página Orders e teste os novos botões.

CRUD delete

As regras de exclusão CRUD são usadas para apagar registros das tabelas. No entanto, como é fácil usar elementos da interface do usuário para excluir registros individuais, as regras de exclusão CRUD normalmente são usadas apenas para excluir muitos registros de uma vez. Para demonstrar, vamos criar uma regra de exclusão CRUD que deleta todos os detalhes do pedido associados a um pedido individual, a fim de eliminar a necessidade de excluir todos os detalhes do pedido separadamente quando um pedido é cancelado.

  1. Em App Workbench > Rules, clique em + Rule.

  2. No campo Name, digite OrderDetail (Delete OrderDetail for Order).

  3. No campo Purpose, selecione CRUD.

  4. No campo Action, selecione Delete.

  5. Em Target Layer, selecione Data Layer.

  6. No campo Target, selecione OrderDetail.

  7. Clique em Create.

  8. Na guia Tables, o App Builder adicionou a tabela OrderDetail e selecionou sua chave primária, OrderDetailID. Mantenha isso selecionado, pois direcionar a chave primária é a forma mais eficiente e segura de executar uma operação de exclusão. Selecione também a coluna OrderID; usaremos essa coluna na próxima seção para vincular a regra a um pedido específico.

Eventos

As regras CRUD só podem ser usadas quando estão anexadas a eventos, que são processos incorporados em tabelas ou objetos de negócio executados em resposta a certas ações, como salvar um registro. Todas as tabelas e objetos de negócio possuem intrinsecamente quatro eventos: salvar, atualizar, excluir e inserir, que são executados conforme você altera registros no App Builder.

Vamos ativar as regras CRUD que criamos. Para isso, criaremos nossos próprios eventos personalizados. Diferentemente dos eventos intrínsecos, eventos personalizados devem estar anexados a um controle para serem executados. As regras CRUD que estamos criando exigem eventos personalizados para executar quando desejamos.

Primeiro, vamos criar um evento personalizado para associar à nossa regra de exclusão CRUD, de modo que quando um pedido for excluído, os detalhes do pedido relacionados também sejam excluídos.

  1. Em App Workbench > Rules, localize e abra a regra Order (Source).

  2. No painel Rule, clique em Events. A página All Events (Order (Source)) é aberta. Ela lista os quatro eventos intrínsecos que o App Builder inclui para cada tabela e objeto de negócio: Insert, Save, Update e Delete. Para uma descrição completa desta página e suas opções, consulte Configure an event.

  3. Como estamos criando um evento personalizado, clique em + Rule Event. A página Event é aberta, onde você pode adicionar os detalhes do novo evento (consulte Event detail options para uma descrição completa de todos os campos):

    1. Em Event Information, no campo Name, digite Delete Order Details.

    2. Em Messages, no campo Confirmation, digite uma mensagem que será exibida aos usuários antes da execução do evento, pedindo que confirmem se desejam prosseguir. A mensagem deve deixar claro o que acontecerá se o usuário continuar, ajudando a evitar ações acidentais. Consulte Configure an event para aprender sobre os outros tipos de mensagem.

      Confirmation message

    3. Na seção Execution Properties, marque a caixa Transaction. Isso garante que o evento seja uma execução "tudo ou nada": como nossa regra de exclusão afeta múltiplos itens de linha, uma transação garante que se ocorrer um erro no meio do processo, o App Builder reverta todas as alterações. Isso evita um cenário em que alguns registros sejam excluídos enquanto outros permanecem, deixando os dados em estado inconsistente. Consulte Execution properties para uma descrição completa de todas as opções nesta seção.

    4. Deixe os outros campos com suas seleções padrão e clique em Save. O App Builder criará o evento.

      Nota

      Para cenários de acesso simultâneo onde a integridade dos dados pode ser comprometida, o App Builder também fornece Event Locking, que força a execução serial e pode ser direcionada a registros individuais. Deixe isto desmarcado para o evento atual, mas tenha-o em mente para ambientes de alto tráfego ou fluxos de trabalho complexos onde a sincronização em nível de registro é um requisito.

  4. O evento foi criado e o App Builder exibe sua tela de configuração:

    Delete Order Details configuration screen

    Você está atualmente na Grid View (mostrada na captura de tela acima), que fornece uma lista de alto nível de todas as ações e validações registradas neste evento. Uma visualização alternativa do evento pode ser vista no Visual Workflow Editor, que mostra a ordem de execução e o relacionamento entre eventos herdados. Para vê-lo, clique no ícone no painel Event. Para retornar à Grid View a qualquer momento, clique no ícone que a substitui.

    O Visual Workflow Editor transforma seus eventos em diagramas de fluxo interativos, facilitando a visualização do caminho que seus dados percorrem conforme se movem pelo sistema. Cada evento é mapeado como um processo com pontos de início e fim distintos, e subprocessos marcados com um ícone de mais podem ser clicados duas vezes para explorar camadas mais profundas de lógica. Você pode usar botões dedicados para adicionar novas ações ou validações diretamente à sequência, e selecionar qualquer nó para editar seus detalhes, excluí-lo ou reorganizá-lo na cadeia de lógica. Consulte Visual Workflow Editor para uma descrição completa de seus recursos.

  5. O evento ainda não possui ações anexadas a ele. Se estiver na Visualização em Grade, observe que o painel Ações está vazio e clique no botão Registrar. Se estiver no Editor de Fluxo de Trabalho Visual, clique no botão + Ação na parte superior do painel Diagrama de Eventos. Isso abre a caixa de diálogo Ação:

    1. No campo Tipo, selecione Regra.

    2. No campo Regra, selecione OrderDetail (Delete OrderDetail for Order), a regra CRUD de exclusão que criou anteriormente.

    3. Deixe os outros campos com suas seleções padrão. Esses incluem configurações de Posição que controlam a ordem e o tempo de execução. Consulte Tipos de ação de evento para obter uma descrição completa. Clique em Salvar. A caixa de diálogo da ação mostrará mais detalhes:

      Ação Excluir OrderDetails

    4. No painel Vinculações, clique em + Vinculação. Selecione OrderID como a Coluna de Origem e OrderID como a Coluna de Regra.

      Nota

      Esta etapa de vinculação é crítica, pois filtra os resultados da regra pelo registro do painel em relação ao qual executou o evento. Se deixada "desvinculada", a regra de exclusão afetaria todos os registros na tabela OrderDetail. Ao vincular a Coluna de Origem (OrderID do registro do painel Order (Origem)) à Coluna de Regra (OrderID na regra de exclusão), adiciona-se um filtro implícito (por exemplo, WHERE OrderID = 10248).

      Isso garante que apenas os registros de OrderDetail que correspondem a esse OrderID específico sejam excluídos. Se essa vinculação for omitida, disparar o evento excluirá todos os registros da tabela OrderDetail.

    5. Clique em Salvar.

  6. O evento personalizado agora está pronto para ser implementado.

Leitura adicional

Além do que é mostrado neste exemplo, a configuração de eventos do App Builder também pode incluir o seguinte:

  • Onde os eventos são configurados: Os eventos podem ser configurados na camada de negócios (objetos de negócios) ou na camada de dados (tabelas). Registrar eventos na camada de negócios permite lógica distinta por interface, enquanto eventos da camada de dados são globais. Leia mais em Onde os eventos são configurados.

  • Herança de eventos: Os objetos de negócios podem herdar lógica de eventos da tabela subjacente ou de outras fontes. Leia mais em Herança de eventos.

Hora da prática: Adicionar um controle de exclusão

Agora que a regra de exclusão e o evento estão prontos, vamos colocá-los em funcionamento na interface. Adicione um botão Excluir Detalhes do Pedido ao painel Pedidos e vincule-o ao evento Excluir Detalhes do Pedido que acabou de configurar. Isso permite que os usuários limpem os detalhes de um pedido inteiro com um único clique.

Regras de subconsulta

Uma regra de subconsulta funciona como intermediária lógica, calculando ou ajustando dados antes de passá-los para outro objeto. Diferentemente das regras padrão que interagem diretamente com um registro, as subconsultas não gravam novamente nas tabelas. Em vez disso, realizam uma operação específica, como uma agregação, para gerar um valor para uso em outro lugar na aplicação.

Demonstraremos criando uma regra de subconsulta. Ela será usada para encontrar o máximo OrderNumber da tabela Order e adicionar um a ele. Mais tarde, criaremos uma regra CRUD com o objetivo de copiar um pedido, e ela dependerá dessa subconsulta para funcionar.

  1. Em App Workbench > Regras, clique em + Regra.

  2. No campo Nome, digite Order (OrderNumber + 1).

  3. No campo Finalidade, selecione Subconsulta.

  4. No campo Alvo, selecione Order.

  5. Clique em Criar. O App Builder criará a nova regra.

  6. O App Builder selecionará automaticamente a chave primária da tabela Order, mas não será necessária para esta regra. Desmarque-a na guia Tabelas.

    Por que desmarcar OrderID?

    Ao usar uma função de agregação como faremos aqui, adicionar qualquer outra coluna à consulta (como OrderID) fará com que o banco de dados aplique uma cláusula GROUP BY para essa coluna.

Se incluíssemos OrderID, a expressão encontraria o máximo OrderNumber por OrderID. Isso apenas retornaria o OrderNumber de cada pedido, o que não é o que queremos.

Para encontrar o único máximo OrderNumber em toda a tabela, não devemos incluir nenhuma outra coluna em nossa consulta. É por isso que usamos uma subconsulta: para realizar esse cálculo de agregação primeiro, de modo que possa ser usado em outra regra.

  1. Na aba Columns, clique em + Column. O diálogo Column - Add Column será aberto.

  2. No campo Column or Expression, digite a expressão Max(O.OrderNumber) + 1. A sintaxe Max() invoca a função Max(), que encontra o maior valor na coluna O.OrderNumber. Em seguida, um é adicionado a ela.

  3. No campo Alias and Target, digite um alias apropriado para essa coluna, como MaxOrderNumber.

  4. No campo Logical Data Type, selecione Number, já que OrderNumber não é um UUID, mas um número natural.

  5. Clique em Save.

  6. Verifique se a regra está funcionando corretamente clicando no botão Results. Deve haver apenas uma linha com um número de pedido, que deve ser um número maior que o maior número de pedido atualmente presente na tabela Order.

Agora vamos criar uma regra CRUD capaz de copiar um pedido. Essa regra CRUD dependerá da regra de subconsulta que acabamos de criar para funcionar.

  1. Em App Workbench > Rules, clique em + Rule.

  2. No campo Name, digite Order (Copy Order).

  3. No campo Purpose, selecione CRUD.

  4. No campo Action, selecione Insert.

  5. No campo Target Layer, selecione Logic Layer.

  6. No campo Target, selecione Order.

  7. Clique em Create. O App Builder criará a regra.

Depois que a regra for criada, configure suas colunas e destinos:

  1. Na aba Tables, o App Builder adicionou automaticamente a tabela Order, mas precisaremos de mais. Clique em + Tables.

  2. Selecione a regra de subconsulta que criamos para esse propósito, Order (OrderNumber + 1). Clique em Add.

  3. Na aba Tables, marque a caixa de seleção ao lado da barra de pesquisa na parte superior da lista de colunas. Isso seleciona todas as colunas existentes da tabela Order de uma vez.

  4. Clique no nome da tabela Order. O diálogo Table é aberto. Em Select all Columns, ative a caixa de seleção. Isso garante que qualquer nova coluna adicionada à tabela Order no futuro seja automaticamente incluída nessa regra. Feche o diálogo.

  5. Da tabela de subconsulta Order (OrderNumber + 1), selecione sua única coluna, MaxOrderNumber.

  6. Na aba Columns, refine o mapeamento de dados da regra da seguinte forma:

    • Remova o destino para OrderID. Como essa é uma chave primária gerada automaticamente, a camada de negócios atribuirá automaticamente um valor único quando a regra for executada.
    • OrderNumber: Confirme que a linha OON.MaxOrderNumber tem como destino OrderNumber, mapeando o novo valor incrementado para a coluna correta.
    • OrderDate: Clique no campo Column or Expression dessa coluna e substitua seu valor atual por Now() para definir a data do pedido copiado como hoje.
    • Nem todas as colunas são necessárias nessa regra. Remova as seguintes:
      • RequiredDate, ShippedDate e Freight: Esses detalhes devem ser inseridos manualmente para o novo pedido em vez de duplicados do original.
      • AddedOn, AddedBy, ChangedOn, ChangedBy e IsActive: O App Builder gera automaticamente esses valores após a criação.

    Leitura complementar

    Saiba mais sobre esse conceito em Target in business object rules.

  7. Clique em Results no painel Rule para verificar se a regra está funcionando corretamente.

Agora vamos criar uma segunda regra CRUD para copiar os itens de linha do pedido. Essa regra será registrada como um manipulador de sucesso no evento Copy Order, garantindo que as linhas de detalhe sejam criadas apenas depois que o novo registro de pedido existir.

  1. Em App Workbench > Rules, clique em + Rule.

  2. No campo Name, digite OrderDetail (Insert) Copy Order Detail.

  3. No campo Purpose, selecione CRUD.

  4. No campo Action, selecione Insert.

  5. No campo Target Layer, selecione Logic Layer.

  6. No campo Target, selecione OrderDetail.

  7. Clique em Create.

  8. Na aba Tables, marque a caixa de seleção ao lado da barra de pesquisa para selecionar todas as colunas existentes de uma vez. Em seguida, clique no nome da tabela OrderDetail, ative Select all Columns no diálogo Table e feche o diálogo.

  9. Na aba Columns, faça as seguintes alterações:

    • Exclua as colunas de auditoria e selecionáveis pelo usuário (AddedOn, AddedBy, ChangedOn, ChangedBy, IsActive). Essas serão preenchidas automaticamente após a criação.
    • Atualize a expressão para OrderDetailID para NewUUID(). Isso garante que cada item de linha copiado receba seu próprio identificador exclusivo.
    • Remova o alvo para OrderID e defina seu alias como BindOrderID. Esse valor representa a ID do pedido original, que usaremos para vinculação durante o evento.
    • Adicione uma nova expressão usando Generated() direcionando OrderID. A função Generated() recupera um valor criado durante a execução do evento atual e aceita dois argumentos: o valor e o tipo de dados. Digite Generated('OrderID', 'UUID') como a expressão.
  10. Clique em Results para verificar a regra.

Agora criamos ambas as regras de cópia. Vamos anexar a regra Copy Order a um evento personalizado e conectar a regra Copy Order Lines para dispara automaticamente em seu sucesso.

  1. Em App Workbench > Rules, localize e abra a regra Order (Source).

  2. No painel Rule, clique em Events. A página All Events (Order (Source)) abre.

  3. Clique em + Rule Event. A página Event abre:

    1. Em Event Information, no campo Name, digite Copy Order.

    2. No campo Refresh Scope, selecione Panel Refresh. Isso garante que o painel seja atualizado imediatamente após a conclusão da cópia, para que o novo pedido apareça sem uma atualização manual.

    3. Em Messages, configure uma mensagem de confirmação, sucesso e falha usando substituição dinâmica. Ao usar chaves duplas, você pode extrair dados em tempo real da regra subjacente e injetá-los no texto. Como esse evento está registrado na regra Order (Source), você tem acesso a todas as suas colunas. Por exemplo:

      • Confirmation: Are you sure you want to duplicate order {{OrderNumber}}?
      • Success: Order {{OrderNumber}} has been successfully copied!
      • Failure: Error: Order {{OrderNumber}} failed to copy!
    4. Na seção Execution Properties, marque a caixa de seleção Transaction para garantir a integridade dos dados, revertendo todo o processo se qualquer parte da duplicação falhar.

    5. Deixe os outros campos com suas seleções padrão e clique em Save.

      Nota

      Consulte Event detail options para obter uma descrição completa de todos os campos.

  4. O evento foi criado. No painel Actions, clique em Register. O diálogo Action abre:

    1. No campo Type, selecione Rule.
    2. No campo Rule, selecione Order (Copy Order).
    3. No painel Bindings, clique em + Binding. Selecione OrderID como a Source Column e OrderID como a Rule Column. Usar OrderID para vinculação é mais confiável que OrderNumber, que pode não ser único.
    4. Salvar.
  5. No painel Actions, há um campo Handlers que mostra três botões: Success, Failure e Rollback:

    • Success Handler: É acionado apenas quando a regra pai é concluída com sucesso. Use-o para encadear lógica, como copiar nossos detalhes de pedido, que depende da existência do registro pai em primeiro lugar.
    • Failure Handler: É acionado apenas se a regra pai encontrar um erro. Use-o para enviar alertas, registrar erros ou disparar ações de compensação.
    • Rollback Handler: Usado ao trabalhar com sistemas que não suportam transações de banco de dados padrão, como uma API REST de terceiros. Executa ações em ordem cronológica inversa para desfazer manualmente a execução da regra até esse ponto.

Clique em Success. O diálogo Success Handlers será aberto. Clique em Create. O diálogo Action será aberto:

  1. No campo Type, selecione Rule.
  2. No campo Rule, selecione OrderDetail (Insert) Copy Order Detail.
  3. Salve.
  4. No painel Bindings, clique em + Binding e mapeie o seguinte:
    • Source Column: Selecione OrderID (o ID único do pedido sendo copiado).
    • Rule Column: Selecione BindOrderID (o alias que criamos na regra para identificar o registro de origem).
  5. Salve.

  6. Saia dos diálogos abertos e navegue até o Visual Workflow Editor clicando no ícone . O diagrama de eventos agora é mais complexo que o evento Delete Order Details que revisamos anteriormente. Observe o seguinte:

    • Logic Layer: Tanto a regra Copy Order quanto Copy Order Lines são executadas pela camada de negócios, por isso ambos os blocos de regra mostram o ícone +. Clique duas vezes em qualquer bloco para navegar diretamente aos eventos pai que ele dispara.
    • Conditional paths: Você pode ver os caminhos de ramificação para Success e Failure. O caminho Success mostra a regra Copy Order Lines sendo disparada, enquanto o caminho Failure não mostra eventos subsequentes, confirmando que o processo para se a cópia principal falhar.

Hora de praticar: Adicione um controle de cópia

Agora que suas regras de cópia e evento estão prontos, vamos colocá-los em funcionamento na UI. Adicione um botão Copy ao painel Orders e vincule-o ao evento Copy Order que você acabou de criar. Depois que o botão for adicionado, teste-o: você deverá ver a mensagem de confirmação com o número de pedido dinâmico e, após o sucesso, um novo pedido aparecerá usando o próximo número de pedido disponível.

Validações

Regras de validação são usadas para garantir que os dados inseridos no App Builder sejam válidos antes de serem salvos. Na Lição 7, abordamos uma validação simples de "campo obrigatório". Agora exploraremos um cenário de validação mais complexo, incluindo lógica personalizada e mensagens de erro dinâmicas.

Como outras regras, regras de validação devem ser anexadas a um evento para serem usadas. A escolha do evento depende do caso de uso:

  • Intrinsic event: Use isto quando você quer que a validação seja executada automaticamente durante operações padrão (por exemplo, evitar salvar se os dados são inválidos).

  • Custom event: Use isto quando você quer disparar a validação sob demanda a partir de um controle específico (por exemplo, um clique de botão).

Vamos criar uma regra de validação para garantir que um desconto em um pedido nunca seja maior que 10%. Queremos que isso seja executado toda vez que um registro OrderDetail seja salvo, então o anexaremos ao evento de salvamento intrínseco.

  1. Em App Workbench > Rules, clique em + Rule.

  2. No campo Name, digite OrderDetail (Validate Discount).

  3. No campo Purpose, selecione Validation.

  4. No campo Target, selecione OrderDetail.

  5. Clique em Create.

  6. Na aba Tables, selecione a coluna Discount (você pode desselecionar OrderDetailID).

  7. Na aba Where, clique em + Where Clause. Um diálogo será aberto onde você pode criar cláusulas WHERE:

    Diálogo de cláusula Where

    1. No campo Left Expression, digite OD.Discount.

    2. No campo Operator, selecione >.

    3. No campo Right Expression, digite 0.1.

  8. Clique em Save.

A regra agora foi criada. Ela foi projetada para encontrar dados "ruins" (registros onde o desconto é superior a 10%).

Limiar dinâmico

Na última etapa, codificamos um limite de 10%. Agora, vamos torná-lo configurável: armazenaremos o limiar como um parâmetro de aplicação para que o negócio possa atualizá-lo a partir da UI sem tocar na regra. Aplique as seguintes etapas usando as habilidades das lições anteriores:

  1. Adicione uma coluna DiscountMaximum à tabela Parameter. Defina o Logical Data Type como Percent e a escala como 4 para capturar valores precisos como 12,25%.

  2. Navegue até a página Parameter. Na tela de edição de tabela, o botão Pages oferece um atalho: lista todas as páginas que usam essa tabela, permitindo que você acesse diretamente a página certa.

  3. Adicione DiscountMaximum como um controle numérico à página e preencha-o com um valor como .3 para permitir descontos de até 30%.

  4. Retorne para App Workbench > Rules e abra a regra OrderDetail (Validate Discount).

  5. Na aba Tables, clique em + Tables e adicione a tabela Parameter. Selecione a coluna DiscountMaximum.

  6. Na aba Where, clique no ícone de lápis para editar a cláusula WHERE. No campo Right Expression, substitua 0.1 por P.DiscountMaximum.

O valor definido na página Parameter agora controla o limite para essa validação.

Anexar a regra de validação

Agora, vamos anexar a regra de validação ao evento de salvamento intrínseco para OrderDetail.

  1. Em App Workbench > Rules, localize o objeto de negócio OrderDetail (Source) e abra-o.

  2. No painel Rule, clique em Events. A página All Events (OrderDetail (Source)) abre.

  3. Localize a linha Save. Observe que há dois botões de designer: Table Event Detail e Rule Event Detail. Queremos registrar essa validação usando Rule Event Detail. Essa é uma distinção importante: garante que a validação seja aplicada apenas quando essa regra específica for utilizada, em vez de impor uma restrição global em toda a tabela OrderDetail. Isso mantém o app flexível. Por exemplo, você poderia construir uma página Manager Approval posteriormente. Ao usar um objeto de negócio diferente lá, um supervisor poderia autorizar descontos maiores sem ser bloqueado pela regra padrão que estamos criando aqui. Clique em Rule Event Detail para o evento Save.

  4. No painel Validations, clique em Register. A caixa de diálogo Validation abre:

    Validation dialog

  5. No campo Type, selecione Rule.

  6. No campo Rule, selecione OrderDetail (Validate Discount), a regra de validação que acabamos de criar.

  7. No campo Binding, selecione Implicit.

    Nota

    Implicit binding valida contra os dados atualmente "na memória" na tela do usuário. Esse é o valor digitado pelo usuário, antes de ser salvo no banco de dados. Usamos implicit binding aqui porque queremos impedir que o usuário salve um novo registro enquanto o valor de Discount for inválido (ou seja, maior que o limite configurado). Por outro lado, Explicit binding valida contra os dados já salvos no banco de dados.

    Para ilustrar, imagine um registro salvo com um desconto inválido de 50%. Um usuário abre esse registro, corrige o campo Discount para um valor válido como 7% e envia. Se o evento de validação usar explicit binding, ele verificará o banco de dados, verá o valor original de 50% e falhará na validação. No entanto, se o evento de validação usar implicit binding, ele verificará o valor na memória (7%), verá que não é maior que o limite e passará na validação, permitindo o salvamento.

    Leia mais em Implicit and explicit binding.

  8. No campo Failure, selecione Fail on data returned.

    Nota

    As validações do App Builder podem ser configuradas de duas maneiras. A padrão, que estamos usando, é Fail on data returned. Isso significa que a regra de validação foi escrita para encontrar dados ruins (por exemplo, Discount é maior que o limite). Se a regra encontrar registros que correspondem a esse critério "ruim", ela falha e exibe a mensagem de erro. A alternativa é Fail on no data returned, que é usada quando uma regra foi escrita para encontrar dados bons.

  9. No campo Severity, selecione Error.

    Nota

    O campo Severity determina com que força o App Builder interage com o usuário quando uma validação é acionada:

    • Error: O nível mais crítico. Indica um problema grave e impede o salvamento inteiramente. O usuário vê uma notificação vermelha e deve corrigir os dados antes de poder prosseguir.
    • Warning: Um bloqueio suave. Alerta o usuário sobre um possível problema com uma notificação amarela, mas oferece a opção de cancelar e corrigir ou prosseguir e salvar o registro mesmo assim.
    • Information: Puramente informativo. Fornece uma notificação azul após o evento ser executado para dar contexto útil ao usuário, mas nunca interrompe ou bloqueia o fluxo de trabalho.
  10. No campo Message, insira: Discount cannot be greater than {{ DiscountMaximum }}. Usar substituição dinâmica aqui garante que a mensagem de erro reflita automaticamente qualquer limite atualmente definido na página Parameter.

  11. Clique em Save para fechar o diálogo.

A validação está anexada. Para testá-la, acesse a visualização da página Orders, selecione um pedido e tente editar um item OrderDetail para ter um desconto maior que o limite definido. Ao clicar para salvar, você deve ver a mensagem de erro dinâmica.

Para que o placeholder {{ DiscountMaximum }} seja resolvido corretamente, a coluna deve estar disponível no objeto de negócios OrderDetail (Source). Como DiscountMaximum está em uma tabela Parameter separada, é necessário adicioná-lo explicitamente:

  1. Retorne a App Workbench > Rules e abra a regra OrderDetail (Source).

  2. Na aba Tables, clique em + Tables e adicione a tabela Parameter. Selecione a coluna DiscountMaximum.

O nome da coluna na regra deve corresponder exatamente ao placeholder na sua mensagem de validação. Se você tivesse usado um nome diferente na mensagem (por exemplo, {{ MaxDiscount }}), seria necessário criar um alias da coluna na regra para corresponder.

Leitura complementar

Para conhecer mais técnicas sobre como garantir a integridade dos dados, consulte Validation rules.

Aprendizado adicional

Isso conclui este aprofundamento nos detalhes da camada de negócios do App Builder. Consulte Appendix A para uma análise mais detalhada da camada de dados, Appendix C para a camada de interface do usuário, ou Appendix D para a camada de segurança.