<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Pedro Innecco</title>
	<atom:link href="http://www.pedroinnecco.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.pedroinnecco.com</link>
	<description>ICT Specialist: pgDMS, MBA, MBSS, MCTS, MCP, VTSP</description>
	<lastBuildDate>Fri, 11 May 2012 18:24:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Dynamics CRM: Disabling the selection of contacts for opportunities all the way</title>
		<link>http://www.pedroinnecco.com/2012/05/dynamics-crm-disabling-the-selection-of-contacts-for-opportunities-all-the-way/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=dynamics-crm-disabling-the-selection-of-contacts-for-opportunities-all-the-way</link>
		<comments>http://www.pedroinnecco.com/2012/05/dynamics-crm-disabling-the-selection-of-contacts-for-opportunities-all-the-way/#comments</comments>
		<pubDate>Tue, 08 May 2012 13:25:39 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[Dynamics CRM]]></category>
		<category><![CDATA[customisation]]></category>
		<category><![CDATA[dynamics crm]]></category>
		<category><![CDATA[jscript]]></category>
		<category><![CDATA[workflow]]></category>

		<guid isPermaLink="false">http://www.pedroinnecco.com/?p=1407</guid>
		<description><![CDATA[I recently got a requirement for a Dynamics CRM implementation that all recorded sales should follow the B2B (business to business) and therefore, opportunities should only able to be related [...]]]></description>
			<content:encoded><![CDATA[<p>I recently got a requirement for a Dynamics CRM implementation that all recorded sales should follow the B2B (business to business) and therefore, opportunities should only able to be related to accounts, and not contacts as well.</p>
<p>This is a common scenario which can be easily covered with some simple JScript in the opportunity form. However I found out that in some circumstances, an opportunity could still be created for a contact, thus violating the requirement and even worse, breaking some of the implemented processes and business logic. Here is how I fixed this issue.<span id="more-1407"></span></p>
<h2>Background</h2>
<p>In a default Dynamics CRM implementation, customers can either be accounts or contacts. When creating a record that can be bound to either an account or contact such as an opportunity, the customer field is bound to a virtual composite entity where either an account or a contact is valid. Thinking from a database perspective, there is no <strong>customerid</strong> column in the opportunities table, because there is no customer entity on the system. There is, however, an <strong>accountid</strong> column and a <strong>contactid</strong> column. When the record is saved, either <strong>accountid</strong> or <strong>customerid</strong> will be filled with a link to the respective record, depending whether if the user specified an account, or a contact.</p>
<h2>A simple JScript?</h2>
<p>A simple way to avoid users from selecting a contact as a potential customer for opportunities is through the use of a JScript bound the form’s <strong>onLoad</strong> event. Here is an example:</p>
<pre class="brush: jscript; title: ; notranslate">
function FilteredCustomerLookupAccount(customerField) {
var CRM_FORM_TYPE = Xrm.Page.ui.getFormType();
if (CRM_FORM_TYPE == 4 || CRM_FORM_TYPE == 3) { return; }

//Limit the entity lookup choice to Account
document.getElementById(customerField).setAttribute(&quot;lookuptypes&quot;, &quot;1&quot;);
}
</pre>
<p>Make sure to pass the name of the customer field between quotes as a parameter when calling the function. In the case of the Opportunity&#8217;s form, you should specify <code>'customerid'</code>.</p>
<p>This should do the trick, right? Well, yes; if opportunity records are being created and edited through the form that contains such JScript. But this script takes no effect if an opportunity record is created through another context, thus bypassing this JScript. For example, if the user creates a record using the Mobile Express forms, or a third party client or solution that creates the record through the web service of Dynamics CRM.</p>
<p>Even if you have disabled Mobile Express forms and no one uses a third party client to create records in Dynamics CRM, there are still cases where the Jscript above could be bypassed.</p>
<p class="infobox"><strong>Update: Don&#8217;t forget the Opportunities link in the Contact&#8217;s form</strong><br/>As Adam V mentioned in the comments section below, make sure that you remove the link to Opportunities from the left navigation pane of the Contact forms. Since any CRM platform is all about relationships between different entities, it is important to consider both ends of the relationship tether when performing such type of customisations.</p>
<h2>Activities: The agent provocateur</h2>
<p>When a user converts an activity to an opportunity, the record specified in the <strong>Recipient</strong> field of the activity will become the <strong>Potential Customer</strong> of the opportunity that is created. Therefore if the user specified a contact as the recipient of the activity, the opportunity will be bound to the contact. This is because the opportunity record is created and then saved when the user converts the activity to an opportunity, thus bypassing the JScript to disallow contacts.</p>
<h2>Solution – part I: Workflow</h2>
<p>The first part of my solution involves a workflow. In this Dynamics CRM implementation, a contact must be bound to a parent account, and it must be an account. That is, the above JScript used to block the selection of contacts is also bound to the onLoad of my Contact form.</p>
<p>So what I did is to create a workflow for the Opportunity entity that checks for the condition <code>Opportunity:Potential Customer equals [Potential Customer (Contact):Contact]</code> (that is, if the opportunity is bound to a contact). If it is bound to a contact, then it will change the customer from the current contact to <code>{Parent Customer(Potential Customer (Contact))}</code>, which is effectively the contact’s parent account.</p>
<p style="text-align: center;"><a href="http://www.pedroinnecco.com/files/crm_activities_01.png"><img src="http://www.pedroinnecco.com/files/crm_activities_01-300x245.png" alt="" title="Limiting opportunities to accounts: Handling loopholes through a workflow" width="300" height="245" class="aligncenter size-medium wp-image-1420" /></a></p>
<p>Because an opportunity record created outside the scope of its form will bypass all JScripts, it not only bypasses the blocking of contact selection, but also any other business logic I might have in any other JScript. Therefore my workflow also checks for empty fields that shouldn’t be empty, and set some default values.</p>
<h2>Solution – part II: JScript</h2>
<p>The problem with workflows is that although they are useful, they are an asynchronous, background process. Therefore the user wouldn’t get any sort of feedback of what is going on. In order to resolve this, I added a second JScript to the onLoad event of my Opportunity form, as follows:</p>
<pre class="brush: jscript; title: ; notranslate">
function setOpAccountPerContact() {

	var CRM_FORM_TYPE = Xrm.Page.ui.getFormType();
	if (CRM_FORM_TYPE != 2) { return; }

	if(Xrm.Page.getAttribute(&quot;customerid&quot;).getValue()!=null) {
		if(Xrm.Page.getAttribute(&quot;customerid&quot;).getValue()[0].typename==&quot;contact&quot;) {
		alert (&quot;This opportunity is bound to a contact. The relationship will automatically change for the contact's parent account.&quot;);

		var idCustomer = Xrm.Page.getAttribute(&quot;customerid&quot;).getValue()[0].id;
		var retrieveRecordsReq = new XMLHttpRequest();
		var ODataPath = Xrm.Page.context.getServerUrl() + &quot;/XRMServices/2011/OrganizationData.svc&quot;;

		retrieveRecordsReq.open('GET', ODataPath+&quot;/ContactSet(guid'&quot; + idCustomer + &quot;')&quot;,false);
		retrieveRecordsReq.setRequestHeader(&quot;Accept&quot;, &quot;application/json&quot;);
		retrieveRecordsReq.setRequestHeader(&quot;Content-Type&quot;, &quot;application/json; charset=utf-8&quot;);
		retrieveRecordsReq.send();

		var records = this.parent.JSON.parse(retrieveRecordsReq.responseText).d;

		var lookupValue = new Array();
		lookupValue[0] = new Object();
		lookupValue[0].id = records.ParentCustomerId.Id;
		lookupValue[0].name = records.ParentCustomerId.Name;
		lookupValue[0].entityType = &quot;account&quot;;
		Xrm.Page.getAttribute(&quot;customerid&quot;).setValue(lookupValue); 

		}
	}
}
</pre>
<p>The above script will check if the opportunity is bound to a contact as the potential customer. If that is the case, it will inform the user through an alert, and it will proceed to change the <strong>Potential Customer</strong> field from the current contact to the contact’s parent account.</p>
<h2>Wrapping up</h2>
<p>When users convert an account to an opportunity for a contact and the option to open the new opportunity is selected, the users will receive an alert, and they will see the <strong>Potential Customer</strong> field change its value to the related account record. Even if the user doesn&#8217;t save the change performed by the JScript, the workflow will replace the <strong>Potential Customer</strong> value with the related account.</p>
<p style="text-align: center;"><a href="http://www.pedroinnecco.com/files/crm_activities_02.png"><img src="http://www.pedroinnecco.com/files/crm_activities_02-300x256.png" alt="" title="Limiting opportunities to accounts: Converting an activity to an opportunity" width="300" height="256" class="aligncenter size-medium wp-image-1417" /></a>
<p>The JScript provides users with the visual, client-side aid, while the workflow is our catch-all in the lookout for any discrepancy in the system.</p>
<p>There is no way I could have done this solution without the help of <a href="http://mahenderpal.wordpress.com/" title="Mahender Pal's Blog" target="_blank">Mahender Pal</a>, a Dynamics MVP from India who helped me out with the JScript part of the solution. Thank you Mahender!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pedroinnecco.com/2012/05/dynamics-crm-disabling-the-selection-of-contacts-for-opportunities-all-the-way/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Dynamics CRM: The importance of the Address entity</title>
		<link>http://www.pedroinnecco.com/2012/04/dynamics-crm-the-importance-of-the-address-entity/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=dynamics-crm-the-importance-of-the-address-entity</link>
		<comments>http://www.pedroinnecco.com/2012/04/dynamics-crm-the-importance-of-the-address-entity/#comments</comments>
		<pubDate>Mon, 23 Apr 2012 22:05:21 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[Dynamics CRM]]></category>
		<category><![CDATA[customisation]]></category>
		<category><![CDATA[dynamics crm]]></category>
		<category><![CDATA[jscript]]></category>
		<category><![CDATA[workflow]]></category>

		<guid isPermaLink="false">http://www.pedroinnecco.com/?p=1342</guid>
		<description><![CDATA[Earlier this year I wrote an article about considerations when customising address fields. I was happy with the reception the article got, as it sparked some interesting discussions not only [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this year <a href="http://www.pedroinnecco.com/?p=1152" title="Dynamics CRM: Considerations when customising address fields">I wrote an article about considerations when customising address fields</a>. I was happy with the reception the article got, as it sparked some interesting discussions not only with some of my clients, but also with fellow Dynamics CRM consultants.</p>
<p>Today I would like to expand further on that discussion and talk about an often neglected entity in Dynamics CRM: The Address entity and its importance in every single Dynamics CRM deployment out there (yes, including yours).<span id="more-1342"></span></p>
<h2>Address fields in customer entities: Isn&#8217;t that enough?</h2>
<p>Let’s have a look at Accounts and Contacts (i.e.: the customer entities) in Dynamics CRM. These entities already contain address fields which are used to capture address information for a customer record. Consider the following screenshot of a default, “vanilla” form for the Account entity:</p>
<p style="text-align: center;"><a href="http://www.pedroinnecco.com/files/crm_address-entity_01.png"><img src="http://www.pedroinnecco.com/files/crm_address-entity_01-300x127.png" alt="" title="crm_address-entity_01" width="300" height="127" class="aligncenter size-medium wp-image-1344" /></a></p>
<p>The above example illustrates most of the default address related fields available for an Account entity (note that the same fields are available for contacts). If you look at the fields available for the entity however, you will notice that there are many more address related fields available. There are two instances for each address-related field, each starting with the prefix <strong>address1</strong> or <strong>address2</strong>, with forty six fields in total.  A customer record could potentially store information about two different addresses.</p>
<p style="text-align: center;"><a href="http://www.pedroinnecco.com/files/crm_address-entity_02.png"><img src="http://www.pedroinnecco.com/files/crm_address-entity_02-300x241.png" alt="" title="Some of the available address fields for a customer entity." width="300" height="241" class="aligncenter size-medium wp-image-1345" /></a></p>
<p>Therefore, most people then consider unnecessary the use of the Address entity, and tend to neglect it completely when customising Dynamics CRM. The problem is that the Address entity is alive and kicking.</p>
<h2>Hidden address records</h2>
<p>I invite you to perform an Advanced Find in a deployment of Dynamics CRM containing data to look for Address records. Just click on <strong>Advanced Find</strong> to open the Advanced Find dialog, then where it says <strong>Look For</strong>, select <code>Addresses</code>. Make sure that where it says <strong>Used Saved View</strong>, the option <code>[new]</code> is selected. Then click on the <strong>Results</strong> button at the ribbon to execute the search query.</p>
<p style="text-align: center;"><a href="http://www.pedroinnecco.com/files/crm_address-entity_03.png"><img src="http://www.pedroinnecco.com/files/crm_address-entity_03-300x68.png" alt="" title="The results of an Address search query." width="300" height="68" class="aligncenter size-medium wp-image-1346" /></a></p>
<p>Well, I never created address records in this implementation of Dynamics CRM. So where did all these addresses came from?</p>
<p>Here is the kicker. Every time you create a new account or contact, the system creates two address records which are related in a parental relationship with the customer record: One address record containing the information populated in the address1 fields of the customer record, and a second address record containing the information populated in the address2 fields of the customer record. Every time you modify the address within the customer record, it updates the related address record and vice-versa.</p>
<p>Now if you try to find these address records by navigating through More Addresses when viewing a customer record, you wouldn’t find them; but you would find the address records you have manually created for the customer record. The reason being is that there is a filtered view in the Address entity, as to only show address records were the field <strong>Address Number</strong> is greater than 2 (which are the ones created by the users).</p>
<p style="text-align: center;"><a href="http://www.pedroinnecco.com/files/crm_address-entity_04.png"><img src="http://www.pedroinnecco.com/files/crm_address-entity_04-300x112.png" alt="" title="crm_address-entity_04" width="300" height="112" class="aligncenter size-medium wp-image-1347" /></a></p>
<p>Therefore for the purpose of mail merge, Dynamics CRM relies on the address records, not on the address fields contained in the customer record. Furthermore, this entity is quite useful when integrating Dynamics CRM with ERP systems, such as Dynamics NAV. Therefore it is extremely important that when customising the addresses in Dynamics CRM that the Address entity is not neglected.</p>
<h2>Considerations when customising address information</h2>
<p>Although these two hidden address records are automatically created whenever a customer record is created, this isn&#8217;t a process that can be easily customised. There isn&#8217;t a workflow in the system that can be configured to consider custom address fields and to make things worse, field mappings between address and accounts and contacts can&#8217;t be configured either.</p>
<p class="infobox"><strong>The truth about Address1 and Address2 fields:</strong> As <a href="http://www.meteorit.co.uk/" title="Adam Vero is the Dynamics CRM expert behind Meteor IT UK" target="_blank">Adam Vero</a> explained in the comments section below, and I quote: &#8220;The addresses are NOT stored on Account and Contact records at all, they just look like they are, which is why you can&#8217;t map anything with the Address records &#8211; the fields are really on the Address entity anyway and simply shown on the Account or Contact for ease of use and simplicity of building queries, workflows etc.&#8221; </p>
<p>These limitation reinforce not only the points I raised in <a href="http://www.pedroinnecco.com/?p=1152" title="Dynamics CRM: Considerations when customising address fields">my previous article</a> concerning address fields<a href="http://www.pedroinnecco.com/?p=1152" title="Dynamics CRM: Considerations when customising address fields">, but also <a href="http://www.pedroinnecco.com/?p=491" title="Dynamics CRM: Adding a Country/Region option set using ISO 3166-1">some points I raised</a> when creating a custom Country/Region field.</p>
<p>Always make sure that the default address fields are populated, even when using custom fields. For example, if you replace the default Country/Region text field for Accounts and Contacts (also Competitors and Addresses), make sure that you still populate the default Country/Region text field, either through JScript or through a workflow. This will ensure that all address information captured in the customer record is passed on to its related address records.</p>
<p>In other words: Consider your custom address fields simply as controls that <strong>must</strong> pass their values to the default address fields.</p>
<p>Also, since there are limitations on the field mappings between the Address entity the Account and Contact entity, it is not wise to allow users to edit those hidden address records if have replaced or added new address fields. One way to avoid this is to set a JScript on the onLoad of the Address form so it disable (or even hide) its fields if the value of the <strong>Address Number</strong> field is equal to either 1 or 2, which are the values of the two hidden address records for a given customer. You could even add an alert (a message box popup) when the user tries to edit one of these records, explaining that the user should do it through editing the address fields within the customer record. This will avoid mismatches between the Address record and the address fields for a customer record.</p>
<p>If you want to disable all fields of the Address form, Andrew Zimmer from Avtex wrote an article on how to achieve this <a href="http://blogs.inetium.com/blogs/azimmer/archive/2011/04/01/disabling-an-entire-form-in-crm-2011.aspx" title="Disabling all Fields on a Form in CRM 2011 - Andrew Zimmer - Avtex" target="_blank">here</a>. Here is a modified version of Adrew&#8217;s script that you could use:</p>
<pre class="brush: jscript; title: ; notranslate">
// Add this script as a webresource and to the Address form
function doesControlHaveAttribute(control) {
    var controlType = control.getControlType();
    return controlType != &quot;iframe&quot; &amp;&amp; controlType != &quot;webresource&quot; &amp;&amp; controlType != &quot;subgrid&quot;;
}

function disableFormFields(onOff) {

    Xrm.Page.ui.controls.forEach(function (control, index) {
        if (doesControlHaveAttribute(control)) {
            control.setDisabled(onOff);
        }
    });
}

//Call the following function on the Address form onLoad event
function disableAddressForm(){

    if (Xrm.Page.getAttribute(&quot;addressnumber&quot;).getValue() == 1 || Xrm.Page.getAttribute(&quot;addressnumber&quot;).getValue() == 2) {

           disableFormFields(true);
		   // We can also show an alert to help users out
		   alert(&quot;In order to edit this address record, please edit the address information of its related customer record.&quot;);

    }
}
</pre>
<p>However, since I have customised the Address form with custom fields just like I did with the Address fields for Accounts, Contacts and Competitors, I much rather hide the fields altogether because since there is no field mapping between the Address and Accounts and Contacts, the default addresses just look messy. We can achieve this by hiding the form sections with the following JScript, which I modified from <a href="http://gtcrm.wordpress.com/2011/03/16/jscript-reference-for-microsoft-crm-2011/" title="Gareth Tucker - Jscript reference for Microsoft CRM 2011" target="_blank">Gareth Tucker&#8217;s JScript examples for Dynamics CRM 2011</a>:</p>
<pre class="brush: jscript; title: ; notranslate">
// Add this script as a webresource and to the Address form
function HideShowSection(tabName, sectionName, visible) {
    try {
        Xrm.Page.ui.tabs.get(tabName).sections.get(sectionName).setVisible(visible);
    }
    catch (err) { }
}

//Call the following function on the Address form onLoad event
function disableAddressForm(){

    if (Xrm.Page.getAttribute(&quot;addressnumber&quot;).getValue() == 1 || Xrm.Page.getAttribute(&quot;addressnumber&quot;).getValue() == 2) {

           HideShowSection(&quot;general&quot;, &quot;customer address information&quot;, false);
		   HideShowSection(&quot;general&quot;, &quot;phone numbers&quot;, false);
		   HideShowSection(&quot;general&quot;, &quot;additional information&quot;, false);
		   // We can also show an alert to help users out
		   alert(&quot;In order to view or edit this address record, please refer to the address information stored in its related customer record.&quot;);

    }
}
</pre>
<p>Just remember that for these scripts to work, you would need to add the field <strong>Address Number</strong> hidden to the form since it is not there by default.</p>
<p>Also, instead of displaying an alert, we could add an HTML web resource to the Address hidden by default with some instructions or information on disabled forms, and show this web resource based on the value of the <strong>Address Number</strong> field.</p>
<h2>Bonus: Avoiding empty address records with workflows</h2>
<p>When populating address information for accounts and contacts, many users (and I include myself in this generalisation) often disregard the <strong>Address Name</strong> and <strong>Address Type</strong> fields. In fact it is common for clients to request these fields to be removed altogether from the forms. However since two address records are going to be created no matter what, we end up with nameless address records in the Address entity, as per the third screenshot from the top bottom.</p>
<p>Normally this might not be an issue for many clients. However I got a client who often perform a lot of queries against the Address entity, and having to look through lots of address records without an Address Name and Address Type can make it difficult to find a record.</p>
<p>The solution is to create one workflow for the Account entity and another for the Contact entity for when a record is created, that automatically populates the Address Name and Address Type fields with some default information. In my case I populate <strong>address1_name</strong> with <code>{Account Name (Account)} - Primary Address</code> and <strong>address2_name</strong> with <code>{Account Name (Account)} - Secondary Address</code>. You could also set the value for <strong>address1_addresstypecode</strong> and <strong>address2_addresstypecode</strong>.</p>
<p style="text-align: center;"><a href="http://www.pedroinnecco.com/files/crm_address-entity_05.png"><img src="http://www.pedroinnecco.com/files/crm_address-entity_05-300x169.png" alt="" title="crm_address-entity_05" width="300" height="169" class="aligncenter size-medium wp-image-1358" /></a></p>
<p>The workflow for the Contact entity would be similar, but using the contact&#8217;s full name instead for naming the address, such as <code>{Full Name (Contact)} - Primary Address</code> and <strong>address2_name</strong> with <code>{Full Name (Contact)} - Secondary Address</code>.</p>
<p>Make sure these workflows also run when their respective fields change (i.e.: <strong>Account Name</strong> for Accounts and <strong>Full Name</strong> for Contacts) in case the records are renamed. Finally, you could make these workflows run on demand in order to update all of your existing account and contact records.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pedroinnecco.com/2012/04/dynamics-crm-the-importance-of-the-address-entity/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Dynamics CRM: Set Title Case for a text field using JScript; but only once</title>
		<link>http://www.pedroinnecco.com/2012/04/dynamics-crm-set-title-case-for-a-text-field-using-jscript-but-only-once/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=dynamics-crm-set-title-case-for-a-text-field-using-jscript-but-only-once</link>
		<comments>http://www.pedroinnecco.com/2012/04/dynamics-crm-set-title-case-for-a-text-field-using-jscript-but-only-once/#comments</comments>
		<pubDate>Wed, 04 Apr 2012 15:40:05 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[Dynamics CRM]]></category>
		<category><![CDATA[customisation]]></category>
		<category><![CDATA[dynamics crm]]></category>
		<category><![CDATA[jscript]]></category>

		<guid isPermaLink="false">http://www.pedroinnecco.com/?p=1322</guid>
		<description><![CDATA[Today I had to work on a interesting JScript for Dynamics CRM. When creating a new Contact record, the text values within the fields for First Name, Middle Name and [...]]]></description>
			<content:encoded><![CDATA[<p>Today I had to work on a interesting JScript for Dynamics CRM. When creating a new Contact record, the text values within the fields for First Name, Middle Name and Last Name should have a Title Case enforced to them. For example, if a user types &#8220;JOhN&#8221; in the First Name field, the case should be automatically corrected to &#8220;John&#8221;.</p>
<p>To make things more interesting, here is the second part of the requirement: After a case correction has been performed in a field, it shouldn&#8217;t be performed again. So if the user now proceeds to type &#8220;JOHN&#8221; in the First Name field after the first case correction, the system should leave the case as it is.</p>
<p>Now, I am not saying that I agree with this requirement, but it is a requirement nonetheless. I make no secret that I am far from having the JScript knowledge I aspire for, so this was a good exercise for me and I hope the community can benefit from it.<span id="more-1322"></span></p>
<p>This is an interesting solution because it covers the usage of global variables in JScript, function parameters and an array for individually controlling whether a field should have its case fixed or not.</p>
<ol>
<li>The first step is to create a new JScript web resource for our Dynamics CRM solution. I called it <code><span style="color: #0000ff;">new_</span>SetTitleCase</code>. Then paste the following code for the script:</li>
<pre class="brush: jscript; title: ; notranslate">
// Let's start by declaring the Global variable outside the function. Feel free to name it _WhatEverYouFancy
var _i = null;

// This is the function we will call in the onChange event of a field. Make sure to pass the field Schema Name as a parameter (fieldName) when using the function
SetTitleCase = function(fieldName) {
  if ((_i != null) &amp;&amp; (_i.indexOf(fieldName) &gt;= 0))
    return;
  var CRM_FORM_TYPE = Xrm.Page.ui.getFormType();

  // If the form isn't of type 1 (Create Form) then stop the script
  if (CRM_FORM_TYPE != 1) { return; }

	var str = Xrm.Page.data.entity.attributes.get(fieldName).getValue();

	str = str.toLowerCase().replace(/\b[a-z]/g, function(letter) {
	return letter.toUpperCase();
	});

	Xrm.Page.getAttribute(fieldName).setValue(str);
		if (_i == null)
			_i = fieldName;
		else
			_i += &quot;|&quot; + fieldName;

}
</pre>
<li>Now while customizing the Contact form, click on <strong>Form Properties</strong>, then under <strong>Form Libraries</strong> within the <strong>Events</strong> tab we must add the new JScript we just created. Confirm all the changes and go back to the main Contact customization form.</li>
<li>Now double-click on a field we would like the Title Case to be enforced to. Within the <strong>Events</strong> tab, click on <strong>Add</strong> under <strong>Event Handlers</strong> to bind our JScript to the <strong>onChange</strong> event of the field.</li>
<li>In the Handler Properties dialog, make sure that the correct script is specified in <strong>Library</strong> selection. Type <code>SetTitleCase</code> as the value for the <strong>Function</strong> field, and then type the field schema name between quotes for the parameters field. For example <code>'firstname'</code> for the First Name field.</li>
<li>Make sure to confirm all changes and publish the customizations.</li>
</ol>
<p>There is no way I could have code this script by myself with my limited knowledge of JScript. Thanks to <strong>JBlaeske</strong> at the Microsoft forums for the help on this one!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pedroinnecco.com/2012/04/dynamics-crm-set-title-case-for-a-text-field-using-jscript-but-only-once/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The entertainment industry&#8217;s war on consumers</title>
		<link>http://www.pedroinnecco.com/2012/02/the-entertainment-industrys-war-on-consumers/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=the-entertainment-industrys-war-on-consumers</link>
		<comments>http://www.pedroinnecco.com/2012/02/the-entertainment-industrys-war-on-consumers/#comments</comments>
		<pubDate>Fri, 24 Feb 2012 11:05:14 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[Current Affairs]]></category>
		<category><![CDATA[video games]]></category>

		<guid isPermaLink="false">http://www.pedroinnecco.com/?p=1290</guid>
		<description><![CDATA[The consumer preview of Windows 8 is around the corner, and I&#8217;ve been reflecting about it&#8217;s Windows Store, the consumerisation of IT and how it affects us as consumers. I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>The consumer preview of Windows 8 is around the corner, and I&#8217;ve been reflecting about it&#8217;s Windows Store, the consumerisation of IT and how it affects us as consumers. I&#8217;m afraid I see dark times ahead of us.</p>
<p>Sure that downloading content from the comfort of your home is a convenient concept. But corporations are luring consumers to become cattle in a battery farm, where they milk consumers for their money to pay for services, but consumers hold no right to any goods. As consumers we don&#8217;t own anything but the limited right to consume content provided by these companies. So when we buy a song or a book, we don&#8217;t own a copy of the song or the book, but the limited right to play the song and read the book. If the corporation wishes to do so, they can pull out our right to such content.<span id="more-1290"></span></p>
<p>The ultimate goal of the entertainment industry goes way beyond their claims to stop piracy. What they want is to remove from consumers any ownership claims over <strong>a copy</strong> of a record, movie or video game. Remember when we could go to a shop of used records to buy a hard-to-find album or movie? Well if it is up to the entertainment industry this will be a thing of the past. The first step is to remove the material objects out of the equation. How do they do that? By offering access to music, video and games as a service. However, &#8220;digital content as a service&#8221; is just one front of the entertainment&#8217;s industry war against consumers.</p>
<p>Even if we don&#8217;t subscribe to a service and instead buy records, movies and games individually, if we buy such content digitally, the content provider can ultimately revoke our rights to such content if we (allegedly) violate their terms and conditions (as ludicrous as they might be). But wait, there is more! <a href="http://arstechnica.com/gaming/news/2012/01/how-the-next-xbox-could-stop-you-from-playing-used-games.ars" title="ars technica - How the next Xbox could stop you from playing used games" target="_blank">Now the game industry is evaluating ways of taking this travesty one step further</a> in the next generation of video game consoles by establishing an activation process between retail game copies (i.e.: physical &#8220;material objects&#8221; like a game disk or cartridge) and consoles. In practical terms this means that when you buy a game in a store, it will come with a code that must be activated against your video game console as to grant you the right to play that copy of the game with that console. So if you try to play that game in another console, the game will not load. Unless the video game industry finds its way to grasp their claws over the rental and second-hand games market, you can say goodbye to the renting and selling of used games. Even lending a copy of a game to a friend will be impossible. If this really happens with the next generation of video game consoles, I will proudly and openly condone all mods, hacking and tampering aimed to circumvent such system.</p>
<p>And now the software industry wants to join in as well. With Windows 8, Microsoft will also debut their new digital marketplace. Imagine being able to download and shop for apps and applications from one centralized location and having updates automatically pushed to your desktop. It sure sounds convenient (unless of course, this idea is against your political views). However, imagine a software you bought being pulled out of your computer automatically because you (allegedly) violated some obscure T&#038;C agreement, or because &#8220;Microsoft doesn&#8217;t like it anymore&#8221;, or because &#8220;<a href="http://www.youtube.com/watch?v=Ly3Ew3wQ4PA" title="Little Britain - Computer says no..." target="_blank">computer says no</a>&#8220;.</p>
<p>Don&#8217;t get me wrong. I believe that musicians, artists and video game developers should be rewarded for their hard work and should hold their right to their material. My problem is with cartels like the RIAA and the MPAA. Our intellectual property laws are a failure, which allow big corporations to bully and push consumers around. If I buy a CD, a movie or a book, why shouldn&#8217;t I be able to sell it a a latter stage to someone else? Why should I buy two copies of a game if I want to play online against two different &#8220;regions&#8221; in the world? The answer is <strong><a href="http://www.youtube.com/watch?v=Muz1OcEzJOs" title="Greed is good!" target="_blank">GREED</a></strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pedroinnecco.com/2012/02/the-entertainment-industrys-war-on-consumers/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Warning EU Citizens: Avoid getting a Windows Phone (or Xbox Live for that matter)</title>
		<link>http://www.pedroinnecco.com/2012/02/warning-eu-citizens-about-microsoft/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=warning-eu-citizens-about-microsoft</link>
		<comments>http://www.pedroinnecco.com/2012/02/warning-eu-citizens-about-microsoft/#comments</comments>
		<pubDate>Thu, 23 Feb 2012 11:39:15 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[Current Affairs]]></category>
		<category><![CDATA[IT]]></category>

		<guid isPermaLink="false">http://www.pedroinnecco.com/?p=1272</guid>
		<description><![CDATA[One of the fundamental basis of the European Union is the principle of four freedoms: freedom of movement of people, goods capitals and services. As Europeans, we can freely move [...]]]></description>
			<content:encoded><![CDATA[<p>One of the fundamental basis of the European Union is the <a href="http://en.wikipedia.org/wiki/Four_Freedoms_(European_Union)" title="Internal Market (European Union) on Wikipedia" target="_blank">principle of four freedoms</a>: freedom of movement of people, goods capitals and services. As Europeans, we can freely move around member states and live in as legal residents.</p>
<p>However, if you&#8217;re planning to get a Windows Phone, prepare to have your rights as an EU citizen challenged by Microsoft.<span id="more-1272"></span></p>
<p>Let me just say beforehand that Windows Phone is by far the best piece of smartphone hardware I had. In my view it is far &#8212; far superior than an iPhone or an Android phone. The problem isn&#8217;t with the phone&#8217;s hardware or the software, but with Microsoft&#8217;s draconian control of the phone&#8217;s ecosystem.</p>
<p>In order to purchase goods in the Windows Phone Marketplace, you require a Windows Live ID account. However, when you create a Windows Live ID account, the are certain details of the account that will be permanently bound to your current country of residence. I am talking about the account billing details.</p>
<p>Consider this scenario. John was living in France working as a contractor when he got his Windows Phone. He had to create a Windows Live ID to join the Windows Phone Marketplace, and so he did. He registered a payment card and even bought several apps for his phone. Well, now John moved back to the UK. And now he wants to change his payment details for a UK-based credit card.</p>
<p>Well, guess what. John can&#8217;t do that. Even if users update their Windows Live ID details at <a href="https://account.live.com/summarypage.aspx" title="Summary page of one's account information at Windows Live, where users can change their Country/Region" target="_blank">accounts.live.com</a> and change their Country/Region to the country they are currently residents of, the Country/Region for billing information is disabled. Users will not be able to register a payment card (be it debit, credit or cash) from their new country of residence.</p>
<p>This means users will not be able to buy any new content with their existing Windows Live ID account using payment details from their new country of residence. Even though Microsoft operates around all EU member states. The only option suggest by Microsoft if for users that moved country to create a new Windows Live ID account. The inconvenience with this approach are enormous. Microsoft is seriously suggesting that EU citizens must have one Windows Live ID per country they lived in? For instance, in 10 years I lived in 4 different countries. And what digital rights management and all the content that users have acquired with their previous Windows Live IDs?</p>
<p>If you have a Xbox Live account prepare to add insult to the injury, because the same applies to Xbox Live content you might have bought, such as arcade games and add-ons. What gets me so disgruntled about this is that when I created my Windows Live ID ten years ago, I did so in order to join Xbox Live. Nowhere in their Terms and Conditions at the time I read that I would be forever bound to the country I was living in at the time. Since I created that Windows Live ID account I bought Xbox Live contents with it and used it for several other purposes, such as Microsoft Certifications. I use my current Windows Live ID for a lot of tasks and services. When I got my Windows Phone, I had NO IDEA that I would be bound to the Windows Phone Marketplace for the country which I was a former resident from when I signed in for Xbox Live.</p>
<p>What I found out is that by using certain prepaid Visa or MasterCard payment cards based in the country my Windows Live ID is bound to, I can in some cases by-pass Microsoft&#8217;s enforcement. The idea is that I can top-up my foreign prepaid card (from the same country where my Windows Live ID account is tethered to) with my local debit or credit card. However, Microsoft doesn&#8217;t like that and try to block the use of prepaid cards saying that they aren&#8217;t supported; which is puzzling, since they are getting paid for their content through legitimate means anyway, so what is the fuzz all about? Also, prepaid cards tend to charge customers for topping up their cards and/or an annual fee, and/or a transaction fee&#8230;</p>
<p>Bottom line: If you are an EU citizen that enjoy your freedom of movement in the continent and want to get a smart phone with a choice of services and apps, think twice before getting a Windows Phone. Same applies to Xbox Live content.</p>
<p class="warnbox"><strong>And it is about to get worse with Windows 8:</strong> Geoff Coupe wrote an article about this issue at his blog, and how it is likely that all this grievance will extend to Windows desktops with the upcoming Windows marketplace in Windows 8. You can read all about it <a href="http://gcoupe.wordpress.com/2012/02/23/i-dont-want-to-be-born-again/" title="I Don’t Want to be Born Again, by Geoff Coupe" target="_blank">here</a>.<br/><br />
And <a href="http://www.pedroinnecco.com/?p=1290" title="The entertainment industry’s war on consumers" target="_blank">here</a> are my subsequent thoughts about it.</br><br />
<strong>Get involved:</strong> For more information about this issue and how you can get involved to demand a change, visit <a href="http://www.itisourdata.com" target="_blank">www.itisourdata.com</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pedroinnecco.com/2012/02/warning-eu-citizens-about-microsoft/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Dynamics CRM: JScript vs workflow – Caveats</title>
		<link>http://www.pedroinnecco.com/2012/01/dynamics-crm-jscript-vs-workflow-caveats/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=dynamics-crm-jscript-vs-workflow-caveats</link>
		<comments>http://www.pedroinnecco.com/2012/01/dynamics-crm-jscript-vs-workflow-caveats/#comments</comments>
		<pubDate>Tue, 31 Jan 2012 15:09:48 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[Dynamics CRM]]></category>
		<category><![CDATA[customisation]]></category>
		<category><![CDATA[dynamics crm]]></category>
		<category><![CDATA[jscript]]></category>
		<category><![CDATA[workflow]]></category>

		<guid isPermaLink="false">http://www.pedroinnecco.com/?p=1103</guid>
		<description><![CDATA[JScripts in Dynamics CRM are a powerful feature to enhance the user interface in Dynamics CRM. We can use JScripts to perform calculations and validate fields in forms in order [...]]]></description>
			<content:encoded><![CDATA[<p>JScripts in Dynamics CRM are a powerful feature to enhance the user interface in Dynamics CRM. We can use JScripts to perform calculations and validate fields in forms in order to introduce a better user experience. However, JScripts are a client-side based, and only work with the desktop-based (main) forms. In other words, if the user is accessing Dynamics CRM through a mobile device displaying the mobile forms, or using a 3rd party client for a tablet device, the JScripts will not be loaded at all. Workflows on the other hand are server-based, and they will execute no matter which device and client is used to access Dynamics CRM.</p>
<p>This often raises the question of JScript versus workflows when customising Dynamics CRM, particularly when designing a <a href="http://www.pedroinnecco.com/?p=413" title="Dynamics CRM: Diving into the sales pipeline – Part 1">sales pipeline workflow</a>. In this posts I explain how to combine the usage of both JScript and workflows in order to get the best of both worlds, and the most out of Dynamics CRM.<span id="more-1103"></span></p>
<h2>Overview</h2>
<p>Dynamics CRM 2011 is a web-based application that uses a multi-tier architecture. This means that the Dynamics CRM platform serves as an intermediary between the client access users and the data. The application business logic sits in this intermediary bit, and this is where Dynamics CRM workflows are located. When a workflow is executed, it is executed at the server level, not at the client level (e.g.: Internet Explorer or Microsoft Outlook). JScripts on the other hand are interpreted at the client level.</p>
<h2>Considerations</h2>
<p>Consider my previous Sales Pipeline tutorial (see <a href="http://www.pedroinnecco.com/?p=880" title="Dynamics CRM: Diving into the sales pipeline – Part 2" target="_blank">second post of the series</a>). For the Opportunity record we added an option set (i.e.: a drop-down menu) where the user can select the stage of the sales pipeline for the opportunity is. The current sales pipeline stage, along with the user rating (e.g.: <em>Hot, Warm, Cold</em>) calculates the Probability for the opportunity record. We achieved this with the use of JScripts, which are quite handy since JScript provide users with an on-the-fly update. As the <strong>Pipeline Phase</strong> and <strong>Rating</strong> fields change, the <strong>Probability</strong> field is immediately recalculated.</p>
<p>However, since JScripts only work on main forms, this whole logic would be simply disregarded if the record is being edited through another method, such as through a mobile form , a web service call or a 3rd party client for tablet devices. How can we solve this issue?</p>
<p class="warnbox"><strong>About Mobile Express:</strong> Mobile Express is how Microsoft calls the mobile-friendly forms that can be used to access Dynamics CRM with mobile devices. Microsoft cleverly calls them &#8220;express&#8221; so they can argue that they are far from being a full-featured solution. So we must work around the limitations of these forms. Even though Microsoft calls them &#8220;express&#8221;, at the moment these mobile forms lack some fundamental functionality (such as disallowing users to edit records) so I am very reluctant to use them. I suggest you also avoid using them if you can.<br />
<br/><strong>Hacking Mobile Express:</strong> It is possible to modify the Mobile Express Cascading Style Sheet (CSS) files to hide the New, Edit and Delete buttons that would allow users to create or modify records bypassing any JScript you have. You can find the instructions on how to do it by at <a href="http://social.msdn.microsoft.com/Forums/en-GB/crm/thread/9d4165d2-08fb-451d-a0bb-97bbc4e49c84" title="MSDN CRM Forum: How to hide Mobile Express buttons - Solution by nrodri" target="_blank">this forum</a> post. <strong>Please bear in mind that this hack is NOT supported by Microsoft</strong>. Thanks to Nuno R Costa for the tip.</p>
<p>Consider now the workflows introduced in my Sales Pipeline tutorial (see <a href="http://www.pedroinnecco.com/?p=971" title="Dynamics CRM: Diving into the sales pipeline – Part 3" target="_blank">third post of the series</a>). If you look into the <strong>Sales Process</strong> workflow, you will notice that at every stage (<code>1 - Prospect, 2 - Proposal, 3 - Negotiation</code>) we wait for the <strong>Process Code</strong> (<code>salesstagecode</code>) field to change (which moves the workflow to its next stage). However the workflow doesn&#8217;t perform any actions.</p>
<h2>Solution</h2>
<p>The solution is to add an action at every stage to replicate the functionality of the JScript. Since workflows work at the server level, no matter what client or method was used to modify a record the workflow will be triggered as per its rules and its actions will take place. One might wonder if that is the case, then why bother with JScript at all. But remember when I said in the introduction of this post. JScript is all about enhancing the user experience, while a workflow works in the background, away from the user&#8217;s eyes. The issue, particularly for Dynamics CRM on-demand users, is to design a workflow using the built-in workflow designer and avoiding Visual Studio.</p>
<p>So let&#8217;s get back to the Sales Pipeline example. Consider the following screenshot of the Sales Pipeline workflow:</p>
<p style="text-align: center;"><a href="http://www.pedroinnecco.com/files/crm_sales-pipeline3_01c.png"><img src="http://www.pedroinnecco.com/files/crm_sales-pipeline3_01c-300x229.png" alt="" title="Post Mortem workflow: Design (revisited)" width="300" height="229" class="aligncenter size-medium wp-image-1045" /></a></p>
<p>Notice that under each stage, between the lines <code>Wait Until Opportunity:Process Code equals [...]</code> and <code>Otherwise, wait until Opportunity:Status equals [...]</code> there is a line that says <code>Select this row and click add step</code>. This is because there are no actions being executed there. What we want to do is select this line at each stage, and add the appropriate actions to replicate the functionality of the JScript.</p>
<p>For example under the first stage (<code>1 - Prospect</code>) we would add an action to change the value of the <strong>Sales Pipeline</strong> field to <code>2 - Proposal</code>. Moreover, we would need to add an additional wait condition to update the <strong>Probability</strong> field according to the option selected in the <strong>Rating</strong> option set. For more information on workflow conditional waiting, please refer to the <a href="http://www.pedroinnecco.com/?p=971" title="Dynamics CRM: Diving into the sales pipeline – Part 3" target="_blank">third post</a> of my sales pipeline tutorial.</p>
<h2>Final Words</h2>
<p>At first sight, if we could design a Dynamics CRM deployment that relies completely on workflows and no JScripts at all, it might seem as we could have a fail-proof business process. However the server-side nature of workflows at the platform layer makes them more linear and less receptive for situations in which users require a more dynamic response, such as on-the-fly calculations and conditional formatting of fields. When dealing with JScripts and workflows don&#8217;t start from the premise that you must choose either one of them, but how you can combine both of them. Finally, bear that JScripts only apply to browser-based forms (i.e.: Main Forms). In other words, all of your JScripts will be disregarded if a user manipulates data through Mobile Express forms, or through some sort of integration with another product.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pedroinnecco.com/2012/01/dynamics-crm-jscript-vs-workflow-caveats/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dynamics CRM: Considerations when customising address fields</title>
		<link>http://www.pedroinnecco.com/2012/01/dynamics-crm-considerations-when-customising-address-fields/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=dynamics-crm-considerations-when-customising-address-fields</link>
		<comments>http://www.pedroinnecco.com/2012/01/dynamics-crm-considerations-when-customising-address-fields/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 17:18:34 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[Dynamics CRM]]></category>
		<category><![CDATA[address]]></category>
		<category><![CDATA[dynamics crm]]></category>

		<guid isPermaLink="false">http://www.pedroinnecco.com/?p=1152</guid>
		<description><![CDATA[The perceived issue of how to store addresses in computer systems always fascinated me. Not because of any apparent complexity one might believe that exists when handling addresses, but mostly [...]]]></description>
			<content:encoded><![CDATA[<p>The perceived issue of how to store addresses in computer systems always fascinated me. Not because of any apparent complexity one might believe that exists when handling addresses, but mostly because of people&#8217;s undeserved anxiety around the subject. And in Dynamics CRM it is no different.</p>
<p>The issue tends to surround the myth that countries and regions with different subdivisions would require complex requirements for address handling. I came across a couple of clients who believe that they require such a complex solution that  their Dynamics CRM deployments almost came onto  a halt because of it such hurdle. I the end, the solution relies not on complex customisation, but on standards compliance, a little bit of compromising, but most importantly: common sense.<span id="more-1152"></span></p>
<h2>What is the issue?</h2>
<p>Well if you ask me, there is no issue. But here is the source of discord. Most countries and regions in the world (with the exception of some microstates) have constituent entities (i.e.: top-level subdivisions), which in different countries tend to carry different names. Here are four examples of countries and the name of their respective constituent entities:</p>
<ul>
<li>Germany &#8211; Federated States</li>
<li>Uruguay &#8211; Departments</li>
<li>Sweden &#8211; Counties</li>
<li>Switzerland &#8211; Cantons</li>
</ul>
<p>By default Dynamics CRM has the following fields to store address information:</p>
<ul>
<li>Address Line 1</li>
<li>Address Line 2</li>
<li>Address Line 3</li>
<li>City</li>
<li>State/Province</li>
<li>Country/Region</li>
</ul>
<p>Now let&#8217;s consider the chart below, which is a rough representation of how addresses are hierarchically defined:</p>
<p style="text-align: center;"><img src="http://www.pedroinnecco.com/files/crm_address-issue_00.png" alt=""Address hierarchy diagram<a href="http://www.pedroinnecco.com/files/crm_address-issue_02.png"></p>
<p>Many customers tend to see as an issue that in Dynamics CRM the top-level constituency entity of a country or region is named as <strong>State/Province</strong>, gripping on arguments such as &#8220;<em>but what if here in country X we use counties rather than states or provinces?</em>&#8221; As a result, customers tend to add custom fields for specific subdivisions in hope to use them with the relevant countries/regions. However, consider the following cut-out (i.e.: resumed) diagram of client records in a database:</p>
<p style="text-align: center;"><img src="http://www.pedroinnecco.com/files/crm_address-issue_02.png" alt="" title="Accounts address list table" width="612" height="98" class="aligncenter size-full wp-image-1171" /></p>
<p>If we add fields for every possible subdivision we want to use, we will end up with a a plethora of unused fields for every account record we have. From the example above, although ACME is a company based in Germany (a country with federal states), even though we only need to use the state field for this account, the account record still has the fields for all other possible subdivisions we created (cantons, departments etc).</p>
<p>From an technical perspective this is a mess which would make database designers and technical architects twitch their face with disgust. But from the end-user perspective this could also be a nightmare for reports, mail merge and other tasks that rely around data manipulation of account records.</p>
<p>If you still doubt this is a bad idea, then consider countries that have more than just one type of subdivision. In the United Kingdom for instance, England has 27 two-tier counties, 32 London boroughs, 36 metropolitan districts, 55 unitary authorities and 1 city corporation. Northern Ireland has 26 districts. Scotland has 32 council areas and Wales has 22 unitary authorities. Following the logic of creating a field for each subdivision (and being finicky about it), shouldn&#8217;t we create a field for each of these possible subdivisions? And for the record, the UK is far from being an exception. There are several other countries (Russia being another example) that has more than one type of constituent entity.  </p>
<p>If this was really an issue, every single logistics company out there would be in shambles. Your FedEx post for London England would end-up in the Faroe Islands, or the Amazon order you placed to be delivered in Moscow would end up in Guam. How come these companies are still standing?</p>
<h2>Recommendations</h2>
<p>My solution is plain simple. When adding addresses, consider the <strong>State/Province</strong> field the top-level constituent entity, regardless if for the address in question is for a state, province, department, canton, oblast or emirate. The City field should then be used by city, town or village.</p>
<h3>It is just a label</h3>
<p>With a little bit of common sense a user will understand that when filling an address, Bern being a Swiss Canton and therefore the top-level constituent entity of A Swiss address, should be filled in the <strong>State/Province</strong> field. However if the &#8220;<em>State/Province</em>&#8221; label really bothers you, you could use a JScript bound to the <strong>Country/Region</strong> field to change the &#8220;State/Province&#8221; label according to the selected country/region (this will work best if you <a href="http://www.pedroinnecco.com/?p=491" title="Dynamics CRM: Adding a Country/Region option set using ISO 3166-1" target="_blank">use an option set</a> for the country/region field).</p>
<h3>City field vs State/Province field</h3>
<p>In some cases it might be unnecessary to have both City and State/Province fields filled in. The first question you address is what sort of address information should be included in correspondences to this address.</p>
<p>This is often the case in the UK since only the address along with the city (or town, or village) is required along with the post code. For example when filling an address for London, typing London as the city should suffice for postal records. However, the second question you also need to consider is if State/Province is required for any of your business processes such as workflows, or reports. If that is the case then again the solution relies on common sense, and also some user training. Some solutions could be:</p>
<ul>
<li>Type <em>London</em> for both City and State/Region</li>
<li>Type the London Borough (or City of London) in City, and <em>London</em> in State/Province</li>
</ul>
<p>Keep in mind the following: When filling addresses, having extra information is better than missing information. One might think it is irrelevant to capture both <em>Gloucester</em> in the City field and <em>Goucestershire</em> in the State/Province field and that such address label would look unsightly. However when dealing with databases I rather have consistency over aesthetics. An address label is a means to an end and it is likely that it will end up in the bin as soon as the letter received by its recipient. </p>
<h3>Beware of the County field</h3>
<p>Dynamics CRM does provide a county field (not used by default) for the several entities with address-related fields (e.g.: Accounts, Contacts, Competitors, etc). However, unless your are planning to use Dynamics CRM only with countries or regions that has counties as their constituent entities, I strongly suggest you NOT to use for the previously mentioned reasons.</p>
<p>Another option would be that when filling an address of a country/region with county constituencies, we sync the value of the <strong>County</strong> and the <strong>State/Province</strong> fields through the use of a workflow or JScript (in such case, one of these fields would be hidden in the entity form).</p>
<p>In some exceptional cases a country/region can have counties not as their top level constituent entity. The Republic of Ireland is a good example, where its top level constituency of &#8220;Province&#8221; is subdivided into counties (see <a href="http://en.wikipedia.org/wiki/ISO_3166-2:IE" title="Wikipedia article about ISO 3166-2 for the Republic of Ireland" target="_blank">ISO 3166-2:IE</a>). However in Ireland&#8217;s case nobody uses provinces for address purposes. But in some cases provinces might be required for reporting, business processes (such as workflows) or integration with other systems. so a combination of both <strong>County</strong> and <strong>State/Province</strong> fields might be required. Again, it is all about common sense and data integrity.</p>
<h2>Final thoughts</h2>
<p>The idea of this post is to give some guidance when customising Dynamics CRM around business requirements that might arise for capturing address information. It is important that such requirements are realistic considering the advantages and limitations of computer science, which is: computers think through binary operations; not as humans do! Therefore there must be a compromise between usability and system architecture in order to avoid bad data. Bottom line; it is all about common sense.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pedroinnecco.com/2012/01/dynamics-crm-considerations-when-customising-address-fields/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Dynamics CRM: Diving into the sales pipeline – Part 3</title>
		<link>http://www.pedroinnecco.com/2011/10/dynamics-crm-sales-pipeline-3/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=dynamics-crm-sales-pipeline-3</link>
		<comments>http://www.pedroinnecco.com/2011/10/dynamics-crm-sales-pipeline-3/#comments</comments>
		<pubDate>Mon, 17 Oct 2011 10:39:09 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[Dynamics CRM]]></category>
		<category><![CDATA[customisation]]></category>
		<category><![CDATA[dynamics crm]]></category>
		<category><![CDATA[sales pipeline]]></category>
		<category><![CDATA[workflow]]></category>

		<guid isPermaLink="false">http://www.pedroinnecco.com/?p=971</guid>
		<description><![CDATA[In my previous post of this series we discussed how to apply our previously defined sales pipeline through the customisation of the Opportunity entity form. We went through the design [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.pedroinnecco.com/?p=880" title="Dynamics CRM: Diving into the sales pipeline - Part 2">In my previous post of this series</a> we discussed how to apply our previously defined sales pipeline through the customisation of the Opportunity entity form. We went through the design of the Opportunity form, which included the addition of fields built-in fields which aren&#8217;t part of the default form, and we added some scripts for the calculation of our probability matrix.</p>
<p>In this final post we will go through the creation of some workflows that will be part of our sales pipeline process.<span id="more-971"></span></p>
<h2>Overview of the processes</h2>
<p>We are going to create three workflows for the Opportunity entity. One of these workflows, the main one entitled <em>Sales Process</em>, will be triggered with the creation of an opportunity. This workflow is the one which the Sales Pipeline report will use for the sales pipeline phases. The second workflow entitled <em>Sales Process &#8211; Post Mortem</em> is a child process, which will be called by the main <em>Sales Process</em> workflow when the opportunity is marked as lost or won. Finally, the third workflow entitled <em>Sales Process &#8211; Reopen of Opportunity</em> will be triggered only when an opportunity is reopened (that is, it status changes from closed to open).</p>
<p>So let&#8217;s start by adding the first workflow. I assume you&#8217;re already logged into Dynamics CRM through an account that has administrative or customisation privileges.</p>
<h2>Sales Process workflow</h2>
<p>As mentioned in a previous post of this series, the default Sales Pipeline report that comes with Dynamics CRM relies on a workflow of the Opportunity entity to show the different stages of the Sales Pipeline. Therefore we are going to create a workflow for this purpose with the same stages of our sales pipeline as we did to customise the Opportunity form in my previous post.</p>
<p>All that this workflow is going to do is to move through its stages as the sales process progresses so the Sales Pipeline report can make use of it. However, you might as well add your own actions to the stages of this workflow if you wish to do so.</p>
<ol>
<li>Add a new blank process of the category workflow for the entity Opportunity entitled <code>Sales Process</code>:</br><br />
Process name: <code>Sales Process</code><br />
Entity: <code>Opportunity</code><br />
Category: <code>Workflow</code><br />
Type: <code>New blank process</code></br><br />
Click on <strong>OK</strong> to confirm your settings and load the workflow design window.</li>
<p class="infobox"><strong>Editing workflows:</strong> It doesn&#8217;t matter what name you give to your workfow and you can also rename and modify workflows at a latter stage if you want. However, in order for a workflow to work it must be activated, and activated workflows can&#8217;t be modified. If you wish to modify a workflow at a latter stage, whether to change its name or to modify its actions, you will have to deactivate the workflow.</p>
<li>In the workflow design window under the <strong>General</strong> tab, make sure you set the process properties as follows:<br/><br />
<table>
<tr>
<td><a href="http://www.pedroinnecco.com/files/crm_sales-pipeline3_01.png"><img src="http://www.pedroinnecco.com/files/crm_sales-pipeline3_01-300x120.png" alt="Process Name: Sales Process; Activate As: Process; Available to Run: As a child process; Scope: Organization; Start when: Record is created" title="Sales Process workflow: Properties" width="300" height="120" class="alignleft size-medium wp-image-1043" /></a></td>
<td>Process Name: Sales Process<br />
Activate As: <code>Process</code><br />
Available to Run: <code>As a child process</code><br />
Scope: <code>Organization</code><br />
Start when: <code>Record is created</code></td>
</tr>
</table>
</li>
<li>Next we will start adding the stages of the workflow. Click on <strong>Add Step</strong> and select <strong>Stage</strong> and name the first stage <code>1 - Prospect</code>. Repeat these steps to add two more stages: <code>2 - Proposal</code> and <code>3 - Negotiation</code>.</li>
<p class="warnbox"><strong>Workflow steps: Naming stages and describing actions</strong><br/>Dynamics CRM allow you to provide a name/description for every step in your workflow, which are mandatory for the stages of a workflow, but are optional for the sub-steps (i.e.: &#8220;actions&#8221;) within a stage.<br/><br/>Remember that the name of the stages will be used by the Sales Pipeline report, so for the sake of consistency they <u>must</u> reflect the same names we defined for the Sales Pipeline in the previous posts of this series.<br/><br/>However I will not be telling you what descriptions to use for the steps in each stage since this is irrelevant for the workflow to work, but you can refer to the screenshots below as they show the descriptions I have provided for the actions.</p>
<p>Now under each stage we must add a wait condition with a parallel wait branch. The idea is that the workflow is waiting either for the opportunity to move to the next stage, or for the opportunity to close. If the Process Code field (which is &#8220;disguised&#8221; as the Pipeline Phase field in the form) changes to the next option, then the workflow will move to the next phase. Otherwise, if the opportunity record is closed as lost or won, then call the Sales Process &#8211; Post Mortem workflow to deal with the closed opportunity, and stop the workflow.</p>
<li>Under the first stage (1 &#8211; Prospect), select the line that says <strong>Select this row and click Add Step</strong>. Click on <strong>Add Step</strong> and select <strong>Wait Condition</strong>.</li>
<li>Click where it says <strong><condition> (click to configure)</strong> and set the condition as: <code>Opportunity:Proccess Code equals [2 - Proposal]</code>.</li>
<li>Repeat the two previous steps (4 and 5) for the second stage. However, make sure that for this stage we are waiting for the condition <code>Opportunity:Process Code equals [3 - Negotiation]</code>.</li>
<li>Under the third and last stage will add a wait condition just as we did for the other two previous steps. However this time we want to configure the waiting condition to be <code>Opportunity:Status equals [Lost;Won]</code>.</li>
<p><br/>We should now have the steps configured for our workflow as the following screenshot:</p>
<p style="text-align: center;"><a href="http://www.pedroinnecco.com/files/crm_sales-pipeline3_01b.png"><img src="http://www.pedroinnecco.com/files/crm_sales-pipeline3_01b-300x115.png" alt="" title="Sales Process workflow: Design (partial)" width="300" height="115" class="alignnone size-medium wp-image-1044" /></a></p>
<p>The workflow as it is will move through the stages as the Opportunity&#8217;s Process Code field (again, which is &#8220;disguised&#8221; as Pipeline Phase field in the form) is updated. However, what if the opportunity is closed? For that we must account for other conditions. Our next step will be to create the workflow that will be called by this workflow when the opportunity closes.</p>
<li>For now, click on <strong>Save and Close</strong> so we can proceed to design our next workflow. We will come back to this workflow afterwards to add the required parallel wait branches.</li>
</ol>
<h2>Sales Process &#8211; Post Mortem workflow</h2>
<p>This next workflow is pretty straightforward. We are going to create a child workflow which will be called by our main Sales Process workflow when an opportunity is either lost or canceled, and perform given actions accordingly.</p>
<ol>
<li>Add a new blank process of the category workflow for the Opportunity entity entitled <code>Sales Process - Post Mortem</code>:</br><br />
Process name: <code>Sales Process - Post Mortem</code><br />
Entity: <code>Opportunity</code><br />
Category: <code>Workflow</code><br />
Type: <code>New blank process</code></br><br />
Click on <strong>OK</strong> to confirm your settings and load the workflow design window.</li>
<li>In the workflow design window under the <strong>General</strong> tab, make sure you set the process properties as follows:<br/><br />
<table>
<tr>
<td><a href="http://www.pedroinnecco.com/files/crm_sales-pipeline3_02.png"><img src="http://www.pedroinnecco.com/files/crm_sales-pipeline3_02-300x120.png" alt="Process Name: Sales Process - Post Mortem; Activate As: Process; Available to Run: As a child process; Scope: Organization" title="Sales Process - Post Mortem: Properties" width="300" height="120" class="alignleft size-medium wp-image-1046" /></a></td>
<td>Process Name: <code>Sales Process - Post Mortem</code><br />
Activate As: <code>Process</code><br />
Available to Run: <code>As a child process</code><br />
Scope: <code>Organization</code><br />
Start when: <code>Record is created</code></td>
</tr>
</table>
</li>
<li>Next we will design the workflow as per the screenshot below. Click on <strong>Add Step</strong> and select <strong>Stage</strong> and name the stage <code>X - Post Mortem</code>. <strong>Note:</strong> We are just adding this stage for consistency, since this workflow doesn&#8217;t require stages.</li>
<li>Select the line that says <strong>Select this row and click Add Step</strong>. Click on <strong>Add Step</strong> and select <strong>Check Condition</strong>.</li>
<li>Click where it says <strong>(click to configure)</strong> and set the condition as: <code>Opportunity:Status equals [Lost]</code>.</li>
<li>Click on the next line where it says <strong>Select this row and click Add Step</strong>. Click on <strong>Add Step</strong> and select <strong>Update Record</strong>. Make sure that where it says <strong>Update</strong> the <strong>Opportunity</strong> entity (the primary entity) is selected, and click on <strong>Set Properties</strong>. In the form, click on the <strong>Probability (%)</strong> field and type <code>0</code>, then click on <strong>Save and Close</strong> to return to the workflow designer.</li>
<p class="infobox"><strong>Editing read-only fields:</strong> If you remember from the previous post in the series, the <strong>Probability (%)</strong> field has been set as read-only when customising the Opportunity form. We will need to temporarily remove the read-only restriction of the Probability field and re-publish our customisation in order to be able to specify values for this field.</p>
<li>Back at the workflow designer, make sure that the last step we added is selected (the one that updates the Opportunity&#8217;s probability) then click on <strong>Add Step</strong> and select <strong>Stop Workflow</strong>. Make sure that where it says <strong>Stop workflow with status of</strong> the option <strong> Succeeded </strong> is selected.</li>
<li>Now click on the line that says <strong>If Opportunity:Status equals [Lost]</strong> in order to select the whole condition. Click on <strong>Add Step</strong> and select <strong>Conditional Branch</strong>.</li>
<li>At the line that says <strong>Otherwise</strong>, click where it says <strong>(click to configure)</strong> and set the condition as: <code>Opportunity:Status equals [Won]</code>.</li>
<li>Repeat the same steps as step 6 above. However, this time when setting the properties in the form, type <code>100</code> in the <strong> Probability (%)</strong> field.</li>
<li>Finally, repeat the same steps as step 7 above.</li>
<p><br/>We should now have the steps configured for our workflow as the following screenshot:</p>
<p style="text-align: center;"><a href="http://www.pedroinnecco.com/files/crm_sales-pipeline3_02b.png"><img src="http://www.pedroinnecco.com/files/crm_sales-pipeline3_02b-300x126.png" alt="" title="Sales Process - Post Mortem workflow: Design" width="300" height="126" class="alignnone size-medium wp-image-1047" /></a></p>
<li>Click on <strong>Save and Close</strong> so we can proceed to update the previous workflow.</li>
</ol>
<h2>Sales Process workflow &#8211; revisited</h2>
<p>Now we must update our Sales Process workflow so it can trigger the Sales Process &#8211; Post Mortem workflow we just created when an opportunity is closed. SO lets proceed to edit the Sales Process workflow.</p>
<ol>
<li>Under the first stage (1 &#8211; Prospect), click on the line that says <strong>Wait until</strong> in order to select the whole condition. Click on <strong>Add Step</strong> and select <strong>Parallel Wait Branch</strong>.</li>
<li>At the line that says <strong>Otherwise</strong>, click where it says <strong>(click to configure)</strong> and set the condition as: <code>Opportunity:Status equals [Lost;Won]</code>.</li>
<li>Click on the next line where it says <strong>Select this row and click Add Step</strong>. Click on <strong>Add Step</strong> and select <strong>Start Child Workflow</strong>. Make sure that where it says <strong>Start child workflow</strong> the Opportunity entity (the primary entity) is selected, and then select the <code>Sales Process - Post Mortem</code> workflow in the lookup field.</strong>
<li>Make sure that the last step we added is selected (the one that starts the child workflow) then click on <strong>Add Step</strong> and select <strong>Stop Workflow</strong>. Make sure that where it says <strong>Stop workflow with status of</strong> the option <strong> Succeeded </strong> is selected.</li>
<li>Repeat all previous steps (steps 1-4) for the second stage. Leave the last stage as it is.</li>
<p><br/>We should now have the steps configured for our workflow as the following screenshot:</p>
<p style="text-align: center;"><a href="http://www.pedroinnecco.com/files/crm_sales-pipeline3_01c.png"><img src="http://www.pedroinnecco.com/files/crm_sales-pipeline3_01c-300x229.png" alt="" title="Post Mortem workflow: Design (revisited)" width="300" height="229" class="alignnone size-medium wp-image-1045" /></a></p>
<p>The workflow now will move through the stages as the Opportunity&#8217;s Process Code field (again, which is &#8220;disguised&#8221; as Pipeline Phase field in the form) is updated. If the opportunity is closed (either lost or won) the workflow will call the Sales Process &#8211; Post Mortem workflow and stop the workflow as successful.</p>
<p class="infobox"><strong>Actions:</strong> You might have noticed that at each stage of our workflow, all that we do is wait we have added no actions to take place. The idea of this workflow is simply to support the Sales Pipeline report and introduce the design of workflows in the process. Feel free to add your own actions to these workflows if you wish to do.</p>
<li>Click on <strong>Save and Close</strong> so we can proceed to create our last workflow.</li>
</ol>
<p>Now consider this: The Sales Process workflow follows the life-cycle of an opportunity from the moment it is created. However, what would happen if a user re-opens an opportunity record? At the moment, nothing would happen. But we can create one final workflow to cover this scenario.</p>
<h2>Sales Process &#8211; Reopen of Opportunity</h2>
<p>This final workflow will be triggered when an opportunity status is changed. If the status is changed to open (i.e.: the opportunity is re-opened), then the Sales Process workflow will be called. Otherwise, the workflow will stop as succeeded.</p>
<ol>
<li>Add a new blank process of the category workflow for the entity Opportunity entitled Sales Process – Reopen of Opportunity:</br><br />
Process name: <code>Sales Process - Reopen of Opportunity</code><br />
Entity: <code>Opportunity</code><br />
Category: <code>Workflow</code><br />
Type: <code>New blank process</code></br><br />
Click on <strong>OK</strong> to confirm your settings and load the workflow design window.</li>
<li>In the workflow design window under the <strong>General</strong> tab, make sure you set the process properties as follows:<br/><br />
<table>
<tr>
<td><a href="http://www.pedroinnecco.com/files/crm_sales-pipeline3_03.png"><img src="http://www.pedroinnecco.com/files/crm_sales-pipeline3_03-300x120.png" alt="" title="Sales Process - Reopen of Opportunity: Properties" width="300" height="120" class="alignleft size-medium wp-image-1048" /></a></td>
<td>Process Name:  <code>Sales Process - Reopen of Opportunity</code><br />
Activate As: <code>Process</code><br />
Available to Run: <code>no option selected</code><br />
Scope: <code>Organization</code><br />
Start when: <code>Record status changes</code></td>
</tr>
</table>
</li>
<li> Click on <strong>Add Step</strong> and select <strong>Check Condition</strong>.</li>
<li>Click where it says <strong>(click to configure)</strong> and set the condition as: <code>Opportunity:Status equals [Open]</code>.</li>
<li>Click on the next line where it says <strong>Select this row and click Add Step</strong>. Click on <strong>Add Step</strong> and select <strong>Update Record</strong>. Make sure that where it says <strong>Update</strong> the <strong>Opportunity</strong> entity (the primary entity) is selected, and click on <strong>Set Properties</strong>. In the form, click on the <strong>Probability (%)</strong> field and type <code>5</code>, for the <strong>Rating</strong> field select <code>Cold</code> and for the <strong>Process Code</strong> field select <code>1 - Prospect</code> then click on <strong>Save and Close</strong> to return to the workflow designer.</li>
<li>Back at the workflow designer, make sure that the last step we added is selected (the one that updates the opportunity&#8217;s probability, rating and process code) then click on <strong>Add Step</strong> and select <strong>Start Child Workflow</strong>. Make sure that where it says <strong>Start child workflow</strong> the Opportunity entity (the primary entity) is selected, and then select the <code>Sales Process</code> workflow in the lookup field.</li>
<li>Make sure that the last step we added is selected (the one that starts the child workflow) then click on <strong>Add Step</strong> and select <strong>Stop Workflow</strong>. Make sure that where it says <strong>Stop workflow with status of</strong> the option <strong>Succeeded</strong> is selected.</li>
<li>Now click on the line that says <strong>If Opportunity:Status equals [Open]</strong> in order to select the whole condition. Click on <strong>Add Step</strong> and select <strong>Default Action</strong>.</li>
<li>Under <strong>Otherwise</strong> select the line that says <strong>Select this row and click Add Step</strong>. Click on <strong>Add Step</strong> and select <strong>Stop Workflow</strong>. Make sure that where it says <strong>Stop workflow with status of</strong> the option <strong>Succeeded</strong> is selected.</li>
<p><br/>We should now have the steps configured for our workflow as the following screenshot:</p>
<p style="text-align: center;"><a href="http://www.pedroinnecco.com/files/crm_sales-pipeline3_03b.png"><img src="http://www.pedroinnecco.com/files/crm_sales-pipeline3_03b-300x126.png" alt="" title="Sales Process - Reopen of Opportunity: Design" width="300" height="126" class="alignnone size-medium wp-image-1049" /></a></p>
<li>Click on <strong>Save and Close</strong> so we can proceed to activate our workflows.</li>
</ol>
<h2>Activating and testing the workflows</h2>
<p>After saving and publishing our workflows, our next step is to activate our workflows so we can test them.</p>
<ol>
<li>After activating the workflows, proceed to create an opportunity and save it without closing it.</li>
<li>If you click on <strong>Workflows</strong> under <strong>Procecces</strong> at the left-hand side navigation pane in the Opportunity form, you will be able to see the associated Sales Process workflow which has been triggered upon the creation of this Opportunity record.</li>
<li>Go back to the <strong>General</strong> tab of the Opportunity form and change the <strong>Pipeline Phase</strong> from <code>1 - Prospect</code> to <code>2 - Proposal</code>. Now if you go back to the associated workflow view (see previous step) and click on the Sales Process workflow, you can see its progress.</li>
<p style="text-align: center;"><a href="http://www.pedroinnecco.com/files/crm_sales-pipeline3_04.png"><img src="http://www.pedroinnecco.com/files/crm_sales-pipeline3_04-300x204.png" alt="" title="Sales Process: workflow progress" width="300" height="204" class="alignnone size-medium wp-image-1086" /></a></p>
<p class="warnbox"><strong>Workflow stages:</strong> Unfortunately Dynamics CRM 2011 workflow designer only allow a linear and sequential progression through the stages of a workflow. In practical terms, this means that from Stage 1 we can only progress to Stage 2, from Stage 2 to Stage 3 and so forth; and we can&#8217;t jump a stage or go backwards on stages. This is why we added the bonus JScript in the previous post of the series to enforce users to follow a linear and sequential progression. If you want to create a workflow that allow jumping back and forth through its stages, you will have do design the workflow using Visual Studio.<br/><br />
<strong>Update May/2012:</strong> Even though the Dynamics CRM 2011 workflow designed doesn&#8217;t allow us to jump stages (e.g.: like a &#8220;GOTO&#8221; statement), we could still progress through all the stages if a user jumps forward by adding additional conditionals, and even support users moving backwards through additional parallel wait branches and restarting the Sales Pipeline workflow as a child workflow from itself. Because this would significantly increase the complexity of this workflow, I will be covering this scenario in another post.</p>
<li>Now proceed to view all of the open opportunities. At the Ribbon, click on <strong>Run Report</strong> and select the <strong>Sales Pipeline</strong> report. When prompted to select records, select <strong>All applicable records</strong> then click on <strong>Run Report</strong>.</li>
<li>When the report finish to load, at the top where it says <strong>Group by Sales Process</strong> select <code>Sales Process</code> (the name of our workflow) from the drop-down. Where it says <strong>Group By</strong> select <code>Sales Stage</code>. Then click on <strong>View Report</strong> to update the report. We should now see the opportunities estimated revenue grouped by the sale stages.</li>
<p style="text-align: center;"><a href="http://www.pedroinnecco.com/files/crm_sales-pipeline3_04b.png"><img src="http://www.pedroinnecco.com/files/crm_sales-pipeline3_04b-300x231.png" alt="" title="Sales Pipeline Report" width="300" height="231" class="alignnone size-medium wp-image-1092" /></a></p>
<p>The report takes the sale stages from the stages of our Sales Process workflow. You might be wondering why couldn&#8217;t this report make use of the same field as the pipeline chart does in the previous post of this series. I asked myself the same question when I first came across this report. However it does make sense to have the report based on the workflow stages and the chart on an entity field; particularly if you have complex workflows and sub-stages for dealing with different products or business units.</ol>
<h2>Wrapping up</h2>
<p>Wow&#8230; That was a lot of writing. Through the course of this series we introduced a lot of concepts for creating a functional sales pipeline in Dynamics CRM 2011. Through the customization of the Opportunity entity we also introduced some useful JScripts which calculate fields and remove options from option sets. Also through the design of workflows we introduced the concepts of conditionals, waits and branches; as well the use of child workflows. I hope you enjoyed this series and that it can be a useful reference for those in the Dynamics CRM community. Thank you for stopping by!</p>
<h2>Bonus: Challenge yourself</h2>
<p class="helpbox"><strong>Update Jan/2012:</strong> Because the sales pipeline is only about open opportunities, we only covered the open stages of the opportunity in this series of posts (1 &#8211; Prospect, 2 &#8211; Proposal, 3 &#8211; Negotiation). However, let&#8217;s say that for consistency we would also like the Pipeline Phase field of a closed opportunity to show either &#8220;4 &#8211; Won&#8221; or &#8220;X &#8211; Lost&#8221;, in case someone opens the form of a closed opportunity record. How could we do that?</p>
<p>This can easily be done with by adapting our workflow to change the value of the <strong>Pipeline Phase</strong> (<code>stepname</code>) accordingly for when an opportunity is closed either as won or as lost. As for our <strong>Process Code</strong> (<code>salesstagecode</code>) field labeled as Pipeline Phase, we can either adapt our JScript to hide it when a form is disabled (using <code>CRM_FORM_TYPE == 4</code>) so users would only see the <strong>Pipeline Phase</strong>  (<code>stepname</code>) in the form footer when viewing inactive records. Alternatively, we can add two additional options to the <strong>Process Code</strong> (<code>salesstagecode</code>) and have them always hidden from the end-user in an editable form by adapting the bonus JScript proposed in the previous post. Then the workflow would update the value of the <strong>Process Code</strong> option set according to the close status of the opportunity (either as won or as lost).</p>
<p>Have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pedroinnecco.com/2011/10/dynamics-crm-sales-pipeline-3/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Dynamics CRM: Diving into the sales pipeline – Part 2</title>
		<link>http://www.pedroinnecco.com/2011/10/dynamics-crm-sales-pipeline-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=dynamics-crm-sales-pipeline-2</link>
		<comments>http://www.pedroinnecco.com/2011/10/dynamics-crm-sales-pipeline-2/#comments</comments>
		<pubDate>Thu, 06 Oct 2011 15:16:45 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[Dynamics CRM]]></category>
		<category><![CDATA[customisation]]></category>
		<category><![CDATA[dynamics crm]]></category>
		<category><![CDATA[jscript]]></category>
		<category><![CDATA[sales pipeline]]></category>

		<guid isPermaLink="false">http://www.pedroinnecco.com/?p=880</guid>
		<description><![CDATA[In my previous post of this series, we discussed some fundamental concepts of the sales pipeline and how Dynamics CRM handles the sales process. While considering the requirements of ACME [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://www.pedroinnecco.com/?p=413" title="Dynamics CRM: Diving into the sales pipeline – Part 1">my previous post of this series</a>, we discussed some fundamental concepts of the sales pipeline and how Dynamics CRM handles the sales process. While considering the requirements of ACME (a fictitious company), we defined the stages of their sales pipeline, and started to outline the functional specification of the opportunity entity, including the elaboration of an opportunity probability matrix.</p>
<p>In this post we will discuss how to apply what have been defined so far by covering the customisation of the Opportunity entity form, including some scripting.<span id="more-880"></span></p>
<p>So let&#8217;s start by customising the Opportunity form.</p>
<h2>Opportunity form: Adding and editing fields</h2>
<ol>
<li>Add the <strong>Process Code</strong> field (<code>salesstagecode</code>) above the <strong>Rating</strong> field (<code>opportunityratingcode</code>).</li>
<li>Edit the Process Code field properties. Under <strong>Display</strong>, change the field label to <code>Pipeline Phase</code>.</li>
<li>Now under <strong>Details</strong>, click on Edit to add the Pipeline Phase stages as options into the option set field, remembering the caveats concerning naming and numbering the pipeline phases we mentioned in the previous post. As per the previous post, we should add the following options:<br/><br />
<code>1 - Prospect<br />
2 - Proposal<br />
3 - Negotiation</code><br/><br />
Make sure to save and close the properties dialog for the Process Code field.</li>
<li>Back at the Opportunity form under Forecast Information, make the <strong>Probability</strong> field (<code>closeprobability</code>) read-only.</li>
<li>Add the <strong>Pipeline Phase</strong> field (<code>stepname</code>) just under the Probability field, which is the field used by the <em>Sales Pipeline Funnel Chart</em>. Change the properties of the field and make sure that under <strong>Visibility</strong>, the field is <strong>not</strong> selected as visible by default.</li>
</ol>
<p style="text-align: center;"><img src="http://www.pedroinnecco.com/files/crm2011_sales-pipeline2_01.png" alt="" title="Opportunity form: Forecast Information section" width="546" height="194" class="aligncenter size-full wp-image-911" /></p>
<p class="infobox"><strong>Our Goal: </strong>What we are going to achieve here is that using the Process Code field labeled (i.e.: &#8220;disguised&#8221;) as the Pipeline Phase field, users will be able to manualy select the Pipeline Phase in which the opportunity is at. The label of the option selected in this field will then be copied into the real Pipeline Phase field, which we just added as hidden in the form. Furthermore, we made the Probability field readonly because its value will be automatically calculated based on the combination of values from the Pipeline Phase and Rating fields, following our probability matrix we defined in the previous post.</p>
<h2>Adding our JScript: Creating the web resource</h2>
<p>In order to achieve the goal mentioned above, we must add some code that will work with the customisation we did so far.</p>
<ol>
<li>Create a new JScript web resource and name it <code><span style="color: #0000ff;">new_</span>SalesPipeline</code>.</li>
<li>Add the following code into the web resource:</li>
<pre class="brush: jscript; title: ; notranslate">
SalesPipelineProbCalc = function() {
  var CRM_FORM_TYPE = Xrm.Page.ui.getFormType();
  if (CRM_FORM_TYPE == 4 || CRM_FORM_TYPE == 3) { return; }

	// Get value of Pipeline Phase set by user
	if (Xrm.Page.getAttribute(&quot;salesstagecode&quot;).getSelectedOption() != null)
	{var val_salesstagecode = Xrm.Page.getAttribute(&quot;salesstagecode&quot;).getSelectedOption().value;}
	else {var val_salesstagecode = null;}

	// Get text of Pipeline Phase set by user (this text should be the same for all languages)
	if (Xrm.Page.getAttribute(&quot;salesstagecode&quot;).getSelectedOption() != null)
	{var txt_salesstagecode = Xrm.Page.getAttribute(&quot;salesstagecode&quot;).getSelectedOption().text;}
	else {var txt_salesstagecode = null;}

	 // Set the text of Pipeline Phase field
	Xrm.Page.getAttribute(&quot;stepname&quot;).setValue(txt_salesstagecode);

	// Set the submition mode of closeprobability (which is set as read-only) in order to commit the value when saving the record
	var closeprobabilityAttr = Xrm.Page.getAttribute(&quot;closeprobability&quot;);
	closeprobabilityAttr.setSubmitMode(&quot;always&quot;);

	// Get value of the Rating selected by user
	if (Xrm.Page.getAttribute(&quot;opportunityratingcode&quot;).getSelectedOption() != null)
	{var val_rating = Xrm.Page.getAttribute(&quot;opportunityratingcode&quot;).getSelectedOption().value;}
	else {var val_rating = null;}

	// Calculation of Close Probability Rating as per Phase X Rate matrix
	if (val_salesstagecode == 1 &amp;&amp; val_rating == 3)
	{ Xrm.Page.getAttribute(&quot;closeprobability&quot;).setValue(10); }
	else if (val_salesstagecode == 1 &amp;&amp; val_rating == 2)
	{ Xrm.Page.getAttribute(&quot;closeprobability&quot;).setValue(25); }
	else if (val_salesstagecode == 1 &amp;&amp; val_rating == 1)
	{ Xrm.Page.getAttribute(&quot;closeprobability&quot;).setValue(50); }
	else if (val_salesstagecode == 2 &amp;&amp; val_rating == 3)
	{ Xrm.Page.getAttribute(&quot;closeprobability&quot;).setValue(20); }
	else if (val_salesstagecode == 2 &amp;&amp; val_rating == 2)
	{ Xrm.Page.getAttribute(&quot;closeprobability&quot;).setValue(50); }
	else if (val_salesstagecode == 2 &amp;&amp; val_rating == 1)
	{ Xrm.Page.getAttribute(&quot;closeprobability&quot;).setValue(75); }
	else if (val_salesstagecode == 3 &amp;&amp; val_rating == 3)
	{ Xrm.Page.getAttribute(&quot;closeprobability&quot;).setValue(40); }
	else if (val_salesstagecode == 3 &amp;&amp; val_rating == 2)
	{ Xrm.Page.getAttribute(&quot;closeprobability&quot;).setValue(75); }
	else if (val_salesstagecode == 3 &amp;&amp; val_rating == 1)
	{ Xrm.Page.getAttribute(&quot;closeprobability&quot;).setValue(95); }
	else { Xrm.Page.getAttribute(&quot;closeprobability&quot;).setValue(0); }

}
</pre>
<li>Save your changes and make sure to publish the customisation.</li>
</ol>
<p class="warnbox"><strong>A warning on pipeline phases:</strong> At the moment, users can move both forward and backwards in the sales pipeline stages without any limitations. For instance, a user could jump from step 1 to 3, or move backwards from step 2 to 1. There are two issues with at hand. First, I personally don&#8217;t think an opportunity can go backwards; it can either go forward or be cancelled/lost. Second, the Sales Pipeline report is based on steps within a workflow that we&#8217;re yet to create (which we will cover in my next post), and workflows created within Dynamics CRM doesn&#8217;t allow us to jump backward on steps.<br/><br />
A workaround would be to add a JScript that prevent users from moving backward on the pipeline phases. See the &#8220;bonus JScript&#8221; section below for further information.</p>
<h2>Opportunity form: Binding JScript into form and fields</h2>
<p>Now that we added our JScript as a web resource, we must bind it into the Opportunity form and into field events to ensure the calculation will take place when the user changes the correspondent values within the form. So let&#8217;s go back to customise the Opportunity form.</p>
<ol>
<li>Click the <strong>Form Properties</strong> button located in the Ribbon. In the Form Properties dialog under the <strong>Events</strong> tab,  click on <strong>Add</strong> under the <strong>Forms Libraries</strong> section and select the <code><span style="color: #0000ff;">new_</span>SalesPipeline</code> web resource we created previously. Then close the Form Properties.</li>
<li>Double click on the <strong>Process Code</strong> field (which we labeled Pipeline Phase) in order to bring its properties. In the Field Properties dialog under the <strong>Events</strong> tab,  click on <strong>Add</strong> under the <strong>Event Handlers</strong> section.
<li>On the Handler Properties dialog, where it says <strong>Function</strong>, type in <code>SalesPipelineProbCalc</code>, which is the name of the function we created in the <code><span style="color: #0000ff;">new_</span>SalesPipeline</code> web resource. Then click on OK, then OK again in the previous dialog to confirm our customisation.</i>
<li>Repeat the two previous steps (2, and 3) for the <code>Rating</code> field.</li>
<li>Save the form and publish the customisation.</li>
</ol>
<p class="infobox"><strong>What we just did:</strong> We have now added the JScript library we created (i.e.: the JScript web resource) into the Opportunity form and bound the SalesPipelineProbCal into the onChange event for the Process Code (&#8220;disguised&#8221; as Pipeline Phase) and Rating fields. So when the user changes the value of either one of these fields, the value within the Probability field will change accordingly as per the Probability Matrix we defined previously.<br/><br />
<strong>onLoad Form:</strong> We could have also added this function to the form&#8217;s onLoad event. This means that as soon as the form loads, the script will be executed. The script contains a conditional at the top that checks if the form isn&#8217;t read-only (e.g.: if viewing a closed opportunity) in order to execute the calculation.</strong> </p>
<h2>Testing our solution</h2>
<p>When can now go ahead and test our solution by creating an opportunity. We can manually specify the pipeline phase in which the opportunity is at, and this will reflect in the Pipeline Funnel chart. We can also give our opportunity the rating of <em>hot</em>, <em>warm</em> or <em>cold</em>, and along with the pipeline phase selected, the system will automatically calculate the probability for closing the opportunity.</p>
<h2>Bonus JScript: Filtering option set values</h2>
<p>In order to prevent users from jumping backward or skipping phases from the sales pipeline, we can filter the options available within the <strong>Pipeline Phase</strong> option set based on the current value with a simple JScript:</p>
<pre class="brush: jscript; title: ; notranslate">
SalesPipelineOptFilter = function() {
  var CRM_FORM_TYPE = Xrm.Page.ui.getFormType();
  if (CRM_FORM_TYPE == 4 || CRM_FORM_TYPE == 3) { return; }

	// Get value of Pipeline Phase set by user
	if (Xrm.Page.getAttribute(&quot;salesstagecode&quot;).getSelectedOption() != null)
	{var val_salesstagecode = Xrm.Page.getAttribute(&quot;salesstagecode&quot;).getSelectedOption().value;}
	else {var val_salesstagecode = null;}

	if (val_salesstagecode == 1)
	{ Xrm.Page.getControl(&quot;salesstagecode&quot;).removeOption(3); }

	else if (val_salesstagecode == 2)
	{ Xrm.Page.getControl(&quot;salesstagecode&quot;).removeOption(1); }

	else if (val_salesstagecode == 3)
	{
	Xrm.Page.getControl(&quot;salesstagecode&quot;).removeOption(1);
	Xrm.Page.getControl(&quot;salesstagecode&quot;).removeOption(2);
	}

}
</pre>
<p>Make sure you add this JScript on the <strong>onLoad</strong> event of the form as well as in the <strong>onChange</strong> event of the <strong>Process Code</strong> field (<code>salesstagecode</code>) field (labeled as Pipeline Phase in our customised form).</p>
<h2>Coming up next: Creating a workflow</h2>
<p><a href="http://www.pedroinnecco.com/?p=971" title="Dynamics CRM: Diving into the sales pipeline - Part 3">In my next post</a> we will be discussing how to create workflows to support our customisation. This is important if we want to use the default Sales Pipeline report that comes with Dynamics CRM.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pedroinnecco.com/2011/10/dynamics-crm-sales-pipeline-2/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Steve Jobs: 1955-2011</title>
		<link>http://www.pedroinnecco.com/2011/10/steve-jobs/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=steve-jobs</link>
		<comments>http://www.pedroinnecco.com/2011/10/steve-jobs/#comments</comments>
		<pubDate>Thu, 06 Oct 2011 14:33:50 +0000</pubDate>
		<dc:creator>Pedro</dc:creator>
				<category><![CDATA[Current Affairs]]></category>
		<category><![CDATA[IT]]></category>

		<guid isPermaLink="false">http://www.pedroinnecco.com/?p=934</guid>
		<description><![CDATA[I started using Windows 3.0 at the age of 12 and even though I worked with a lot of different systems, from Linux and OS/2 to BSD (and a few [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.pedroinnecco.com/files/apple.jpg" alt="" title="Apple" width="150" height="150" class="alignright size-full wp-image-946" />I started using Windows 3.0 at the age of 12 and even though I worked with a lot of different systems, from Linux and OS/2 to BSD (and a few times, Apple OSes), I have pretty much solidified my profession career with Microsoft products.</p>
<p>I saw Jobs as a difficult man who mistreated his employees, and I never understood his value to the market. That is, until I did my Masters Degree and I was introduced to the concept of industry paradigms.</p>
<p>Regardless of any rivalry feeling one can feel on &#8220;Apple Vs Windows&#8221; subject, Steve Jobs was undeniably a visionary and a <strong>paradigm pioneer</strong> who challenged concepts and developed new markets and trends. Before the iPod, the digital music players were all but a joke, and the iPad succeeded to launch the tablet industry where others previously failed.</p>
<p>The world will be less innovative without him. My sympathies to Apple and his family and friends.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pedroinnecco.com/2011/10/steve-jobs/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

