CRM 2013 Javascript Object Model - Control

by Pedro Azevedo 30. November 2014 22:04

Boas pessoal,

Hoje na sequência dos posts do object model do Javascript, desta vez vamos ver as opções que temos ao nível do controlo.

getAttribute

function getAttributeTest() {
	Xrm.Utility.alertDialog(Xrm.Page.getControl("subject").getAttribute().getValue());
}

getControlType

Valores possíveis de retorno:

Return Value

Description

standard

A Standard control.

iframe

An IFRAME control

lookup

A Lookup control.

optionset

An OptionSet control

subgrid

A subgrid control

webresource

A web resource control

notes

A Notes control

function getControlTypeTest() {
	Xrm.Utility.alertDialog(Xrm.Page.getControl("subject").getControlType());
}

getDisabled

function getDisabledTest() {
	Xrm.Utility.alertDialog("subject está com disabled a " + Xrm.Page.getControl("subject").getDisabled());
	Xrm.Utility.alertDialog("lastusedincampaign está com disabled a " + Xrm.Page.getControl("lastusedincampaign").getDisabled());
}

setDisabled

function setDisabledTest() {
	Xrm.Page.getControl("subject").setDisabled(true);
} 

getLabel

function getLabelTest() {
	Xrm.Utility.alertDialog(Xrm.Page.getControl("subject").getLabel());
}

setLabel

function setLabelTest() {
	Xrm.Page.getControl("subject").setLabel("Nova Label");
}

getName

function getNameTest() {
	Xrm.Utility.alertDialog(Xrm.Page.getControl("subject").getName());
}

getParent

Dá a secção onde está dentro.

function getParentTest() {
	Xrm.Utility.alertDialog(Xrm.Page.getControl("subject").getParent().getLabel ());
} 

getVisible

function getVisibleTest() {
	Xrm.Utility.alertDialog("O controlo subject está com visible a " + Xrm.Page.getControl("subject").getVisible());
}

setVisible

function setVisibleTest() {
	Xrm.Page.getControl("subject").setVisible(false);
}

setFocus

function setFocusTest() {
	Xrm.Page.getControl("subject").setFocus(true);
}

setNotification

function setNotificationTest() {
	Xrm.Page.getControl("subject").setNotification("Teste a função setNotification");
}

 

clearNotification

function clearNotificationTest() {
	Xrm.Page.getControl("subject").setNotification("Teste a função setNotification", "UMID");
	Xrm.Page.getControl("subject").clearNotification("UMID");
}

Até a próxima

Tags: , , ,

Disponibilização do CRM 2015 - Online e On-premise

by Pedro Azevedo 26. November 2014 01:28

 

Boas pessoal,

Já está disponível o acesso ao CRM 2015, quer na versão on-premise como nas novas instâncias de CRM Online. Para as organizações atuais de CRM Online está previsto para breve que se possa calendarizar o seu upgrade.

Para comprovar este lançamento podem ver na próxima imagem:

Esta foi uma nova instância de CRM Online.

Para as versões on-premise podemos realizar download do servidor aqui e do cliente para o Outlook aqui.

 

Até a próxima.

Tags: , ,

CRM 2013 Javascript Object Model - Lookup

by Pedro Azevedo 19. November 2014 19:50

Boas pessoal,

Continuando o conjunto de posts sobre a API de Javascript e também continuando o post de lookups no CRM 2013, hoje vou falar sobre o que temos na API de Javascript para interagir com os lookups. Este post já tinha sido feito para a versão 2011, por isso não vou voltar a falar das funções addCustomView, setDefaultView isso porque os métodos mantém os mesmos parâmetros e objetivos.

Ainda dentro dos métodos que existiam no CRM 2011, existe o getDefaultView, segue um exemplo:

function onload() {
        alert('default view->' + Xrm.Page.getControl('parentaccountid').getDefaultView());
}

Depois temos os métodos addCustomFilter, addPreSearch, removePreSearch, estes métodos com já foi dito aparecem na versão 2013. Para usar temos que fazer a combinação entre o addCustomerFilter e addPreSearch, para adicionamos um pré filtro temos que chamar o addPreSearch onde temos que adicionar um event handler que vai adicionar um filtro através do método addCustomerFilter:

function addPreFilter() {
	var city = Xrm.Page.getAttribute("address1_city").getValue();

	var filter ="<filter type='and'>" +
	             "<condition attribute='address1_city' operator='eq' value='" + city + "'/>" +
	             "</filter>";

	Xrm.Page.getControl("parentaccountid").addCustomFilter(filter);
}


function addPreSearchFilter() {
	Xrm.Page.getControl("parentaccountid").addPreSearch(addPreFilter);
}

Vejam as imagens em que na primeira não existe qualquer pré-filtro e na segunda aplicando o método anterior, ou seja, em vez de aparecer todos os registos consegue-se aplicar um filtro mais eficaz e com mais possibilidade de escolher sem ter que abrir uma nova janela.

 

Para se retirar este pré filtro temos que chamar o método removePreSearch e passar o event handler que passamos no método addPreSearch.

function removePreSearchFilter() {
	Xrm.Page.getControl("parentaccountid").removePreSearch(addPreFilter);
}

Este métodos podem ser de grande ajuda quando bem utilizados.

 

Até a próxima

Tags: , , , , ,

Participação como orador no evento ISCTE-IUL ACM Student Chapter

by Pedro Azevedo 14. November 2014 07:33

Boas pessoal,

É com grande prazer que anuncio que vou participar como orador do “ISCTE-IUL ACM Student Chapter”, podem ver mais detalhes desta iniciativa aqui. Aqui mais uma vez vou falar do Microsoft Dynamics CRM e já na versão 2015 J.

O título da sessão será “Microsoft Dynamics CRM – Mais que uma plataforma de CRM” e terá como tópicos a ressaltar:

  • Mercado CRM
  • O que é CRM?
  • Falar sobre Dynamics CRM
  • Integrações que se pode realizar

O site para o evento é este, por isso inscrevam-se e venham partilhar comigo o vosso conhecimento, no dia 17 de Dezembro pelas 19h30.

 

Até a próxima

 

Tags: , , , ,

Eventos antes do lançamento do Microsoft Dynamics CRM 2015

by Pedro Azevedo 11. November 2014 09:13

Boas pessoal,

Mais uma vez estou aqui a relatar eventos que acontecem sobre Microsoft Dynamics CRM. Infelizmente estes relatos são através do twitter com grande pena minha. Hoje reuni três eventos que aconteceram a bem pouco tempo e que culminaram com o Convergence 2014 em Barcelona, esses eventos foram:

  • CRMUGSUMMIT – organizado pelo CRMUG e que decorreu entre 14 e 17 de Outubro em St. Louis;
  • Fall Analyst Event (FAE) – que decorreu a 20 de Outubro em Washington
  • Convergence 2014 – que decorreu de 4 a 6 de Novembro em Barcelona

Para não repetir imagens vou colocar por tópicos e colocar imagens dos eventos. De um modo geral os assuntos andaram pelo Microsoft Dynamics 2015 e as próximas versões e depois sobre o Microsoft Marketing, Microsoft Social Listening e Parature.

O maior evento sem dúvida é o Convergence e vejam só estes números mais de 4,000 pessoas presentes, 700 potenciais clientes, 71 países, mas vamos a mais números.

Números

Querem justificar o porquê de apostar na plataforma Microsoft Dynamics? Vejam estes números impressionantes.

E como é que esta plataforma está a crescer? Muito e prevê-se que com estas novas funcionalidades venha a crescer ainda mais.

E agora especificamente sobre Microsoft Dynamic CRM. E os números não acabam:

É impressionante o número de sistemas que a Microsoft consegue integrar e por isso se torna uma das grandes vantagens.

Roadmap

E para não variar o roadmap mais atualizado:

Temos o Carina para o CRM, Hydra para o Social Listening, Spica para o Marketing e mais um update para o Parature.

CRM 2015

Um resumo das novidades que vêm no CRM 2015, hierarquias, melhoria na gestão de produtos, social insights, Power BI, Pesquisa e Ajuda, Mobilidade e voz.

Uma das novidades que é a pesquisa global e a possibilidade de colocarmos um help personalizado.

Mais integração feita, desta vez com o Windows Phone e com integração com a Cortana para comandos de voz. No Convergence foi feita uma demo, onde se via as atualização no Microsoft Band Cool.

Parature

Um resumo das novidades que estão a chegar com o Parature.

O Parature veio trazer a flexibilidade para integrar com qualquer coisa em qualquer lado. Incrível uma grande aquisição por parte da Microsoft.

Uma das grandes vantagens do Parature é ter a noção de um serviço self-service permitindo assim baixar o número de issues para a empresa e com isso baixar os custos. Um bom case disto é a Konami.

Não me canso de dizer vai ser um grande diferenciador, fantástica ferramenta.

Microsoft Social Listening

Alguns números deste serviço.

Vejam um dashboard que conseguimos tirar. Fantástico.

Sure Step

O sure step é uma metodologia que a Microsoft fornece aos seus parceiros para os ajudar a fazer migrações, deploy,  configurações e upgrade.

Vendas

Muito se fala no Marketing, Social, Serviço mas as Vendas não foram esquecidas. Temos algumas novidades e melhorias: templates Power BI; hierarquia de vendas; processos guiados; gestão dos produtos; Mobile e colaboração com o Marketing.

Esta nova funcionalidade permite ver de uma forma de árvore como é composto um cliente.

A gestão de produtos teve também uma grande melhoria, permitindo por exemplo extrair propriedades dos produtos, poder associar produtos de substituição e de complemento.

Marketing

Um resumo do que esta ferramenta pode melhorar a área de Marketing de uma empresa.

Este ecrã está mais que visto mas é bonito de se ver, com a configuração de uma campanha.

O email é uma das ferramentas de um profissional de Marketing e para isso esta ferramenta trouxe muitas funcionalidades, como um melhor editor, testes integrados A/B, conteúdo dinâmico, entre outros.

Um dos grandes diferenciadores é o seu poderoso editor de emails.

USD

O Unified Service Desk quie veio substituir o CCA (Customer Care Accelerator) vai-se tornar uma ótima ferramenta para gestão de processos de serviço com o cliente e para os call centers.

 

Developers

Algumas da novidades que temos do nosso lado.

Esta ferramenta permite passarmos dados de configuração de um ambiente para outro num único ficheiro zip. Claro que isto pode ser utilizado como uma ferramenta para migrar dados também.

Criação offline de soluções.

Integração do SDK com o nuget.

Uma ferramenta para atualizar soluções, podendo apagar atributos, relações, …

Cloud

Um dos temas mais falados foi a infraestrutura de Cloud que a Microsoft já possui, é algo monstruoso, existem muitas imagens com os detalhes como os data centers estão compostos, ficam aqui algumas dessas imagens:

A evolução.

A sua dispersão pelo mundo.

Vejam aqui os vários produtos que a Microsoft entrega pela Cloud.

A segurança dos dados é um dos grandes diferenciadores.

Então quais as vantagens de mudar para a Cloud?

 

Pessoal muita informação antes do lançamento do CRM 2015, por isso preparem-se para experimentar tudo.

 

Até a próxima.

 

Tags: , , , , , , ,

Criar um botão de cancelar para a Proposta

by Pedro Azevedo 7. November 2014 07:53

Boas pessoal,

O fórum ataca novamente Cool e foi colocada a seguinte questão. Quando temos uma proposta e criamos uma encomenda, a proposta fica num estado final como Ganha. Se por algum motivo a encomenda não se efetuar o Dynamics CRM permite o seu cancelamento:

A questão prende-se se quisermos cancelar a Proposta também e o que se constata é que não é possível realizar essa operação, apenas existe a opção eliminar:

Penso que a opção eliminar é muito drástica, e já agora ele não vai deixar porque existe a ligação com a encomenda. Então o objetivo de hoje é realizarmos um botão de cancelar. A nível funcional para algumas empresas não fará sentido eu mexer na proposta, já que se ela foi no fundo adjudicada então não devemos mudar o estado para sabermos que este negócio foi cancelado aquando da encomenda. Mas neste caso é apontado como uma incoerência de dados o que também se pode justificar.

Para começar nada melhor que verificarmos como é que mensagens temos para mudar o estado, todo o trabalho poderia ser feito com a mensagem SetStateRequest em que passamos qual o State e o Status que queremos que a proposta fique. Mas para podermos fechar a Proposta necessitamos de recorrer a mensagem CloseQuoteRequest, vejam o erro que ele dá se utilizarmos esta estratégia (SetStateRequest):

This message can not be used to set the state of quote to Closed. In order to set state of quote to Closed, use the CloseQuoteRequest message instead.

Para sermos brutos vamos tentar fechar a Proposta diretamente com o CloseQuoteRequest, como é de esperar ele não deixa pois temos que seguir o fluxo de estados estabelecido para a Proposta:

 E já agora vamos rever quais os valores que estão para cada um destes estados:

Estado

Valor

Razão do Estado

Valor

Ativo

1

Em progresso

Aberto

2

3

Fechado

3

Perdido

Cancelado

Revisto

5

6

7

Rascunho

0

Em Progresso

1

Ganha

2

Ganha

4

Vamos ver a mensagem que dá se mesmo assim insistirmos nesta estratégia, fechado através do CloseQuoteRequest estando a proposta num estado final:

The entity cannot be closed because it is not in the correct state.

Para colocarmos a Proposta em rascunho teremos que efetuar a seguinte chamada:

function SetStateRequest(state, status) {
     var recordId = Xrm.Page.data.entity.getId();

     var requestMain = ""
     requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
     requestMain += "  <s:Body>";
     requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
     requestMain += "      <request i:type=\"b:SetStateRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">";
     requestMain += "        <a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
     requestMain += "          <a:KeyValuePairOfstringanyType>";
     requestMain += "            <c:key>EntityMoniker</c:key>";
     requestMain += "            <c:value i:type=\"a:EntityReference\">";
     requestMain += "              <a:Id>" + recordId.replace('{', '').replace('}', '') + "</a:Id>";
     requestMain += "              <a:LogicalName>quote</a:LogicalName>";
     requestMain += "              <a:Name i:nil=\"true\" />";
     requestMain += "            </c:value>";
     requestMain += "          </a:KeyValuePairOfstringanyType>";
     requestMain += "          <a:KeyValuePairOfstringanyType>";
     requestMain += "            <c:key>State</c:key>";
     requestMain += "            <c:value i:type=\"a:OptionSetValue\">";
     requestMain += "              <a:Value>" + state + "</a:Value>";
     requestMain += "            </c:value>";
     requestMain += "          </a:KeyValuePairOfstringanyType>";
     requestMain += "          <a:KeyValuePairOfstringanyType>";
     requestMain += "            <c:key>Status</c:key>";
     requestMain += "            <c:value i:type=\"a:OptionSetValue\">";
     requestMain += "              <a:Value>" + status + "</a:Value>";
     requestMain += "            </c:value>";
     requestMain += "          </a:KeyValuePairOfstringanyType>";
     requestMain += "        </a:Parameters>";
     requestMain += "        <a:RequestId i:nil=\"true\" />";
     requestMain += "        <a:RequestName>SetState</a:RequestName>";
     requestMain += "      </request>";
     requestMain += "    </Execute>";
     requestMain += "  </s:Body>";
     requestMain += "</s:Envelope>";
     var req = new XMLHttpRequest();
     req.open("POST", _getServerUrl(), false)
     // Responses will return XML. It isn't possible to return JSON.
     req.setRequestHeader("Accept", "application/xml, text/xml, */*");
     req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
     req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
     var successCallback = null;
     var errorCallback = null;
     req.onreadystatechange = function () { ResponseOK(req); };
     req.send(requestMain);
 }

Para colocar em rascunho:

function putQuoteInDraft(){
     SetStateRequest(0, 1);
 }

Neste momento temos a Proposta em Rascunho, para verificarmos mais uma vez o fluxo de estados vamos tentar ativar a Proposta estando esta no estado final, mais uma vez recebemos uma mensagem de erro:

 The quote cannot be activated because it is not in draft state

Então temos que ativar a nossa Proposta com o seguinte código:

function putQuoteInActive(){
     SetStateRequest(1, 3);
 }

E com isto temos a nossa Proposta ativada e com a razão de estado em aberta. Agora sim podemos fechar a nossa Proposta e com a razão cancelado. Para isso efetuamos a seguinte chamada:

function CloseQuoteRequest(status, msg) {
     var recordId = Xrm.Page.data.entity.getId();

     var requestMain = ""
     requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
     requestMain += "  <s:Body>";
     requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
     requestMain += "      <request i:type=\"b:CloseQuoteRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">";
     requestMain += "        <a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
     requestMain += "          <a:KeyValuePairOfstringanyType>";
     requestMain += "            <c:key>QuoteClose</c:key>";
     requestMain += "            <c:value i:type=\"a:Entity\">";
     requestMain += "              <a:Attributes>";
     requestMain += "                <a:KeyValuePairOfstringanyType>";
     requestMain += "                  <c:key>quoteid</c:key>";
     requestMain += "                  <c:value i:type=\"a:EntityReference\">";
     requestMain += "                    <a:Id>" + recordId.replace('{', '').replace('}', '') + "</a:Id>";
     requestMain += "                    <a:LogicalName>quote</a:LogicalName>";
     requestMain += "                    <a:Name i:nil=\"true\" />";
     requestMain += "                  </c:value>";
     requestMain += "                </a:KeyValuePairOfstringanyType>";
     requestMain += "                <a:KeyValuePairOfstringanyType>";
     requestMain += "                  <c:key>subject</c:key>";
     requestMain += "                  <c:value i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">" + msg + "</c:value>";
     requestMain += "                </a:KeyValuePairOfstringanyType>";
     requestMain += "              </a:Attributes>";
     requestMain += "              <a:EntityState i:nil=\"true\" />";
     requestMain += "              <a:FormattedValues />";
     requestMain += "              <a:Id>00000000-0000-0000-0000-000000000000</a:Id>";
     requestMain += "              <a:LogicalName>quoteclose</a:LogicalName>";
     requestMain += "              <a:RelatedEntities />";
     requestMain += "            </c:value>";
     requestMain += "          </a:KeyValuePairOfstringanyType>";
     requestMain += "          <a:KeyValuePairOfstringanyType>";
     requestMain += "            <c:key>Status</c:key>";
     requestMain += "            <c:value i:type=\"a:OptionSetValue\">";
     requestMain += "              <a:Value>" + status + "</a:Value>";
     requestMain += "            </c:value>";
     requestMain += "          </a:KeyValuePairOfstringanyType>";
     requestMain += "        </a:Parameters>";
     requestMain += "        <a:RequestId i:nil=\"true\" />";
     requestMain += "        <a:RequestName>CloseQuote</a:RequestName>";
     requestMain += "      </request>";
     requestMain += "    </Execute>";
     requestMain += "  </s:Body>";
     requestMain += "</s:Envelope>";
     var req = new XMLHttpRequest();
     req.open("POST", _getServerUrl(), false)
     // Responses will return XML. It isn't possible to return JSON.
     req.setRequestHeader("Accept", "application/xml, text/xml, */*");
     req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
     req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
     var successCallback = null;
     var errorCallback = null;
     req.onreadystatechange = function () { ResponseOK(req); };
     req.send(requestMain);
 }

A chamada desta função é a seguinte:

function putQuoteInCancel(){
     CloseQuoteRequest(6, "Cancelado porque a encomenda foi cancelada");
 }

Uma das razões que o SetStateRequest não funciona é que o fecho da Proposta necessita de um objeto QuoteClose onde guarda por exemplo a mensagem que estamos a passar.

Agora que temos a sequência de chamada estabelecida só nos falta criamos o botão, aqui mais uma vez e sem dúvida nenhum vamos recorrer ao RibbonWorkBench já muito referenciado aqui no blog. Por isso vou encurtar os screens desta parte. Resumidamente temos que:

  • Adicionar um botão a barra de comandos, neste caso a tab que diz Form;
  • Dentro deste botão, podemos colocar um novo texto e um icon;
  • Mas o mais importante no botão é associarmos um comando;

·         Este comando é onde está configurado quais os passos a executar e quais os critérios de Display e Enable:


 

Como podem reparar tenho as várias chamadas aos métodos que refiro acima e pela ordem correta.

Vou só colocar as funções auxiliares que usei:

function _getServerUrl() {
     var OrgServicePath = "/XRMServices/2011/Organization.svc/web";
     var serverUrl = "";
     if (typeof GetGlobalContext == "function") {
          var context = GetGlobalContext();
          serverUrl = context.getServerUrl();
     }
     else {
          if (typeof Xrm.Page.context == "object") {
               serverUrl = Xrm.Page.context.getServerUrl();
          }
          else{ 
               throw new Error("Unable to access the server URL"); }
          }
          if (serverUrl.match(/\/$/)) {
             serverUrl = serverUrl.substring(0, serverUrl.length - 1);
     } 
     return serverUrl + OrgServicePath;
}

 function ResponseOK(req) {
       if (req.readyState == 4) {
       if (req.status == 200) {
       }
       else {
           alert('erro');
       }
   }
}

function refreshForm(){
     var recordId = Xrm.Page.data.entity.getId();
     Xrm.Utility.openEntityForm("quote", recordId);
}

 

Se tiverem alguma dúvida coloquem nos comentários ou vão até ao fórum.

 

 

Até a próxima

Tags: , , , , ,

Executar um FetchXML e exportar para CSV com Javascript

by Pedro Azevedo 19. October 2014 16:12

 

Boas pessoal,

Hoje um post muito rápido de como executar um FetchXML e exportar os resultados para um CSV, tudo isto em Javascript.

Para começar é possível executar um FetchXML através de uma requisição SOAP. Quando tenho este tipo de requisição recorro a biblioteca XrmServiceToolkit, no blog existem vários exemplos.

Para executar um FetchXml usamos a função Fetch:

function ExecuteFetch() {
    var fetchXml =
            "<fetch mapping='logical'>" +
               "<entity name='contact'>" +
                  "<attribute name='contactid' />" +
                  "<attribute name='firstname' />" +
                  "<attribute name='lastname' />" +
                  "<attribute name='middlename' />" +
                  "<filter>" +
                     "<condition attribute='parentcustomerid' operator='eq' value='" + Xrm.Page.data.entity.getId() + "' />" +
                  "</filter>" +
               "</entity>" +
            "</fetch>";

    var retrievedContacts = XrmServiceToolkit.Soap.Fetch(fetchXml);
}

Este código está preparado para correr dentro da entidade cliente, retorna todos os contactos desse cliente. A dificuldade a seguir é colocar os dados num ficheiro CSV e fazer download dele, existem várias estratégias:

var csvString = allValues.join("\n");

    var a  = document.createElement('a');
    a.href = 'data:attachment/csv,' + csvString;
    a.target = '_blank';
    a.download = 'myFile.csv';

    document.body.appendChild(a);
    a.click();

Vamos ver agora o código completo que inclui o tratamento dos dados retornados:

function ExecuteFetch() {
    var fetchXml =
            "<fetch mapping='logical'>" +
               "<entity name='contact'>" +
                  "<attribute name='contactid' />" +
                  "<attribute name='firstname' />" +
                  "<attribute name='lastname' />" +
                  "<attribute name='middlename' />" +
                  "<filter>" +
                     "<condition attribute='parentcustomerid' operator='eq' value='" + Xrm.Page.data.entity.getId() + "' />" +
                  "</filter>" +
               "</entity>" +
            "</fetch>";

    var retrievedContacts = XrmServiceToolkit.Soap.Fetch(fetchXml);

    var allValues = [];
    var strCol = "";
    var strVal = "";

    var cols = true;

     for (var i = 0; i < retrievedContacts.length; i++) {
      var attsValues = retrievedContacts[i].attributes;

      for (var att in attsValues) {
        strVal += attsValues[att].value + ";";

        if(cols){
          strCol += att + ";";
        }
      }

      if(cols){
        allValues.push(strCol);
        cols = false;
      }

      allValues.push(strVal);
      strVal = "";
    }

    var csvString = allValues.join("\n");

    var a  = document.createElement('a');
    a.href = 'data:attachment/csv,' + csvString;
    a.target = '_blank';
    a.download = 'myFile.csv';

    document.body.appendChild(a);
    a.click();
}

 

Até a próxima.

Tags: , , , ,

Como fazer debug dos Web Resources no browser

by Pedro Azevedo 17. October 2014 01:47

Boas pessoal,

Neste post vou continuar o assunto de realizar debug sobre as nossas soluções de CRM. No post anterior aprendemos a realizar debug sobre um plugin no CRM Online. Hoje vamos falar como realizar debug sobre o Javascript, como vamos utilizar as ferramentas de programador e vou tentar mostrar dos vários browsers, vamos dar um olhinho como é que obtemos os ids dos elementos que queremos trabalhar e aplicar um Javascript não customizado em cima.

Então como referi vamos usar essencialmente as ferramentas de programador de cada um dos browsers.

O firefox tem uma extensão muito conhecida chamada FireBug, por isso o primeiro passo é instalar esta extensão:

 Depois de instalar basta pressionar F12 ou utilizar um dos botões de atalho que vão aparecer no browser:

Este é o aspeto da nossa ferramenta que neste momento está presa no fundo da página mas podemos correr esta aplicação numa janela a parte. Na “Consola do Terminal” vamos ver todo o feedback sobre esta página, se por exemplo tivermos um console.log é nesta tab que vamos ver esse resultado, bem como se houver algum erro é aqui que vemos. Nesta tab ainda podermos executar código Javascript.

A tab do HTML permite-nos visualizar o DOM desta página e localizar elementos através do botão do retângulo com um cursor ao lado do símbolo do firebug, esta é uma das funcionalidades que mais uso pois permite-nos saber por exemplo o ID dos elementos HTML que usamos depois para aplicar um Javascript não customizado:

Como podemos comprovar eu carregando no icon para pesquisa de elementos, e selecionar um elemento posso ver todas as propriedades\eventos e com isso “sacar” o id desse elemento, que neste caso é o “form_pic_image”.

Na tab CSS posso visualizar todos os estilos que foram carregados nessa página.

No âmbito do assunto mais importante para este post temos a tab do Script que permite-nos ver todos os scripts que estão a ser carregados na página e mais importante permite-nos realizar debug sobre esses mesmos scripts:

Nesta tab temos a possibilidade de ver o código Javascript e conseguimos colocar variáveis de “Vigia” para podermos consultar o estado atual dessas mesmas variáveis. Ao selecionarmos na caixa de seleção podemos visualizar outros ficheiros de Javascript:

Aqui podemos visualizar os ficheiros dos nossos Recursos Web, sejam eles do tipo Javascript ou HTML, já que os ficheiros HTML podem também ter código Javascript. Escolhendo por exemplo o Recurso Web “new_putgridreadonly”:

Sobre este ficheiro podemos colocar breakpoints, basta para isso carregar no espaço em branco do lado direito no número da linha. Outra alternativa para o código Javascript parar é colocarmos a palavra reservada, no código Javascript:

debugger;

Se atualizarmos a página onde estamos vamos parar naquele sítio:

Como podemos comprovar pela seta amarela estou em debug e agora posso usar os icons de andar para a frente ou utilizar os mesmos shortcuts que usamos no Visual Studio F10 para continuar e F11 para entrar dentro da função, cuidado que o F5 aqui vai refrescar a página, neste caso é o F8. Como ainda podemos ver se eu colocar o cursor sobre a variável consigo ver o seu valor e posso ainda adicionar as variáveis de Vigia e ver mais pormenores.

Há mais uma tab que eu gostava de realçar que é a tab de Rede, uma das que mais utilizo e permite vermos o que está a ser carregado na página e por exemplo quanto tempo demorou a carregar, por exemplo para verificar o que uma chamada ODATA ou SOAP está a retornar é excelente:

Como podem ver na segunda imagem tenho uma chamada aos WebServices do CRM e onde posso ver o que foi enviado e a reposta que recebemos é muito útil.

Uma última coisa que não podemos esquecer que é a pesquisa que facilita muito as coisas, pois se tivermos a visualizar elementos pode-se colocar logo um id específico por exemplo e no Javascript pode-se pesquisar pelo nome de uma função.

Nos restantes browsers é tudo muito parecido, por exemplo no Chrome e no Opera as ferramentas de programador são muito parecidas e já vêm embutidas no browser, bastando no caso do chrome premir a tecla F12, no caso do Opera é diferente pois primeiro temos que ativar estas ferramentas e só depois é que as podemos invocar com Ctrl+Shift+I:

Os conceitos são exatamente iguais só que em tabs diferentes. Vamos ver especificamente o debug do Javascript:

As coisas só estão dispostas de maneira diferente mas o resultado vai ser igual, o breakpoint é sinalizado pelo bookmark azul. Quando atualizamos a página temos este ambiente:

No IE temos atualmente duas versões das ferramentas para o programador, uma antes do IE11 e com o IE11, estas ferramentas já vêm por defeito bastando premir o F12, mais uma vez as coisas são muito parecidas com os restantes browsers:

Uma coisa que acontece nesta ferramenta e que já não acontece com o IE11 (prometo brevemente colocar aqui imagens do IE11) é que nós temos que dizer que queremos começar a fazer debug ou nas capturas de rede que queremos começar a capturar, ou seja, ele por defeito não vai fazer nenhuma destas coisas, saltando diretamente para a tab “Script”:

Ao fazermos atualizarmos a página podermos realizar o debug ao Javascript, de referir que aqui o F5 já funciona. Como eu referi anteriormente é possível acrescentarmos um breakpoint escrevendo no código a palavra reservada debugger, mas para ele parar teremos primeiro que averiguar duas configurações em: Ferramentas -> Opções de Internet -> Avançadas e retirar o pisco desta duas configurações:

Como podem ver não é nada específico do Dynamics CRM vocês podem aplicar isto a qualquer aplicação Web. Em relação ao meu preferido não tenho, vario muitas vezes e quando não estou a conseguir ver num salta para outro que me dá outro tipo de feedback. Havia muito para falar mas foi uma breve introdução.

 

Até a próxima.

Tags: , , , ,

Gráficos no Microsoft Dynamics CRM

by Pedro Azevedo 12. October 2014 16:53

Boas pessoal,

Os fóruns de discussão têm servido de inspiração para posts que tenho realizado no blog e este não é exceção, numa thread recente foi colocada uma questão sobre os gráficos, a questão envolvia mexermos diretamente no XML e mesmo assim não consegui dar uma resposta válida, na minha opinião por limitação desta funcionalidade que apareceu no CRM 2011. Este será um post introdutório e em próximos posts explorarmos mais esta funcionalidade.

Como já referi a possibilidade de criarmos gráficos surgiu na versão 2011, onde nos possibilita de criarmos um gráfico com base num conjunto de registos, esta funcionalidade é muito poderosa pois permite-nos realizar drill-down, ver quais os registos que estão por base para aquele gráfico, mas vamos ver estes detalhes todos neste conjunto de posts.

Para começar vamos ver como acedemos a esta funcionalidade, numa lista qualquer temos uma barra lateral para abrirmos os gráficos:

Esta barra é customizável pela barra de comandos, em que podemos fixar a barra e desligar a barra de gráficos para esta entidade:

Para vermos os gráficos basta carregar sobre a barra para ela abrir:

 

Para algumas entidades já existem alguns gráficos pré-definidos, mas por exemplo para as entidades customizadas não vamos ver nenhum gráfico por defeito. De referir também que os dados que estamos a visualizar correspondem a vista que está selecionada e não para os registos todos.

Para além dos gráficos ainda podemos ver um mapa e já agora com o gráfico ancorado no topo:

 

Como opções sobre os gráficos e começando do lado esquerdo para o direito, temo um selector para escolher o relatório já gravados, depois nos ícones temos a opção de adicionar um novo gráfico, expandir ou fechar o gráfico, gravar alguma alteração e importar ou exportar o gráfico.

Neste post vamos entrar apenas na criação de gráficos:

Este é o aspecto da criação de um gráfico, temos a possibilidade de dar um nome a este gráfico, temos uma área para pré-visualizarmos os dados e depois uma área para configurarmos o gráfico:

 

 

Temos vários tipos de gráficos: colunas; barras; área; linha; circular e funil. Dentro dos três primeiros ainda temos mais três opções: “normal”, empilhado e empilhado a 100%.

Para além do tipo de gráfico podemos configurar se queremos aplicar regras para obter por x elementos superiores ou inferiores e temos por defeito as seguintes opções: 3, 5 ou um número personalizado. De referir também a última opção que vai limpar estas regras. Estas regras são úteis sobretudo quando temos muitos valores e para fixarmos um alvo concreto.

Estas opções estão disponibilizadas na configuração de uma série, onde podemos adicionar novas séries, para configurarmos temos que escolher o campo e depois qual a função de agregação que queremos aplicar:

Depois de selecionar o campo é disponibilizado opções de qual a operação de agregação que se quer aplicar, neste caso temos um campo de texto selecionado e por essa razão as operações numéricas não podem ser aplicadas. De notar a diferença entre a Contagem tudo e Não-Vazio em que a opção Não-Vazio não conta os elementos que não têm valor aplicado nesse campo.

Se escolhermos um campo do tipo data temos mais algumas opções:

 

Aqui podemos partir a data em partes do ano.

Por fim não se esqueçam de colocar uma descrição para o gráfico, dá sempre jeito para percebermos qual o seu objetivo ainda mais quando temos uma configuração importada, como vamos ver mais a frente o que vamos configurar no XML não será visível.

Depois de criarmos um gráfico, tal como acontece com as vistas não fica disponibilizado para toda a organização, por isso ficamos com outras opções sobre os gráficos “locais”:

Como podemos observar temos agora opção de editar, eliminar, atribuir e partilhar que não temos sobre um gráfico de sistema.

Vamos apenas ver um pequeno exemplo, onde queremos saber o total do orçamento por classificação por cada Oportunidade Potencial

Como podem ver estou ainda a configurar e já estou a pré-visualizar os resultados. Estes resultados são fidignos, vejam a visualização do gráfico para um utilizador:

Para criar um gráfico de sistema teremos que ir as customizações, aqui temos praticamente as mesmas opções:

Nas customizações para além de podermos criar novos gráficos podemos editar os gráficos existentes de sistema.

Este post teve como grande objetivo mostrar a configuração básica, como podem ver não temos muitas opções. Nos próximos para além da edição do XML vamos ver por exemplo onde podemos utilizar os gráficos.

 

PS: Para este post utilizei o Microsoft Dynamics CRM Online, mas os conceitos são idênticos para o CRM 2011, apenas com outra interface.

 

Até a próxima.

Tags: , , , ,

Auto Numeração no Microsoft Dynamics CRM

by Pedro Azevedo 2. October 2014 00:46

 Boas pessoal,

Esta semana vou falar sobre auto-numeração no Microsoft Dynamics CRM. Uma das dúvidas mais requisitadas nos fóruns do MSDN.

Esta funcionalidade vem por defeito no Dynamics CRM mas apenas para algumas entidades standard nomeadamente:

Sobre estas entidades podemos configurar alguns dados:

  • Prefixo – para ficar antes da numeração propriamente dita, é importante para quando esta numeração aparecer isolada nós consigamos dizer que aquela numeração corresponde neste caso aos contratos.
  • Número – Em que número começa
  • Comprimento do Sufixo – Termos um sufixo, onde temos a hipótese de termos 4, 5 ou 6 algarismos.

Podemos ainda ver um exemplo, de como fica esta numeração.

E se quisermos ter uma numeração por exemplo nas oportunidades, ou numa entidade nossa customizada? Existem algumas tools que ajudam neste trabalho por exemplo este. Mas eu penso que esta tool deixa de fazer sentido no Microsoft Dynamics CRM 2013, ainda mais a vinda do Fluxo de Trabalho síncrono onde temos um feedback imediato dessa mesma numeração. Como referência tenho sempre este artigo que tem uma implementação com o Dynamics CRM 2011. Eu no fundo vou refazer para o Dynamics CRM 2013, utilizando o CRM Online.

Para começar temos que criar uma entidade customizada para guardar a numeração:

Depois de criar a entidade vamos criar dois campos, um para o prefixo (Uma linha de texto) e outro para a numeração (Número Inteiro):

De seguida fui customizar o formulário desta entidade para podermos colocar os dois campos acima, a seguir fui então adicionar registos nesta entidade onde configurei a numeração para a entidade Lead (Oportunidade Potencial). Se quiséssemos mais entidades bastava adicionar várias linhas a esta entidade:

A seguir vamos para a entidade que queremos adicionar a numeração automática, no meu caso a Lead, onde vou uma relação (N:1) para a entidade CustomAutoNumber e um campo que vai guardar a numeração, este campo vou colocar do tipo “Uma Linha de Texto” para poder colocar o sufixo.

De seguida vamos customizar o formulário da Lead, neste caso vou acrescentar dois campos, o lookup para entidade CustoAutoNumber que é o campo correspondente a criação da relação e o campo que vai guardar a numeração. De referir que no vosso caso o melhor é não acrescentar a interface o campo lookup, só vou colocar para vocês verem o que acontece.

Falta-nos o último passo que é a criação do Fluxo de Trabalho sobre a entidade Lead:

A nota mais importante aqui é a checkbox “Executar este fluxo de trabalho em segundo plano”, pois ao desmarcarmos esta checkbox estamos a dizer que este Fluxo de Trabalho vai correr imediatamente.

Na configuração do Fluxo de Trabalho não há muito a fazer, por isso vamos avançar para a configuração dos passos, o primeiro passo a ser configurado é relacionar o registo que vamos criar com o registo da entidade CustomAutoNumber que está reservado para a Lead:

Na definição de propriedades vamos escolher automaticamente o registo da entidade CustomAutoNumber:

De seguida vamos querer incrementar o número do registo associado a Lead da entidade CustomAutoNumber:

Na definição de propriedades vamos dizer que queremos incrementar o campo numeracao:

Por fim vamos atualizar a Lead com a numeração:

Nas propriedades nada mais simples vai-se dizer que o campo da Lead que vai ficar com a numeração é a composição entre o prefixo e o número em que a entidade vai:

Para quem não está tão familiarizado com os Fluxos de Trabalho, neste caso temos que escolher o “Prefixo” e fazer “Adicionar” e “OK”, depois para colocarmos “-” escrevemos diretamente na caixa de texto e depois escolhemos o campo “numeração, fazemos novamente “Adicionar” e “OK”. Vejam aqui o resultado:

Como podem ver o campo do lookup está preenchido e a numeração incrementada. Missão cumprida :D

 

Até a próxima.

Tags: , ,

About

Muito bem casado, Pai babado e um gosto muito grande pela tecnologia.

Tenho um lema "Sharing is Learning"

Mais aqui -> http://www.psazevedo.com

Month List