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: , , , , ,

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