RSS

Monthly Archives: April 2013

Get the Created Records When Lead is Qualified Using Plug-in

Introduction

This blog explains how to register a plug-in in “QualifyLead” message and get the created record when lead is qualified.

Background

Let in some requirement, when a lead is qualified then if you need some custom logic to work then in this scenario you can register you plug-in on the “QualifyLead” message and “Post Operation” Stage.

Code

We can easily get the newly created account, contact and opportunity records and can do any required changes in them.

Codes that will be used inside the plug-in :

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

// Obtain the organization service reference.
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

// Getting the service from the Organisation Service.
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

// Get the qualified lead.
EntityReference leadid = (EntityReference)context.InputParameters["LeadId"];
Entity lead = service.Retrieve("lead", leadid.Id, new ColumnSet(true));

foreach (EntityReference created in (IEnumerable<object>)context.OutputParameters["CreatedEntities"])
{
    //Check if Account record is created when lead qualified.
    if (created.LogicalName == "account")
    {
        Entity account = service.Retrieve("account", created.Id, new ColumnSet(true));
    }
    
    //Check if Contact record is created when lead qualified.
    if (created.LogicalName == "contact")
    {
        Entity contact = service.Retrieve("contact", created.Id, new ColumnSet(true));
    }

    //Check if Opportunity record is created when lead qualified.
    if (created.LogicalName == "opportunity")
    {
        Entity opportunity = service.Retrieve("opportunity", created.Id, new ColumnSet(true));
    }
}

To update any of the created account, contact and opportunity we can use the retrieved data as per below :

Entity entAccount = new Entity("account");
entAccount["accountid"] = account.Attributes["accountid"];
entAccount["name"] = "Test Account Name";
service.Update(entAccount);

By Abhisek Sriramka
Senior Software Engineer @Team DynamicsCRM.
Mindfire Solutions

 
3 Comments

Posted by on April 29, 2013 in CRM Plug-in

 

Tags: , , , , , , , , , , , , , , ,

Customization of CRM Application on Basis Of Security Role

Introduction

This article is about the change in CRM Application page made as per the role.

Requirement

There was a need which was made in a project to show only those views, buttons and links which are relevant for a particular role. Here are few steps which I took to customize the CRM as per Role.

Changes which are need to be made

  1. Change in the security role
  2. Customization of all the CRM form (Home page, Form Data Entry page, Form grid page)
  3. Changing the views according to the roles

Change in the security role

Change in the security role is made in the Setting → Administration → Security Role.

The privilege can be given on the basis of

  1. None:- That privilege will not be given
  2. User :- That user will able to do operation on his/her records only.
  3. Business Unit :- That user will able to do operation on his/her business unit records only.
  4. Parent Business Unit :- That user will able to do operation on his/her parent business unit records only.
  5. Organization :- That user will able to do operation on all records.

Security Role

Customization of all the CRM form (Home page, Form Data Entry page, Form grid page)

There are two things which are needed to be changed:-

  1. Ribbon Button
  2. Site map

Ribbon button Customization

Steps(Example :- Advance Find):-
  1. Create an entity in the name of the button (new_advancefindrole)
  2. Give the permission to the entity(new_advancefindrole) in the Security Role under custom entity(Read).
  3. Open the ribbon solution in a ribbon editor.
  4. Add a new button and copy  the (detail,action , display rule, enable rule ) from advance find to new button
  5. Add a new display rule
    1. Entity Privilege rule
    2. Give the name of the entity(new_advancefindrole)
    3. Privilege depth :- Basic
    4. Privilege type :- Read
    5. Default :- true
    6. Invert Result :- false
  6. Hide the original advance find button(we can’t change the display rule in original advance find as it is managed)
  7. Save the customization
  8. Give permission under security role to entity(new_advancefindrole) to read to show in different roles.

Site Map

Steps(Example :- Settings):-

  1. Create an entity in the name of the button (new_settingsrole)
  2. Give the permission to the entity(new_settingsrole) in the Security Role under custom entity(Read)
  3. Export the “Site map” solution from the CRM
  4. Open Customization.xml in an xml editor
  5. Find “Area Id=<AreaName>(Ex :- Settings)” tag. Paste the Code Below
  6. Paste this code under every subarea of the settings
  7. Save the solution zip it , import it and publish it
  8. give permission under security role to entity(new_settingsrole) to read to show in different roles.

Changing the views according to the roles

Showing the view according to the role. There are two method in which this can be done :-

  1. By plug-in
  2. By creating personal view and sharing it with team

By Plug-in

Steps:-

  1. Create the Plug-in with following code.
  2. By this plug-in the view Starting from “My” will not be shown
  3. Register it :-
    1. Message :- RetriveMultiple
    2. Primary Entity :- savedquery
    3. Eventing :- Per-operation
    4. Execution Mode:- Synchronous
    5. Deployment:- Server

Plug-in Code:-

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using Microsoft.Crm.Sdk;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Crm.Sdk.Messages;

namespace Excitation.PluginHideSystemViews
{
    public class CheckView : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            try
            {
                // Obtain the execution context from the service provider.
                Microsoft.Xrm.Sdk.IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)
                serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));
                // Obtain the organization service reference.
                IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

                // The InputParameters collection contains all the data passed in the message request.
                if (CheckRole(context.UserId, "Salesperson", service))
                {

                    if (context.InputParameters.Contains("Query") == true && context.InputParameters["Query"] is QueryExpression)
                    {
                        QueryExpression qe = (QueryExpression)context.InputParameters["Query"];

                        if (qe.EntityName == "savedquery")
                        {
                            if (qe.Criteria != null)
                            {
                                if (qe.Criteria.Conditions != null)
                                {
                                    /*The query is edited to look at views not starting with "My" at the begining of the View Name*/
                                    ConditionExpression queryCondition = new ConditionExpression("name", ConditionOperator.NotLike, "My%");
                                    qe.Criteria.Conditions.Add(queryCondition);
                                    //context.InputParameters.Properties[ParameterName.Query] = qe;
                                    context.InputParameters["Query"] = qe;
                                }
                            }
                        }

                    }
                }
                else
                {
                    QueryExpression qe = (QueryExpression)context.InputParameters["Query"];
                    context.InputParameters["Query"] = qe;
                }
            }
            catch (Exception e)
            {

            }
        }

        //check if the user belongs to the specified role....
        private static bool CheckRole(Guid UserGuid, string SecurityRole, IOrganizationService CrmService)
        {
            #region Retrieve records from an intersect table via QueryExpression

            //Create Query Expression to fetch Role Entity
            QueryExpression Query = new QueryExpression()
            {
                //Setting the link entity condition and filter condition criteria/
                LinkEntities =
                        {
                            new LinkEntity
                            {
                                LinkFromEntityName = "role",
                                LinkFromAttributeName = "roleid",
                                LinkToEntityName = "systemuserroles",
                                LinkToAttributeName = "roleid",
                                LinkCriteria = new FilterExpression
                                {
                                    FilterOperator = LogicalOperator.And,
                                    Conditions =
                                    {
                                        new ConditionExpression
                                        {
                                            AttributeName = "systemuserid",
                                            Operator = ConditionOperator.Equal,
                                            Values = { UserGuid }
                                        }
                                    }
                                }
                            }
                        }
            };
            Query.EntityName = "role";

            Query.ColumnSet = new ColumnSet(true);

            // Obtain results from the query expression.
            EntityCollection UserRoles = CrmService.RetrieveMultiple(Query);

            // Searching for a specified Security Role into the list
            String test = "";
            test = UserGuid + "   \n";

            foreach (Entity UserSecurityRole in UserRoles.Entities)
            {
                test += (String)UserSecurityRole.Attributes["name"] + "  \n";
                if ((String)UserSecurityRole.Attributes["name"] == SecurityRole)
                {
                    return true;
                }
            }
            Entity testE = new Entity("new_transfer_opp");
            testE.Attributes["new_name"] = test;
            CrmService.Create(testE);
            if (UserRoles.Entities.Count == 0)
            {
                //return false as the role does not present
                return false;
            }
            else
            {
                return false;
            }

            #endregion

        }
    }
}

By creating personal view and sharing it with team

Steps(Example:- Sale manager):-

  1. Create a team(Sales manager) and add user to that team (Team is added under Administration)
  2. Create a view by Advance find Save that view
  3. Go to saved view and share the view to the team you want to see that view.

View Cutomization

By Sukant Shekhar
Senior Software Engineer @Team DynamicsCRM.
Mindfire Solutions

 

Tags: , , , , , , , , , , , , , , , , , , ,

Closing Opportunity using SOAP Request with Close Date

Project scenario

Using SOAP request I need to close opportunity from a custom HTML page. While closing opportunity, I need to send date also as close date for ‘Close Opportunity’.

Explanation of Code

Here format of date is very much different which is used to send through SOAP. I faced problem and stuck for 3 to 4 hours for this.

Finally I did.

Suppose,

var dateToSend = new Date();

Take a Date object and format it as :

dateToSend.format("yyyy-MM-ddThh:mm:ss.sszzz");

Only this Date format is taken by SOAP request.

Total SOAP request is as follows :

function CreateSoapXml(Id, Description, ActualRevenue, CloseDate, CompetitorId, Subject, Status) {
    var callback;

    xml += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
    xml += " <s:Body>";
    xml += " <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
    xml += " <request i:type=\"b:LoseOpportunityRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">";
    xml += " <a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
    xml += " <a:KeyValuePairOfstringanyType>";
    xml += " <c:key>OpportunityClose</c:key>";
    xml += " <c:value i:type=\"a:Entity\">";
    xml += " <a:Attributes>";
    xml += " <a:KeyValuePairOfstringanyType>";
    xml += " <c:key>opportunityid</c:key>";
    xml += " <c:value i:type=\"a:EntityReference\">";
    xml += " <a:Id>" + Id + "</a:Id>";
    xml += " <a:LogicalName>opportunity</a:LogicalName>";
    xml += " <a:Name i:nil=\"true\" />";
    xml += " </c:value>";
    xml += " </a:KeyValuePairOfstringanyType>";
    xml += " <a:KeyValuePairOfstringanyType>";
    xml += " <c:key>description</c:key>";
    xml += " <c:value i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">" + Description + "</c:value>";
    xml += " </a:KeyValuePairOfstringanyType>";
    xml += " <a:KeyValuePairOfstringanyType>";
    xml += " <c:key>competitorid</c:key>";
    xml += " <c:value i:type=\"a:EntityReference\">";
    xml += " <a:Id>" + CompetitorId + "</a:Id>";
    xml += " <a:LogicalName>competitor</a:LogicalName>";
    xml += " <a:Name i:nil=\"true\" />";
    xml += " </c:value>";
    xml += " </a:KeyValuePairOfstringanyType>";
    xml += " <a:KeyValuePairOfstringanyType>";
    xml += " <c:key>actualrevenue</c:key>";
    xml += " <c:value i:type=\"a:Money\">";
    xml += " <a:Value>" + ActualRevenue + "</a:Value>";
    xml += " </c:value>";
    xml += " </a:KeyValuePairOfstringanyType>";
    xml += " <a:KeyValuePairOfstringanyType>";
    xml += " <c:key>subject</c:key>";
    xml += " <c:value i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">" + Subject + "</c:value>";
    xml += " </a:KeyValuePairOfstringanyType>";
    xml += " <a:KeyValuePairOfstringanyType>";
    xml += " <c:key>actualend</c:key>";
    xml += " <c:value i:type=\"d:dateTime\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">" + CloseDate + "</c:value>";
    xml += " </a:KeyValuePairOfstringanyType>";
    xml += " </a:Attributes>";
    xml += " <a:EntityState i:nil=\"true\" />";
    xml += " <a:FormattedValues />";
    xml += " <a:Id>00000000-0000-0000-0000-000000000000</a:Id>";
    xml += " <a:LogicalName>opportunityclose</a:LogicalName>"
    xml += " <a:RelatedEntities />";
    xml += " </c:value>";
    xml += " </a:KeyValuePairOfstringanyType>";
    xml += " <a:KeyValuePairOfstringanyType>";
    xml += " <c:key>Status</c:key>";
    xml += " <c:value i:type=\"a:OptionSetValue\">";
    xml += " <a:Value>" + Status + "</a:Value>";
    xml += " </c:value>"
    xml += " </a:KeyValuePairOfstringanyType>";
    xml += " </a:Parameters>";
    xml += " <a:RequestId i:nil=\"true\" />";
    xml += " <a:RequestName>LoseOpportunity</a:RequestName>";
    xml += " </request>";
    xml += " </Execute>";
    xml += " </s:Body>";
    xml += "</s:Envelope>";
}

//Then send SOAP request as :

var req = new XMLHttpRequest();
req.open("POST", GetServerUrl(), (callback != null));
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");
req.send(xml);

if (req.readyState == 4) {
    if (req.status == 200) {
        alert("Opportunity Closed");
        Cancel();
        //window.opener.location.reload();
    }
    else {
        //errorCallback(_getError(req.responseXML));
        alert("There is an error occured");
    }
}

By Anish Thakur
Senior Software Engineer @Team DynamicsCRM.
Mindfire Solutions

 

Tags: , , , , , , , , , , , , , , , , ,

Convert a Multiple Line of Text field to a Button using JavaScript

First of all create a new field of type “Multiple Lines of Text” and name it as “new_button“.
And also create a “JavaScript Webresource” and add the following method in onload event.
ButtonImage
function OnFormLoad() {
    ConvertTextFieldToButton('new_button', 'ButtonText', '100px', ButtonClickFunction, 'Button Label');
}
 
function ConvertTextFieldToButton(fieldname, buttontext, buttonwidth, clickevent, title) {
    if (document.getElementById(fieldname) == null) {
        return;
    }
 
    var functiontocall = clickevent;
    document.getElementById(fieldname).value= buttontext;
    document.getElementById(fieldname).readOnly = true;
    document.getElementById(fieldname).style.borderRight = "#3366cc 1px solid";
    document.getElementById(fieldname).style.paddingRight = "5px";
    document.getElementById(fieldname).style.borderTop = "#3366cc 1px solid";
    document.getElementById(fieldname).style.paddingLeft = "5px";
    document.getElementById(fieldname).style.fontSize = "11px";
    document.getElementById(fieldname).style.backgroundImage = "url(/_imgs/btn_rest.gif)";
    document.getElementById(fieldname).style.borderLeft = "#3366cc 1px solid";
    document.getElementById(fieldname).style.width = buttonwidth;
    document.getElementById(fieldname).style.cursor = "hand";
    document.getElementById(fieldname).style.lineHeight = "18px";
    document.getElementById(fieldname).style.borderBottom = "#3366cc 1px solid";
    document.getElementById(fieldname).style.backgroundRepeat = "repeat-x";
    document.getElementById(fieldname).style.fontFamily = "Tahoma";
    document.getElementById(fieldname).style.height = "20px";
    document.getElementById(fieldname).style.backgroundColor = "#cee7ff";
    document.getElementById(fieldname).style.textAlign = "center";
    document.getElementById(fieldname).style.overflow = "hidden";

    if(window.attachEvent)
    {
        document.getElementById(fieldname).attachEvent("onmousedown", MouseDown_button);
        document.getElementById(fieldname).attachEvent("onmouseup", MouseUp_button);        
        document.getElementById(fieldname).attachEvent("onclick", functiontocall);
    }
    else
    {
        document.getElementById(fieldname).addEventListener("mousedown", MouseDown_button, false);
        document.getElementById(fieldname).addEventListener("mouseup", MouseUp_button, false);        
        document.getElementById(fieldname).addEventListener("click", functiontocall, false);
    }

    document.getElementById(fieldname).style.lineHeight = "14px";
    document.getElementById(fieldname + '_c').style.visibility = 'hidden';
    document.getElementById(fieldname + '_d').style.width=buttonwidth;
    document.getElementById(fieldname +'_container').style.width="112px";
    document.getElementById(fieldname).title = title;
    window.focus();
 
    //Method Call on Mouse down
    function MouseDown_button(evt) {
       var eventer;   
  
       if(evt.srcElement)
       {
           eventer = evt.srcElement;
       }
       else
       {
           eventer = evt.target;
       }

       eventer.style.borderWidth = "2px";
       eventer.style.borderStyle = "groove ridge ridge groove";
       eventer.style.borderColor = "#3366cc #4080f0 #4080f0 #3366cc";
    }
 
    //Method Call on Mouse up
    function MouseUp_button(evt) {
       var eventer;   
  
       if(evt.srcElement)
       {
           eventer = evt.srcElement;
       }
       else
       {
           eventer = evt.target;
       }
        
       eventer.style.border = "1px solid #3366cc";
    }
}
 
function ButtonClickFunction() {
    //Method call on button click
}

Notes:
It also supports single line of text.

By Puja Jain
Senior Software Engineer @Team DynamicsCRM.
Mindfire Solutions

 
5 Comments

Posted by on April 25, 2013 in WebResources

 

Tags: , , , , , , , , , , , , , , , ,

Adding Tool Tips To Fields

Introduction

Tool tips can be added to the fields of the CRM form. It can be a static or dynamic tool tip.

Implementation

To implement this logic, we need Jquery.1.4.4.min.js file. You can get from here .

Create a  javascript web resource and add following functions in it.

function GetToolTips() {
    //Select Name Of Fields Whose ToolTips Is Recquird
    var fieldName1 = "telephone1";
    var fieldName2 = "telephone2";
    var fieldName3 = "fax";

    //Create Text To Be Shown In Respected Fields
    var textOfFieldName1 = "Tool Tip One";
    var textOfFieldName2 = "Tool Tip Two";
    var textOfFieldName3 = "Tolo Tip Three";

    //Calling Method To set Text On That Label Of Selected Field
    RegisterTips(fieldName1, textOfFieldName1);
    RegisterTips(fieldName2, textOfFieldName2);
    RegisterTips(fieldName3, textOfFieldName3);
}

function RegisterTips(fieldName, textOfField) {
    var obj = document.getElementById(fieldName + '_c').children[0];

    // construct tooltip text according to attribute name
    html = '</pre>
<div id="tooltip_' + fieldName + '" style="visibility: hidden; position: absolute;">: ' + textOfField + '</div>
<pre>
';

    $(obj).append(html); // append tooltip text with label
}

Add  jquery.1.4.4.min.js file as web resource.

In the “account” form property, add  both the Web Resources.

In the Onload event of  the account form call the GetToolTips() function and see the tool tip will be reflected when the mouse points to that fields as shown below.

Capture capture2

Hope it helps you……

By Ranjan Parhi
Senior Software Engineer @Team DynamicsCRM.
Mindfire Solutions

 
 

Tags: , , , , , , , , , , , , , , , , ,

 
%d bloggers like this: