If you enter a lot of products in Dynamics CRM, this JavaScript tip will save you time. We’ll review the JavaScript you can use to allow the user to see the ‘Price’ from the Price List for a selected Product. This can be used/modified for Quote Product, Order Product, or Invoice Product. The example below is for Opportunity Product. (In our next blog, we’ll cover another example where user has already selected the Product, but upon changing the Unit, the appropriate ‘priceperunit’ value is populated.)

Once a user has selected the Product and Unit, now we have enough information to target the Price from the parent Price List. The JavaScript I have provided below will pull the Price from the associated ‘Price List Item’ (using the ProductId guid, Unit guid, and Price List guid) and populate the ‘Price per Unit’ field, all before saving! This will save time, allowing user to verify the price before they create an Opportunity Product record.

Use Javascript to Update price per unit

Notice! – Before JavaScript will work, make sure to add the SDK.REST library, JQuery, and JSON2 library. These libraries are found in the SDK, available for download. The files must be added as web resources and added to the Form Library for Opportunity Product. Also, this JavaScript must be added as web resource and to trigger upon the OnChange event for Product. See below.

So let’s go through this step by step. (Some of the images may appear small. For a bigger view, right click and select View Image. JavaScript is also posted at the bottom of the blog post.) We started by checking to make sure the Product has been selected on the form, and store that GUID in ‘productFieldId’. We check to make sure not null, then continue.

Once we have the productField Guid, we can build our oData query for Ajax. Here we are grabbing the page context, the server Url, adding the DataPath (notice this is for CRM 2011 On-premise). As for oDataSelect, we add our predefined oData Query that we generated using the OData Query Designer. Notice I inserted our productFieldId into the query to have it return the DefaultUoMId (default unit for the product).

NOTICE! – You will want to double check your own value for oDataPath as it may be different for your On-Premise or Online Dynamics CRM.

Now we can conduct our Ajax call. The Ajax call itself won’t return the GUID to our main method, but will call a separate function upon success. This success function will implicitly return two values, data and status. If we want to pass along more parameters, I must call another method that will allow me to pass more than just data and status. Since I will need oDataPath and productFieldId in our next Ajax call, I will pass these along to my custom function – NowHaveDefaultUnitGuid()

Once in the custom function, we will store the returned Unit GUID in defaultUnitGUID. We will also need to grab the parent Opportunity GUID to include in our next query. We will check to make sure not null and continue.

Here we have used the passed in oDataPath parameter to include in our next query. Notice that the Opportunity GUID is inserted into the query string to return PriceLevelId – or also known as the Price List Guid. Upon success, we will call the custom function NowWeHaveEverything.

This will be our last Ajax call to return us the Price List Item field value for Amount (this is what will populate price per unit). Here we take the passed parameter data and sotre the PriceLevelId guid into PriceLevelId. Notice we use all three GUID’s in our Odata query.

Here upon success, we call our custom function havePrice and pass data and the defaultUnitGUID we passed along from earlier.

Here we check to make sure the passed in defaultUnitGUID is not null, then proceed to store the Amount value in priceListItemAmount. Our last step is to update these values on the form, and also set the Unit using the defaultUnitGUID.

Voila! That’s it!

JavaScript Below:

[sourcecode language="JavaScript"]</p>
<p>function updateProductPrice(){</p>
<p>//Developed by PowerObjects 11/9/2012</p>
<p>//This jscript is intended to fire off on the OnChange event of the Product lookup on Opportunity Products</p>
<p>//Once user inputs a product, the default unit for the product will set, and price per unit, from the Price List Item, will populate below</p>
<p>//This javascript assumes there are price lists.</p>
<p>var productField = Xrm.Page.getAttribute(‘productid’).getValue();</p>
<p>var productFieldId = productField[0].id;</p>
<p>if (productFieldId != null){</p>
<p>//build the query to get the default unit</p>
<p>var pagecontext = Xrm.Page.context;</p>
<p>var serverUrl = pagecontext.getServerUrl();</p>
<p>var oDataPath = serverUrl + "/XRMServices/2011/OrganizationData.svc/";</p>
<p>var oDataSelect = oDataPath + "ProductSet?$select=DefaultUoMId&amp;amp;$filter=ProductId eq guid’" + productFieldId + "’";</p>
<p>//Start AJAX call to get default unit guid from product</p>
<p>$.ajax({</p>
<p>type: "GET",</p>
<p>contentType: "application/json; charset=utf-8",</p>
<p>datatype: "json",</p>
<p>url: oDataSelect,</p>
<p>beforeSend: function (XMLHttpRequest) { XMLHttpRequest.setRequestHeader("Accept", "application/json"); },</p>
<p>success: function (data,status) { NowHaveDefaultUnitGuid(data,status,productFieldId,oDataPath);},</p>
<p>error: function (XmlHttpRequest, textStatus, errorThrown) {</p>
<p>alert(‘OData Select Failed: ‘ + errorThrown + ". There is no default unit associated with product");</p>
<p>}</p>
<p>});</p>
<p>}</p>
<p>}</p>
<p>function NowHaveDefaultUnitGuid(data, status, productFieldId, oDataPath) {</p>
<p>//we are passing the oDataPath and productFieldId since we will still need these variables</p>
<p>var defaultUnitGUID = data.d.results[0].DefaultUoMId;//retrieved defaultUnit guid</p>
<p>var opportunityId = Xrm.Page.getAttribute(‘opportunityid’).getValue();</p>
<p>if (opportunityId != null)</p>
<p>{</p>
<p>var oDataSelect = oDataPath + "OpportunitySet?$select=PriceLevelId&amp;amp;$filter=OpportunityId eq guid’" + opportunityId + "’";</p>
<p>//start AJAX call for the parent price list guid</p>
<p>$.ajax({</p>
<p>type: "GET",</p>
<p>contentType: "application/json; charset=utf-8",</p>
<p>datatype: "json",</p>
<p>url: oDataSelect,</p>
<p>beforeSend: function (XMLHttpRequest) { XMLHttpRequest.setRequestHeader("Accept", "application/json"); },</p>
<p>success: function (data,status) { NowWeHaveEverything(data,status,productFieldId,defaultUnitGUID,oDataPath);},</p>
<p>error: function (XmlHttpRequest, textStatus, errorThrown) {</p>
<p>alert(‘OData Select Failed: ‘ + errorThrown + ". There is no parent price list");</p>
<p>}</p>
<p>});</p>
<p>}</p>
<p>}</p>
<p>function NowWeHaveEverything(data, status, productFieldId,defaultUnitGUID, oDataPath) {</p>
<p>//now that we have the pricelist guid, default unit guid, we can lookup the price list item to pull the amount value</p>
<p>var priceLevelId = data.d.results[0].PriceLevelId.Id; //retrieved pricelevel</p>
<p>//start AJAX clal for Price List Item entities = Price List GUID and Product Guid and Unit Guid and return the Amount on that price list item. This will return one results.</p>
<p>var oDataSelect2 = oDataPath + "ProductPriceLevelSet?$select=Amount&amp;amp;$filter=(PriceLevelId/Id eq guid’" + priceLevelId + "’ and ProductId/Id eq guid’"+ productFieldId +</p>
<p>"’ and UoMId/Id eq guid’" + defaultUnitGUID.Id + "’)";</p>
<p>$.ajax({</p>
<p>type: "GET",</p>
<p>contentType: "application/json; charset=utf-8",</p>
<p>datatype: "json",</p>
<p>url: oDataSelect2,</p>
<p>beforeSend: function (XMLHttpRequest) { XMLHttpRequest.setRequestHeader("Accept", "application/json"); },</p>
<p>success: function (data,status){ havePrice(data, defaultUnitGUID);},</p>
<p>error: function (XmlHttpRequest, textStatus, errorThrown) {</p>
<p>alert(‘OData Select Failed: ‘+ errorThrown + ". There is no price list item for this product");</p>
<p>}</p>
<p>});</p>
<p>}</p>
<p>function havePrice(data, defaultUnitGUID){</p>
<p>if(defaultUnitGUID != null){</p>
<p>//set the price per unit</p>
<p>var priceListItemAmount = data.d.results[0].Amount.Value ;</p>
<p>Xrm.Page.getAttribute("priceperunit").setValue(parseFloat(eval(priceListItemAmount)));</p>
<p>Xrm.Page.getAttribute("priceperunit").setSubmitModeAlways;</p>
<p>//set the unit on Opportunity below.</p>
<p>var id = defaultUnitGUID.id;</p>
<p>var name = defaultUnitGUID.Name.toString();</p>
<p>var entityType = defaultUnitGUID.LogicalName.toString();</p>
<p>Xrm.Page.getAttribute("uomid").setValue( [{id: id, name: name, entityType: entityType}]);</p>
<p>}</p>
<p>}<br />
[/sourcecode]

Want more Dynamics CRM JavaScript tidbits? Here are some options for further reading:

Happy CRM’ing!

  • Dave

    Thanks for the script, I found a slight problem with my installation

    var id = defaultUnitGUID.id;
    var name = defaultUnitGUID.Name.toString();
    var entityType = defaultUnitGUID.LogicalName.toString();

    should be

    var id = defaultUnitGUID.Id; <—————————————
    var name = defaultUnitGUID.Name.toString();
    var entityType = defaultUnitGUID.LogicalName.toString();

Return to Top ▲Return to Top ▲