CRM 2013 Javascript Object Model - Data

by Pedro Azevedo 8. August 2014 02:34

 Boas pessoal,

Continuando a “saga” dos métodos Javascript vamos agora ver os métodos Xrm.Page.data.

Xrm.Page.data.getIsValid()

function getIsValidTest() {
                Xrm.Utility.alertDialog(Xrm.Page.data.getIsValid());
}

Xrm.Page.data.refresh(save).then(successCallback, errorCallback)

Esta função refresh recebe um booleano para dizer se queremos que ele salve depois do formulário ser refrescado. Depois existe a possibilidade de passar funções quando houver sucesso ou insucesso na execução da função.

function refreshTest()
{
                Xrm.Page.data.refresh(false).then(function() {
                                               Xrm.Utility.alertDialog("Sucesso no refrescamento");
                               },
                               function() {
                                               Xrm.Utility.alertDialog("Erro no refrescamento");
                });
}

Esta caixa aparece porque como estou a colocar o evento no onchange de um campo do CRM, ele verifica que estamos a querer refrescar a página sem guardarmos as alterações.

Xrm.Page.data.save().then(successCallback, errorCallback)

function saveTest() {
                Xrm.Page.data.save().then(function() {
                                               Xrm.Utility.alertDialog("Sucesso no save");
                               },
                               function() {
                                               Xrm.Utility.alertDialog("Erro no save");
                });
}

As duas últimas funções são muito rápidas isto porque o refrescamento é só dos dados e não da página inteira.

 

Até a próxima.

Tags: , , , , ,

WPC 2014

by Pedro Azevedo 23. July 2014 23:09

Boas pessoal,

Mais um evento da Microsoft que se falou do Microsoft Dynamics CRM, desta vez foi o WPC – World Partner Conference 2014. Um evento dedicado para os parceiros da Microsoft. O site do evento podem encontrar aqui.

Acompanhei o evento principalmente pelo twitter, mas no site estão disponibilizados vários vídeos para rever o evento. O evento decorreu entre os dias 13 e 17 de Julho.

Foram dados alguns dados por exemplo sabe-se que neste momento o Microsoft Dynamics CRM tem cerca de 4,25 milhões de utilizadores e que a receita tem vindo a aumentar a 40 trimestres seguidos mais que dois dígitos:

Não podia falta o belo do roadmap, agora com novidades para o Outono e em todos os pilares do CRM. Depois em futuros posts falarei mal se saiba mais alguma coisa.

Ficou bem presente que o MS Dynamics CRM está entre as tecnologias que mais a Microsoft aposta, vejam esta declaração “CRM Online will be a big bet in a significant way. It will stand out more uniquely than in prior years.  Not that ERP isn't important, but CRM Online will be exaggerated in its intention” do Phil Sorgen (Microsoft "channel chief").

 

Fiquem ligados que brevemente surgirão mais novidades.

 

Até a próxima.

Tags: , , , ,

CRM 2013 - UR3

by Pedro Azevedo 17. July 2014 03:06

 

Boas pessoal,

Foi disponibilizado o UR3 do CRM 2013 e que podem transferir aqui. Para mais informações podem ver aqui, pois este rollup contém mais de 200 correções.

Este rollup é recomendado onde não foi aplicado o SP1 do Microsoft Dynamics 2013, para quem tem esta versão instalada vamos ter que esperar por um rollup específico para esta versão, o que será algo como UR1 para o SP1.

Até a próxima.

Tags: , , ,

CRM 2013 Javascript Object Model - Data.Entity

by Pedro Azevedo 9. July 2014 02:24

Boas pessoal,

Mais um capítulo dos métodos de Javascript desta vez sobre o Xrm.Page.data.entity

Xrm.Page.data.entity.addOnSave([function reference])

function showMessage() {
                Xrm.Utility.alertDialog("Função do evento save");
}

 

function addOnSaveTest() {
                Xrm.Page.data.entity.addOnSave(showMessage);
}

Xrm.Page.data.entity.removeOnSave([function reference])

function removeOnSaveTest() {
                Xrm.Page.data.entity.removeOnSave(showMessage);
}

 

Xrm.Page.data.entity.getDataXml()

function getDataXmlTest() {
                Xrm.Page.data.entity.addOnSave(function(){
                               Xrm.Utility.alertDialog(Xrm.Page.data.entity.getDataXml());
                });
}

Neste XML só aparecem os campos que eu alterei e aquelas que serão enviadas para o registo ser guardado.

Xrm.Page.data.entity.getEntityName()

function getEntityNameTest() {
                Xrm.Utility.alertDialog(Xrm.Page.data.entity.getEntityName());
}

Xrm.Page.data.entity.getId()

function getIdTest() {
                Xrm.Utility.alertDialog(Xrm.Page.data.entity.getId())
}

Xrm.Page.data.entity.getIsDirty()

function getIsDirtyTest() {
                Xrm.Utility.alertDialog(Xrm.Page.data.entity.getIsDirty());
}

 

O primeiro teste foi no evento onload do formulário e como se está a espera o formulário não está dirty. O segundo é invocado após alteração do campo como seria de esperar o CRM diz que o formulário está dirty.

Xrm.Page.data.entity.getPrimaryAttributeValue()

function getPrimaryAttributeValueTest() {
                Xrm.Utility.alertDialog(Xrm.Page.data.entity.getPrimaryAttributeValue());
}

Xrm.Page.data.entity.save( null | "saveandclose" |"saveandnew" )

Aqui é definido o comportamento da função save, se passarmos null ele deve simular o gravar normal, o saveandclose e o saveandnew dizem tudo destas duas opções.

function saveTest() {
                Xrm.Page.data.entity.save();

                Xrm.Page.data.entity.save("saveandclose");

                Xrm.Page.data.entity.save("saveandnew");
}

Já tínhamos visto a função Xrm.Page.data.save() a diferença é que esta corre assincronamente enquanto o save dentro da entity é síncrono e com opções diferentes.

 

Até a próxima.

Tags: , , , , , ,

Acordo entre a Microsoft e a Salesforce

by Pedro Azevedo 6. July 2014 03:05

 

Boas pessoal,

Hoje vou falar de um assunto sensível e muito tem abalado a comunidade. O acordo efetuado com o principal rival do Microsoft Dynamics CRM, a Salesforce.

Para quem não sabe Marc Benioff, CEO da Salesforce foi sempre um anti-Microsoft e nunca se inibi-o de o dizer. Agora e com o Satya Nadella (para os mais distraídos, quem veio substituir o Ballmer) fizeram um acordo de cooperação.

O acordo abrange várias áreas mas eu vou-me concentrar apenas na parte respeitante ao Dynamics CRM. Quando se apresentam as vantagens do Microsoft Dynamics CRM para o Salesforce existe uma grande vantagem que é a facilidade de integração com o Microsoft Office, que tem dois grandes produtos que são largamente utilizados: Outlook e Excel (inclui o Power BI). Para além do Office “on-premise”, ainda existe acordo para a integração dentro do Office 365 (que vai permitir usar o OneDrive e o Sharepoint).

Para ajudar a festa este acordo vai permitir que o Salesforce1 execute nos sistemas operativos Windows (incluindo o Windows Phone), outra força que os parceiros da Microsoft elencavam como grande vantagem.

Bom acho que não havia mais nenhum anel para “vender”. Estou a ser injusto falta ainda a parte servidora (Exchange e SQL Server), mas como a Salesforce não tem uma implementação on-premise não lhe interessava estes produtos.

Eu não entendo o porquê deste acordo e o CEO da Microsoft também não disse grande coisa, ainda por cima numa fase que o Microsoft Dynamics CRM apresentava um crescimento muito grande e apresentando soluções superiores a da Salesforce.

 

Qual é a vossa opinião?

 

Até a próxima.

Tags: , , ,

CRM 2013 Javascript Object Model - Coleções

by Pedro Azevedo 30. June 2014 21:47

Boas pessoal,

Neste post mais uma vez sobre o object model do Javascript para o Dynamics CRM 2013, iremos debruçar sobre collections. Antes virmos os métodos que nos permitem aceder as várias colecções vamos ver três métodos que nos vão ajudar a trabalhar sobre as colecções:

Xrm.Page.ui.controls.forEach(delegate function(control, index))

Aplica uma acção numa função delegate a cada objecto numa colecção

Xrm.Page.ui.controls.get([String][Number][delegate function(attribute, index)])

Extrair um ou mais objectos da colecção

Xrm.Page.ui.controls.getLength()

Retorna o número de itens de uma colecção

Fica aqui uma pequena referência mas eu vou aplicar várias vezes estes métodos com as várias assinaturas. Principalmente no primeiro exemplo que vou percorrer todos este métodos.

Xrm.Page.data.entity.attributes

function attributesAllTest() {

                    Xrm.Utility.alertDialog("Esta entidade tem " + Xrm.Page.data.entity.attributes.getLength() + " entidades no formulário");

                   

                    var firstControlById = Xrm.Page.data.entity.attributes.get(0);

                    var firstControlByName = Xrm.Page.data.entity.attributes.get(firstControlById.getName());

                   

                    var booleanAtts = Xrm.Page.data.entity.attributes.get(isBoolean);

                    var message = "";

                    for (var i in booleanAtts) {

                                         message += "- " + booleanAtts[i].getName() + "\n";

                    }

                    Xrm.Utility.alertDialog(message);

                   

                    message = "";

                    Xrm.Page.data.entity.attributes.forEach(function (attribute, index) {

                                         message += attribute.getName() + "(" + attribute.getAttributeType() + ") \n";

                    });

                    Xrm.Utility.alertDialog(message);

}

 

function isBoolean(att, index) {

                    return att.getAttributeType() == "boolean";

}

 

 

 

Xrm.Page.ui.controls

function controlsTest() {

                    var message = "";

                    Xrm.Page.ui.controls.forEach(function (control, index) {

                                         message += control.getName() + "(" + control.getControlType() + ") \n";

                    });

                   

                    Xrm.Utility.alertDialog(message);

}

Xrm.Page.ui.formSelector.items

Vou abordar esta colecção aquando Xrm.Page.ui.

Xrm.Page.ui.navigation.items

Vou abordar esta colecção aquando Xrm.Page.ui.

Xrm.Page.ui.tabs

function tabsTest() {

                    var message = "";

                    Xrm.Page.ui.tabs.forEach(function (tab, index) {

                                         message += "A tab " + tab.getName() + " está " + tab.getDisplayState() + "\n";

                    });

                   

                    Xrm.Utility.alertDialog(message);

}

 

 

Xrm.Page.getAttribute("…").controls

function attControlsTest() {

                    var message = "";

                    Xrm.Page.getAttribute("subject").controls.forEach(function (control, index) {

                                         message += control.getName() + "(" + control.getControlType() + ") \n";

                    });

                   

                    Xrm.Utility.alertDialog(message);

}

 

Xrm.Page.ui.tabs.get("…").sections

function sectionsTest() {

                    var message = "";

                    Xrm.Page.ui.tabs.get("Summary").sections.forEach(function (section, index) {

                                         message += "A secção " + section.getName() + "tem a seguinte label " + section.getLabel() + " \n";

                    });

                   

                    Xrm.Utility.alertDialog(message);

}

 Xrm.Page.ui.tabs.get("…").sections.get("…").controls

function sectionControlsTest() {

                    var message = "";

                    Xrm.Page.ui.tabs.get("Summary").sections.get("Contact").controls.forEach(function (control, index) {

                                         message += control.getName() + "(" + control.getControlType() + ") \n";

                    });

                   

                    Xrm.Utility.alertDialog(message);

}

 

Até a próxima.

Tags: , , ,

Como fazer debug de um plugin no CRM Online

by Pedro Azevedo 11. June 2014 06:14

Boas pessoal,

Hoje vou mostrar como podemos efectuar debug num plugin do CRM Online, como vão ver não é um debug em real time mas mesmo assim permite-nos ver como é que os dados fluem no nosso plugin. Basicamente é capturado todos os dados num ficheiro e vamos carregar esse ficheiro na ferramenta “Plugin Registration”. Vou já mostrar com a nova interface da ferramenta que apareceu com o SP1 do Microsoft Dynamics CRM Online. É bom relembrar que apenas temos esta opção devido ao facto de a única maneira que temos para fazer deploy dos plugins é no modo sandbox.

Tendo em conta que já temos um plugin registado e queremos realizar o debug deste plugin através da ferramenta “Plugin Registration”. Esta ferramenta está na instalação do SDK, para ter acesso a nova interface relembro que têm que fazer no mínimo o download do SDK do SP1. Depois de instalar tem acesso aplicação nesta pasta …\SDK\Tools\PluginRegistration\PluginRegistration.exe.

Depois de iniciar aplicação terá este aspecto:

 Aqui carregamos no botão “CREATE NEW CONNECTION”, depois disto teremos que introduzir as nossas credenciais:

 

Depois da autenticação é listado a lista de Plugins registados e seleccionamos o plugin sobre o qual queremos realizar o debug e carregamos em “Install Profile”:

 

Depois do profile instalado irá aparecer um nó com o “Plugin-in Profiler”, sobre o passo registado dizemos que queremos começar o profile, carregando no botão “Start Profiling”:

 

Vai aparecer uma janela de settings que podemos aceitar os por defeito:

 

O nó do passo altera-se como vamos ver mais adiante, agora vamos até a nossa instância de CRM Online e vamos despoletar o nosso plugin, ao correr vai aparecer uma janela com o título “Erro de Processo de Negócio” onde vamos fazer download do ficheiro:

De seguida vamos ao nosso Visual Studio e vamos fazer “attach” ao processo da ferramenta “Plugin Registration”:

 

E colocamos um breakpoint onde vamos querer parar e fazer debug. Voltando a ferramenta e voltando ao passo do plugin, verificamos que o passo está marcado como “Profiled”, e seleccionamos o “Debug”:

 

Na janela a seguir vamos então seleccionar o ficheiro que fizemos download anteriormente e colocamos no campo: “Profile Location” e vamos também dizer onde está a DLL respeitante ao nosso plugin, depois de carregar o plugin temos a opção de escolhermos a classe responsável pelo plugin. Ao seleccionarmos o botão “Start Execution” ele vai correr o plugin com base no ficheiro de profile que disponibilizamos e podemos fazer step by step com os dados que inserimos:

 

 

 Assim vimos como podemos realizar debug de um plugin no CRM Online. Não é o ideal mas dá uma tremenda ajuda.

 

Até a próxima.

Tags: , , , , ,

CRM 2013 - SP1

by Pedro Azevedo 7. June 2014 01:00

 

Boas Pessoal,

Estou aqui para dizer que já temos acesso a uma nova versão. As organizações online em princípio já têm esta versão, denominada como Spring 2014, para os ambientes on-premise podem fazer download aquieste update é conhecido como SP1, no site referido pode-se ver as correcções efetuadas.

Por isso pessoal toca a ir experimentar as novas novidades que nos trás este novo update. Antes de atualizar não deixem de olhar este site.

Vejam aqui o novo ecrã nas definições para a Gestão de Serviço:

 

Até a próxima.

Tags: , , , , ,

CRM 2013 Javascript Object Model - Contexto

by Pedro Azevedo 28. May 2014 20:04

Boas pessoal,

Chegou a vez de falarmos sobre o Xrm.Page.context. Aqui temos que obter primeiro o objecto de contexto.

context.client.getClient()

Valores de retorno possíveis deste método:

Cliente

Valor

Browser

Web

Outlook

Outlook

Mobile

Mobile

function getClientTest() {

                Xrm.Utility.alertDialog(Xrm.Page.context.client.getClient());

}

De referir que este método veio tornar o método isOutlookClient obsoleto.

 

context.client.getClientState()

Valores de retorno possíveis deste método:

Cliente

Valor

Web, Outlook, Mobile

Online

Outlook, Mobile

Offline

function getClientStateTest() {

                Xrm.Utility.alertDialog(Xrm.Page.context.client.getClientState());

}

Tal como o método anterior este método veio tornar obsoleto o método isOutlookOnline.

 

context.getClientUrl()

Valores possíveis no retorno:

Cliente

Valor

Microsoft Dynamics CRM (on-premises)

http(s)://server/org

Microsoft Dynamics CRM Online

https://org.crm.dynamics.com

Microsoft Dynamics CRM for Outlook with Offline Access when offline

http://localhost:2525

Na documentação o método getServerURL não vem documentado mas ainda funciona apesar de estar obsoleto deve-se usar sempre o getClientUrl.

 

context.getCurrentTheme()

Este método serve essencialmente para podermos customizar os nossos Recursos Web mediante o theme do Outlook. Valores possíveis de retorno para este método:

Valor

Theme

default

Microsoft Dynamics CRM web application

Office12Blue

Microsoft Dynamics CRM for Outlook 2007 or 2010 Blue Theme

Office14Silver

Microsoft Dynamics CRM for Outlook 2007 or 2010 Silver or Black Theme

function getCurrentThemeTest() {

                Xrm.Utility.alertDialog(Xrm.Page.context.getCurrentTheme());

}

Devem ter atenção que alguns destes métodos não funcionam por exemplo nos tablets por isso os métodos acima passam a ser essenciais. Por exemplo este método em específico não funciona nos tablets.

 

context.getOrgLcid()

Esta função permite devolver a linguagem base da organização.

 

function getOrgLcidTest() {

                Xrm.Utility.alertDialog(Xrm.Page.context.getOrgLcid());

}

Este valor representa o Português de Portugal. Já agora o Português do Brazil é o 1046.

 

context.getOrgUniqueName()

function getOrgUniqueNameTest() {

                Xrm.Utility.alertDialog(Xrm.Page.context.getOrgUniqueName());

}

context.getQueryStringParameters()

Este método serve para ler os query strings passados ao formulário para além dos parâmetros que o CRM envia pode-se passar parâmetros customizados, por exemplo usando a função que já testamos a openEntityForm.

 

function getQueryStringParametersTest() {

                var params = Xrm.Page.context.getQueryStringParameters();

                for(var par in params) {

                               Xrm.Utility.alertDialog("QueryString:" + par + " com o valor " + params[par]);

                }

}

 

 

context.getUserId()
function getUserIdTest() {

                Xrm.Utility.alertDialog(Xrm.Page.context.getUserId());

}

 

context.getUserId() 
function getUserLcidTest() {

                Xrm.Utility.alertDialog(Xrm.Page.context.getUserLcid());

}

 

context.getUserName()
Esta função retorna o nome do utilizador.
function getUserNameTest() {

                    Xrm.Utility.alertDialog(Xrm.Page.context.getUserName());

}

 

context.getUserRoles()

function getUserRolesTest() {

                var roles = Xrm.Page.context.getUserRoles();

                for(var role in roles) {

                               Xrm.Utility.alertDialog("Role ID:" + role);

                }

}

context.prependOrgName(sPath)

 

function prependOrgNameTest() {

Xrm.Utility.alertDialog(getClientUrlTest() + Xrm.Page.context.prependOrgName("/XRMServices/2011/OrganizationData.svc/"));

}

 

Neste contexto ainda tenho a referir que o método getAuthenticationHeader foi retirado definitivamente, este tinha permanecido por causa de compatibilidades com o CRM 4.0.

 

Até a próxima

 

Tags: , , , , , , ,

Plugin para intervir na operações especiais - Ganho e Perda da Oportunidade

by Pedro Azevedo 18. May 2014 19:21

Boas pessoal,

Na continuação deste post vou aqui relatar como realizar o dito plugin, um plugin que interfere em operações especiais. Neste caso vai-se referenciar as operações na entidade Oportunidade que permite marcar um registo como Ganho ou Perdido. Imaginamos que se quer verificar se um determinado campo está preenchido, neste caso quero obrigar que o utilizador preencha a descrição antes de fechar a oportunidade.

O código é o seguinte:

public class CloseOpportunity : IPlugin {
	public void Execute(IServiceProvider serviceProvider) {
		ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
		IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

		if (context.InputParameters.Contains("OpportunityClose") && context.InputParameters["OpportunityClose"] is Entity) {
			Guid oppId = ((EntityReference)((Entity)context.InputParameters["OpportunityClose"]).Attributes["opportunityid"]).Id;

			IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
			IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

			Entity opportunity = service.Retrieve("opportunity", oppId, new Xrm.Sdk.Query.ColumnSet(true));
			if (!opportunity.Contains("description") || string.IsNullOrEmpty(opportunity["description"].ToString()))
				throw new InvalidPluginExecutionException("Para fechar a Oportunidade terá que preencher a descrição");
		}
	}
}

O normal em plugins é esperarmos a entidade no parâmetro “Target” neste caso, esta informação está no parâmetro “OpportunityClose”, ou seja, vem na forma do objecto final, pois quando fechamos uma Oportunidade temos que preencher informações, do estado, receita real, data de fecho e caso seja perdida qual o concorrente que ganhou.

Para verificarmos as propriedades da Oportunidade teremos que obter e no objecto “OpportunityClose” tem o ID da Oportunidade e é com esse ID que vamos obter a Oportunidade relacionada.

No código ainda se pode ressalvar como cancelamos a operação, com recurso a excepção “InvalidPluginExecutionException”, a mensagem que colocamos na excepção é a mensagem que vai aparecer ao utilizador.

Depois do código completo temos que registar o plugin com as seguintes configurações:

  •         Mensagem: Win ou Lose
  •         Entidade Primária: Opportunity
  •         Entidade Secundária: Nenhuma

E registamos no event Pre-Operation para que não seja gravado na BD.

Vamos ver diretamente no Plugin Registration como fica, depois de realizarmos uma ligação, podemos registar o nosso assembly:

 Após selecionarmos a opção "Register New Assembly" aparecerá um formulário para colocarmos o caminho do assembly que contém o nosso plugin e escolhemos qual o Plugin que queremos registar, neste caso estou a selecionar o Plugin acima:

 Se tudo correr bem obtém-se a seguinte mensagem:

Irá aparecer um novo nó com o assembly que se acabou de criar e sobre este vamos adicionar um "passo" (Register New Step):

No formulário a seguir configuramos em que mensagem queremos nos registar, qual a entidade primária, em que fase do pipeline e o modo de execução:

Com isto temos o nosso Plugin registado e pronto a funcionar.

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