Dynamics 365 – Acionar Plugin via JScript

Olá pessoal,

Uma ótima pergunta (ou conjunto de perguntas! rs) foi feita por Tiago Ferraz Alves, que seriam:

Fazer uso do objeto XMLHttpRequest (Ajax) para acionar Plugin é uma prática suportada? Quais são os ganhos e perdas? Você já utilizou anteriormente?

Achei interessante criar um post para que possa ajudar outras pessoas a tomar a decisão de utilizar ou não esta técnica.

Primeiramente, um pouco de base e dimensão do que estamos falando…

Vale apena lembrar que por mais que o Ajax seja capaz de se comunicar com o lado servidor (server-side), sua execução é feita no lado cliente (client-side) de um aplicação, pois é baseado em JScript e envio de pacotes de transmissão.

No entanto, plugins são baseados no server-side, deste modo, apenas serviços/aplicações dentro de um servidor web poderiam “trabalhar” com os plugins.

Como conclusão do que eu disse acima: não é possível “chamar” diretamente um plugin através do lado cliente. Mas indiretamente é absolutamente possível!

Por que indiretamente é possível?

Por mais que não seja possível fazer uma chamada explicita ao plugin, podemos fazer que ele seja executado usando uma chamada client-side. Para fazer isso, existem algumas formas diferentes de se fazer. Vamos a duas abordagens mais utilizadas:

Criar registro em uma entidade customizada para acionar um plugin genérico

Apesar de ainda ser um técnica que pode ser utilizada. Ela era muito mais poderosa quando ainda não tínhamos as Custom Actions (ações de um processo).

A ideia consiste em criar uma nova entidade que funcionará como um orquestrador para o plugin, ou seja, cada vez que um registro for criado neste entidade, um plugin será executado, assim, podemos capturar a ação requisitada (através do contexto e também de atributos da entidade) e realizar a lógica adequada para cada tipo de ação.

Este post não tem o objetivo de explicar tecnicamente como executar esta técnica, porém, este é ótimo artigo para que deseja.

Acionar uma Custom Action  que irá acionar um plugin

 

 

Esta técnica apenas tornou-se possível apenas a partir da versão 2013 do CRM. Faz uso de uma Ação.  Apenas lembrando o objetivo principal de uma ação, que seria, criar ações que um entidade não possui nativamente, possibilitando novos tipos de gatilhos aos processo de negócio.

Além de utilizar um recurso nativo do CRM, tem também a vantagem de necessitar menos codificação do que a técnica anterior. Temos menos etapas de desenvolvimento.

Novamente, o objetivo aqui não é demonstrar como fazer, mas ai vai um artigo com um pouco mais de sofisticação, mas faz uso das Actions!

Bom vamos as respostas das perguntas do Tiago…

– Em resposta a primeira pergunta (se é algo suportado): Sim, completamente suportado.

– Ganhos e perdas, é algo realmente relativo e depende do contexto de utilização, mas vamos lá:

  • Prós:
    • Ambas técnicas podem ser muito eficientes em casos onde precisamos acionar um plugin através de algum controle do lado cliente, como um botão do ribbon, recurso web (web resource) e etc. Pois, usando apenas plugins para esse tipo de situação, implicaria em criar um atributo qualquer que seja alterado via JScript, fazendo o formulário ser salvo e enfim executando a regra de negócio que o plugin possui. Porém, mesmo assim, teríamos que desenvolver ainda mais para fazer algo com o retorno da regra de negócio;
    • Utilizando a proposta da primeira técnica (entidade customizada orquestradora), podemos centralizar ao máximo onde as regras de negócio serão executadas;
    • Utilizando a técnica de acionar uma action, temos como grande vantagem a possibilidade de retornar um output do plugin para a action. Tudo de forma nativa! Isso é muito mais poderoso do que apenas chamar um plugin!
  • Contras:
    • Quando utilizamos chamadas cliente para acionar algo no servidor (em nosso caso plugins). Iremos criar uma chamada extra de desenvolvimento, ou seja, na verdade nossa regra de negócio está no plugin, mas estamos acionando o plugin pelo cliente. Assim, estamos resolvendo um problema, mas inserindo outro. Pois, sempre existirá a possibilidade de ter que dar manutenção nos dois lados do desenvolvimento;
    • Na primeira técnica (entidade customizada), temos o problema de centralizar demais. Pois, considere uma equipe de desenvolvimento trabalhando em um mesmo plugin sempre! Isso não irá ser fácil…
    • É importante não extrapolar o uso desta técnicas, pois para executar qualquer regra de negócio seja necessário primeiro criar um registro em uma entidade ou invocar uma action. Pense em quando processamento adicional será necessário, além de transformar o plugin em uma espécie de Web Service, se a ideia é essa, crie um Web Services! rs
    • Lembre-se também de cenários onde o CRM será consumido por outra aplicação, provavelmente a chamada para a execução de sua regra de negócio deverá ser impactada;

– Última pergunta (se já utilizei): Não, eu não utilizei, pois ao considerar os contras em relação aos pós a resposta foi o uso de outra abordagem. Porém, já criei serviços customizados para serem chamados através de um botão no ribbon por exemplo. Neste caso, não existia uma regra de negócio que precisasse ficar em um plugin.

Bom, espero ter ajudado a esclarecer algumas dúvidas!

[]’s,

Tiago

 

Anúncios
Publicado em Dynamics 365 | Marcado com , | 2 Comentários

The Social Media Revolution 2017

Pessoal,

Todo ano procuro este vídeo no YouTube para me atualizar em relação as Mídias Sociais e a revolução que elas veem fazendo com nossa forma de vender, divulgar e comunicar… Realmente é algo ainda pouco assimilado por nós e principalmente pelas empresas, acredito que o tema esteja sendo muito pouco explorado no Brasil.

Ai vai…

[]’s,

Tiago Cardoso

Publicado em Social Mídia | Marcado com | Deixe um comentário

Dynamics 365 – Acessar WCF Externo Server Side (HTTP Binding + Contract)

Olá pessoal,

No post anterior, escrevi como realizar a comunicação com o serviço WCF externo do Dynamics 365 no server side (utilizei um plugin).

Neste post, irei fazer a mesma chamada, porém utilizando o que acredito que seja o mais recomendado e eficiente. Usar Biding HTML e o Contrato do serviço.

 

É imprescindível que o serviço WCF do post anterior esteja implementado. Pois, ele será a base para este. Na verdade, a única coisa que este post apresenta de diferente é o meio/forma de comunicação com o serviço!

Primeiramente, precisamos gerar o contrato do WCF, para isso, basta navegar no browser pelo endereço do serviço que veremos um tela similar a esta:

Veja que podemos criar nosso contrato utilizando o svcutil.exe (quando instalamos o Visual Studio ele é automaticamente instalado). O svcutil irá ler a interface do WCF e gerar nosso contrato.

Eu inseri alguns parâmetros para facilitar o uso do contrato:

svcutil.exe http://tiagowin20163976.cloudapp.net/WcfService/Mat.svc?wsdl ^
/namespace:*,"Dynamics365" ^
/d:"C:\Users\tiago.cardoso\Downloads"

Para executar o svcutil, precisamos abrir o Developer Command Prompt for VS (cada versão do VS tem programa) e colar o script acima:

No meu caso o arquivo Mat.cs será adicionado na pasta Downloads. Copie e adicione no MESMO PROJETO ONDE O PLUGIN IRÁ FICAR!

A última parte não poderia ser diferente de criar o plugin propriamente! Vou seguir a mesma ideia do post anterior e criar para a entidade Conta (account). Foi colocar o código e depois irei comentar:

using Dynamics365;
using Microsoft.Xrm.Sdk;
using System;
using System.ServiceModel;

namespace Plugins
{
public class AccountCreate : IPlugin
{
#region Secure/Unsecure Configuration Setup
private string _secureConfig = null;
private string _unsecureConfig = null;

public AccountCreate(string unsecureConfig, string secureConfig)
{
_secureConfig = secureConfig;
_unsecureConfig = unsecureConfig;
}
#endregion
public void Execute(IServiceProvider serviceProvider)
{
// Extract the tracing service for use in debugging sandboxed plug - ins.
// If you are not registering the plug-in in the sandbox, then you do
// not have to add any tracing service related code.
ITracingService tracingService =
(ITracingService)serviceProvider.GetService(typeof(ITracingService));

// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));

// The InputParameters collection contains all the data passed in the message request.
if (context.InputParameters.Contains("Target") &&
context.InputParameters["Target"] is Entity)
{
// Obtain the target entity from the input parameters.
Entity entity = (Entity)context.InputParameters["Target"];

// Verify that the target entity represents an entity type you are expecting.
// For example, an account. If not, the plug-in was not registered correctly.
if (entity.LogicalName != "account")
return;

// Obtain the organization service reference which you will need for
// web service calls.
IOrganizationServiceFactory serviceFactory =
(IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

try
{
// Plug-in business logic goes here.
var serviceURL = "http://tiagowin20163976.cloudapp.net/WcfService/Mat.svc";

tracingService.Trace("- CallServiceByWebClientSOAP");
tracingService.Trace("Somar('4','5')");

// Create Bind object
BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.Security.Mode = BasicHttpSecurityMode.None;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
myBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;

// Create endpoint
EndpointAddress endPointAddress = new EndpointAddress(serviceURL);

// Create Channel to access Encrypt Service Interface
ChannelFactory<IMat> factory = new ChannelFactory<IMat>(myBinding, endPointAddress);
IMat channel = factory.CreateChannel();

// Call Encrypt Service
var response = channel.Somar("4", "5");

tracingService.Trace("Result: " + response);

// Close factory
factory.Close();
}
catch (FaultException<OrganizationServiceFault> ex)
{
throw new InvalidPluginExecutionException("An error occurred in MyPlug-in.", ex);
}
catch (Exception ex)
{
tracingService.Trace("MyPlugin: {0}", ex.ToString());
throw;
}
}
}
}
}

Vamos lá:

  • A primeira linha faz uma referência (namespace) ao contrato que criamos com o svcutil;
  • O que acontence dentro do “try“:
    • serviceUrl – Informamos a URL do serviço que estamos requisitando
    • BasicHttpBinding – Criamos o binding que propriamente faz a conexão com o serviço WCF. Note que não estou utilizando nenhum método de autenticação ou proxy neste exemplo;
    • endPointAddress – Criamos um objeto com o endpoint do serviço;
    • factory – Informamos o contrato e endpoint para a classe ChannelFactory. Veja a conversão (unboxing) para o tipo do nosso contrato IMat;
    • channel – Cria o canal com o endpoint, ou seja, cria/abre a conexão com o serviço;
    • channel.Somar – Por fim, chamamos o método do serviço. Veja que por usarmos o contrato do serviço o método e parâmetros são reconhecidos! (tipados)

A resposta da chamada, nada mais é do que o que método retorna. Neste exemplo será um número! O número 9 (5+4)!

Assim, ao criar uma conta no CRM, quando observamos o log de execução do plugin, vemos:

Bom, é isso! Acredito que esta forma seja bem mais robusta e utilize melhores práticas de programação bem como funcionalidades mais atuais!

[]’s,

Tiago

Publicado em Dynamics 365, Dynamics CRM | Marcado com , , , , , | Deixe um comentário

Dynamics 365 – Acessar WCF Externo Server Side (WebClient + SOAP)

Olá pessoal,

Por mais que para alguns seja um assunto já batido. Eu ainda acredito que faltem artigos para melhor descrever como acessar serviços (WCF’s) externos ao Dynamics 365 quando estamos do lado servidor (server side), principalmente no modo online onde existem alguns restrições (falei disso neste post).

Eu não acho que o exemplo oficial seja suficiente e bem detalhado. Pois, não acessa um serviço, não ensina como passar parâmetros…

Neste post, irei fazer/descrever como realizar chamadas à serviços externos utilizando apenas o objeto WebClient e um envelope SOAP. Provavelmente seja o método mais rudimentar, porém o mais simples de se fazer o acesso.

Bom, primeiro vamos criar o serviço WCF… Irei construir um WCF para simplesmente realizar a soma de dois números (apenas para demonstrar a ideia do post).

Primeiramente nossa, interface (IMat.cs):

using System.ServiceModel;

namespace WcfService
{
 [ServiceContract]
 public interface IMat
 {
 [OperationContract]
 int Somar (string x, string y);
 }
}

Agora o code behind do serviço (Mat.svc.cs):

using System;

namespace WcfService
{
 public class Mat : IMat
 {
 public int Somar(string x, string y)
 {
 return Convert.ToInt32(x) + Convert.ToInt32(y);
 }
 }
}

Por fim o Web.config:

<?xml version="1.0"?>
<configuration>

 <appSettings>
 <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
 </appSettings>
 <system.web>
 <compilation debug="true" targetFramework="4.5.2" />
 <httpRuntime targetFramework="4.5.2"/>
 </system.web>
 <system.serviceModel>
 <behaviors>
 <serviceBehaviors>
 <behavior>
 <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
 <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
 <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
 <serviceDebug includeExceptionDetailInFaults="false"/>
 </behavior>
 </serviceBehaviors>
 </behaviors>
 <protocolMapping>
 <add binding="basicHttpsBinding" scheme="https" />
 </protocolMapping> 
 <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
 </system.serviceModel>
 <system.webServer>
 <modules runAllManagedModulesForAllRequests="true"/>
 <!-- To browse web app root directory during debugging, set the value below to true. Set to false before deployment to avoid disclosing web app folder information. -->
 <directoryBrowse enabled="true"/>
 </system.webServer>

</configuration>

Com isso, temos nosso serviço. Faça o build, realize alguns testes localmente. Por fim, publique. Vale lembrar que o serviço tem que ser publicado externamente. Não pode ficar no localhost ou ser acessado por IP. Por isso, neste exemplo, eu usei uma máquina no Azure para hostear o serviço. O serviço ficou com o seguinte endereço:

http://tiagowin20163976.cloudapp.net/WcfService/Mat.svc

PS: Vou tentar sempre manter está maquina ligada, assim, todo mundo pode usar meu serviço para testes!

Com o serviço criado e hospedado. É hora de voltarmos para o mundo do Dynamics! rs

Crie um plugin. Neste exemplo, criei um plugin para entidade Conta (account):

using Microsoft.Xrm.Sdk;
using System;
using System.Net;
using System.ServiceModel;

namespace Plugins
{
 public class AccountCreate : IPlugin
 {
 #region Secure/Unsecure Configuration Setup
 private string _secureConfig = null;
 private string _unsecureConfig = null;

 public AccountCreate(string unsecureConfig, string secureConfig)
 {
 _secureConfig = secureConfig;
 _unsecureConfig = unsecureConfig;
 }
 #endregion
 public void Execute(IServiceProvider serviceProvider)
 {
 // Extract the tracing service for use in debugging sandboxed plug - ins.
 // If you are not registering the plug-in in the sandbox, then you do
 // not have to add any tracing service related code.
 ITracingService tracingService =
 (ITracingService)serviceProvider.GetService(typeof(ITracingService));

 // Obtain the execution context from the service provider.
 IPluginExecutionContext context = (IPluginExecutionContext)
 serviceProvider.GetService(typeof(IPluginExecutionContext));

 // The InputParameters collection contains all the data passed in the message request.
 if (context.InputParameters.Contains("Target") &&
 context.InputParameters["Target"] is Entity)
 {
 // Obtain the target entity from the input parameters.
 Entity entity = (Entity)context.InputParameters["Target"];

 // Verify that the target entity represents an entity type you are expecting. 
 // For example, an account. If not, the plug-in was not registered correctly.
 if (entity.LogicalName != "account")
 return;

 // Obtain the organization service reference which you will need for
 // web service calls.
 IOrganizationServiceFactory serviceFactory =
 (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
 IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

 try
 {
 // Plug-in business logic goes here.
 var serviceURL = "http://tiagowin20163976.cloudapp.net/WcfService/Mat.svc";

 tracingService.Trace("- CallServiceByWebClientSOAP");
 tracingService.Trace("Somar('4','5')");

 using (var client = new WebClient())
 {
 var dataEnvelope = "<s:Envelope xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'>" +
 "<s:Body>" +
 "<<strong>Somar</strong> xmlns='http://tempuri.org/'>" +
 "<<strong>x</strong>><strong>4</strong></<strong>x</strong>>" +
 "<<strong>y</strong>><strong>5</strong></<strong>y</strong>>" +
 "</<strong>Somar</strong>>" +
 "</s:Body>" +
 "</s:Envelope>";

 client.Headers.Add("Content-Type", "text/xml;charset=utf-8");
 client.Headers.Add("SOAPAction", "\"http://tempuri.org/<strong>IMat/Somar</strong>\"");
 var response = client.UploadString(serviceURL, dataEnvelope);

 tracingService.Trace("Result: " + response);
 }
 }
 catch (FaultException<OrganizationServiceFault> ex)
 {
 throw new InvalidPluginExecutionException("An error occurred in MyPlug-in.", ex);
 }
 catch (Exception ex)
 {
 tracingService.Trace("MyPlugin: {0}", ex.ToString());
 throw;
 }
 }
 }
 }
}

Aqui, acredito que seja importante falar sobre o que está acontecendo dentro do “try” do plugin:

  • serviceUrl – Informamos a URL do serviço que estamos requisitando
  • client – Instanciamos e criamos um objeto da classe WebClient usando um bloco “using”
  • dataEnvelope – Criamos nosso envelope SOAP. Veja que é imprescindivel informar o método do serviço, bem como os parâmetros e seus respectivos valores (deixei isso em negrito!)
  • Header “content-type” – Informamos o conteúdo do pacote, neste caso apenas text/xml
  • Header “SOAPAction” – Informamos o formato do pacote, ele deve seguir o que a interface do serviço requisita para a implementação (deixei em negrito onde temos que trocar)
  • UploadString – Por fim, chamamos o serviço através de um upload do pacote SOAP para a URL/Serviço requisitada(o). A resposta é retornada em formato XML (devido ao formato que escolhemos anteriormente). E será esta:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><SomarResponse xmlns="http://tempuri.org/"><strong><SomarResult>9</SomarResult></strong></SomarResponse></s:Body></s:Envelope>

Assim, ao criar uma conta no CRM, quando observamos o log de execução do plugin, vemos:

Bom, é isso, espero ter ajudado! Irei escrever outro post de como fazer a mesma chamada, mas utilizando o que temos de melhor Binding e Contratos!

[]’s,

Tiago

Publicado em Dynamics 365, Dynamics CRM | Marcado com , , , , , | Deixe um comentário

Dynamics 365 – Business Process Error ao exportar uma solução

Olá pessoal,

Um erro bem estranho começou a ocorrer em uma solução que estamos trabalhando. Ao clicarmos em exportar a solução, e concluirmos todas as etapas (publicar as exportações, selecionar o tipo de solução gerenciada/não gerenciada e etc). Antes do CRM iniciar a exportação do arquivo .zip uma mensagem de erro é sempre retornada:

E o mais interessante, se clicamos em “Exibir detalhes técnicos” (Show Techinical Details). Nada é apresentado:

Após um pouco de troubleshooting, meu colega de trabalho Justin Marshall, encontrou o problema. Processos de negócio (Business Process Flows) não publicados, em “Rascunho” (Draft) impedem que a solução seja exportada.

Além disso, existe outro agravante, a Solução Padrão (Default Solution) do CRM, simplesmente não inicia o processo de exportação. Ou seja, qualquer Processo de Negócio em rascunho impedirá a exportação!

Ao meu ver é um bug. Sendo assim, criei um bug no Connect.

Entre por favor no Microsoft Connect, e me ajudem a promover este bug, votando! Assim ele poderá ser rapidamente resolvido pela Microsoft :)

[]’s,

Tiago

Publicado em Dynamics CRM | Marcado com , , | Deixe um comentário

Dynamics 365 – Panel de Navegação não exibe todos as áreas (Vendas, Marketing, Serviços)

Olá pessoal,

A grande vantagem de utilizar o Dynamics 365 online certamente é a facilidade e quantidade de inovações que nossas organizações recebem periodicamente. Porém, em alguns casos, somos “pegos de surpresa”.

Tive bastante dificuldade de como criar o título deste post. Continuo não achando ele completo. Mas, como escrever em poucas palavras que ao criar um novo trial do Dynamics, quando seleciono o cenário Vendas, ao abrir o CRM (com o mesmo usuário que criou a trial, ou seja, o Admin), não vejo as demais áreas básicas do CRM na barra de navegação, como o Marketing e Serviços? Bom abaixo o que aconteceu:

 

Apenas para mostrar o cenário que eu escolhi:

Bom, após um pouco de navegação no próprio e pesquisa, percebi que agora temos um novo botão “Promover a Administrador”, quando estamos na área de segurança do CRM (Configurações > Segurança):

A funcionalidade foi introduzida no Update 1 do CRM 2016. E de fato é muito útil para adicionar e remover direitos de administrador de um ou mais usuários. Porém, o que eu não espera que por padrão, mesmo o usuário que criou o trial do CRM não seja um Administrador do CRM automaticamente!

Se selecionarmos o usuário e clicarmos em “Promover para Administrator”:

Ao confirmar e ATUALIZAR a página do navegador:

Todas ás áreas irão aparecer!!!

Não está claro do por que por padrão este é o comportamento (pelo menos para mim). Mas, fazendo as etapas acima, teremos o mesmo comportamento que já estávamos acostumados.

[]’s,

Tiago

Publicado em Dynamics 365 | Marcado com , , , | Deixe um comentário

Dynamics 365 – Regras de Negócio (Business Rules)

Olá pessoal,

Estava lendo sobre algumas novidades do Dynamics 365 e me deparei que eu nunca havia escrito nada sobre Regras de Negócio*! :(

business_rules_1

*Regras de Negócio e Regras Empresariais são a mesma coisa, mas não vejo sentido para a tradução de “Business Rules” ser Regras Empresariais, assim, vou usar o termo Regras de Negócio!

Primeiro vamos ao propósito da funcionalidade…

Bom a ideia básica quando criaram as Regras de Negócio foi proporcionar ações no formulário do CRM sem a necessidade de programação (como JScripts e em alguns casos Plugins).

Muitas operações simples necessitavam de programadores para a execução delas. Além disso, por muitas vezes os programadores estão envolvidos em atividades mais complexas e com maior valor agregado do que simplesmente esconder um campo quando terminada ação ocorre. Com as Regras de Negócio podemos economizar uma boa quantidade de horas de desenvolvimento e ter um melhor aproveitamento dos profissionais do Dynamics.

Atualmente possuímos o seguinte conjunto de ações que podem ser executadas:

business_rules_2

  • Atribuir valor a campos
  • Limpar o valor dos campos
  • Definir como os campos como obrigatório/não obrigatório para o preenchimento
  • Exibir e ocultar campos
  • Habilitar e desabilitar campos para o preenchimento
  • Validar os valores informados e retornar mensagens de erro
  • Criar recomendações de preenchimento para enriquecer a experiência de uso

Como eu disse anteriormente a ideia é minimizar os esforços de desenvolvimento, por isso, a quantidade de funções não atenderá todos os cenários de automação/validação dos formulários, mas certamente é muito útil na maioria dos casos!

Lembrando como é composto uma Regra de Negócio no CRM:

Regra de Negócio > Condição (que por sua vez possui as Regras da condição irá desempenhar) > Ações

Bom, agora alguns exemplos para relacionar funcionalidades com a parte prática!

Assim como meu post sobre Processos de Negócio, as Regras de Negócio tiveram seu editor melhorado (visual e usualmente) desde o lançamento do Dynamics 365. Visualmente o mesmo conceito foi aplicado. Muito drag and drop e controles visuais.

Alguns pontos importantes antes de começarmos:

  • Regras de Negócio são vinculadas a entidades, assim, cada entidade pode ter suas regras de negócio, mas regra de negócio da entidade A não pode ser usada na entidade B;
  • As regras negócio podem ser aplicadas e um ou todos os formulários que a entidade possui;
  • Não podemos ter mais do que uma condição (condicional) na inicialização da regra de negócio. Outras condições podem ser inseridas após a de inicialização, mas apenas uma única para iniciar.
    • Por exemplo, queremos que caso o campo Número de Funcionários da entidade Cliente em Potencial for maior do que X algumas ações devem ser executadas. Mas também queremos que caso a Cidade do Cliente em Potencial seja “São Paulo” outras ações devem ser executadas. Para solucionar este cenário precisamos de duas regras de negócio independentes, afinal faz sentido não é, pois são regras diferentes, então devem estar separadas.
    • Agora, aproveitando o cenário anterior, quando o Número de Funcionários for mais do que X fazemos algumas ações, mas gostaríamos também de validar se a Cidade é “São Paulo”. Neste cenário, podemos criar a segunda condição, pois ela é executadas após a primeira;
    • Por fim, todo cenário pode ter mais do que uma solução, poderíamos chegar ao extremo de adicionar uma condição, porém, esta teria mais do que duas Regras

Um exemplo bem trivial de como usamos as regras de negócio. Vou criar para a entidade Ciente em Potencial.

Primeiramente, precisamos definir o que nossa condicional (regra de negócio) irá analisar para iniciar as ações. No meu exemplo, coloquei para quando o atributo “Número de Funcionários contiver valor”:

business_rules_3

Depois, inserimos nossas ações. Como todo fluxograma, podemos ter ações para o resultado positivo e também para o negativo. No exemplo, irei deixar o campo “Nome da Empresa” obrigatório para quando a condicional for positiva e não obrigatório para quando negativa:

business_rules_4

PS: Note que existe um quadro na parte debaixo da tela, as informações vão sendo adicionadas de acordo com no fluxo acima. Nas versões anteriores, as regras de negócio eram criadas apenas com a ideia deste quadro! Agora está tudo invertido, o visual vem em primeiro lugar! Muito mais fácil para quem não entende nada de lógica de programação!

Bom de agora em diante, podemos criar outras ações e condições a partir da condição inicial. Neste exemplo foi parar aqui. Então salve e ative o fluxo. Ao abrir o formulário no CRM, veremos algo assim:

business_rules_5

business_rules_6

Simples não? Antigamente precisaríamos de algumas linhas de JScript para isso…

Além da melhoria no editor citada anteriormente que foram lançadas com o Dynamics 365, a possibilidade de criar recomendações de preenchimento foram outra grande novidade. A ideia é alertar/sugerir alguns preenchimentos de campos baseado em alguma inteligência. Por exemplo, podemos sugerir que o País de uma Conta é os Estados Unidos quando o Estado informado for “WA” (Washington).

No exemplo a seguir vou criar a recomendação acima. Nossa condição verificará se o valor do campo “Estado” é “WA”, isso pode indicar que o país é os EUA (minha ideia foi bem básica, mas só para exemplificar mesmo).

business_rules_7

Bom, a condição sendo verdadeira quero fazer uma recomendação, para alertar que possivelmente o país é os EUA:

business_rules_8

Bom, agora é só salvar e publicar. Ao abrir uma conta e preencher o estado com o valor “WA”, veja o resultado:

business_rules_9

Bom por hoje é isso! Para maiores detalhes:

Create business rules and recommendations to apply logic in a form

[]’s,

Tiago

Publicado em Dynamics 365 | Marcado com , , , , , | 3 Comentários