2009-11-13

Passing parameters between MS CRM plugins

I was needed to pass a variable from one plugin to another. If you have a two plugin at pre and post stage registered for on entity, then you can use a SharedVariables context property. But, if every plugins is a different assembly, and they are registered for a different entities... So, when the first plugin is firing, the second, which is starting after that, needed to know some information for redirecting it logic to another way.

I had created some common assembly with helper methods and called it "Helper". Then I had created a static class with static variable and had put the value into it, at the first plugin execution runtime. In the second plugin I just get the value from the static common variable.

And nothing about read\write DB operations.
Helper assembly.
namespace Helper
{
    public static class Keeper
    {
        private static bool _UpdateOppAfterHistory = true;
        public static bool UpdateOppAfterHistory 
        {
            get { return _UpdateOppAfterHistory; }
            set { _UpdateOppAfterHistory = value; }
        }
        
    }
    public class OpportunityHelper
    { ... }
}

First firing plugin code
Keeper.UpdateOppAfterHistory = false;

OpportunityHelper.CreateOpportunityHistory(Opp,crmService);
                
// removing the flag to the back
Keeper.UpdateOppAfterHistory = true;

Second firing plugin code
// common shared variable analysis
bool UpdateOppAfterHistory = Keeper.UpdateOppAfterHistory;
if (UpdateOppAfterHistory)
{ ... }

2009-11-10

How to hide an items of drop-down list?

"We should not be able to choose some steps of Opportunity History, if the opportunity has no quotes or sales orders." - that was they said.

And that was I wrote.

var oService = null;
var oppid = null;

function FormOnLoad()
{
 oService = new Ascentium_CrmService(null, null);
 
 var oParentCrmForm = window.opener.parent.document.all.crmForm;
 if(oParentCrmForm)
 { 
  oppid = oParentCrmForm.ObjectId;
 }
 
 HideComboboxItems();
}


window.HideComboboxItems = function()
{
var newstep = document.getElementById("new_step");
if(newstep)
{
 // checking opportunity for quotes
 var sFetchXml ='<fetch mapping="logical" aggregate="true" version="1.0"><entity name="quote"><attribute name="quoteid" aggregate="count" alias="count" />'+
  '<filter><condition attribute="opportunityid" operator="eq" value="'+oppid+'" /></filter></entity></fetch>';
 
 var aoFetchResult = oService.Fetch(sFetchXml); 
 var quoteCount = 0;

    if(aoFetchResult.length > 0)
    {
       quoteCount = aoFetchResult[0].attributes["count"].value;
    }
 
 // if no qoutes, then hiding items 4,5,6,7 of dropdown list
 if(quoteCount == 0 )
 {
  var allDropDownElements = newstep.childNodes;
  var lastnodevalue = allDropDownElements.length;
  for(var i=lastnodevalue; i >= 4; i--)
  {
    newstep.options.remove(i);
  }
 }
 else
 {
  // if there is some qoutes, then checking for salesorders
  var sFetchXml ='&lr;fetch mapping="logical" aggregate="true" version="1.0"><entity name="salesorder"><attribute name="salesorderid" aggregate="count" alias="count" />'+
   '<filter><condition attribute="opportunityid" operator="eq" value="'+oppid+'" /></filter></entity></fetch>';
  
  var aoFetchResult = oService.Fetch(sFetchXml); 
  var SOCount = 0;

  if(aoFetchResult.length > 0)
  {
     SOCount = aoFetchResult[0].attributes["count"].value;
  }
  
  // if no salesorders, then hiding items 6,7
  if(SOCount == 0)
  {
   var allDropDownElements = newstep.childNodes;
   var lastnodevalue = allDropDownElements.length;
   for(var i=lastnodevalue; i >=6; i--)
   {
     newstep.options.remove(i);
   }
  }
 }
 
}
}

2009-11-09

Salesorder Fulfill state

I was trying to catch the Fulfill state of sales order and my try was successful, with registering plugin to Update message at Child pipeline. But there was a one little problem - you can't get the salesorderdetail thru service. I don't know why, but the simple code like in "Example 1" was falling down with Generic SQL error x80044150.

//  Example 1
QueryByAttribute qba = new QueryByAttribute();
qba.EntityName = EntityName.salesorderdetail.ToString();
qba.ColumnSet = new AllColumns();
qba.Attributes = new string[] { "salesorderid" };
qba.Values = new object[] { soid };
BusinessEntityCollection bec = crmService.RetrieveMultiple(qba);


Then I was switch on the Fulfill Sdk Message and everything start working fine!
1. open up the SdkMessage view, filter by Name and find the SdkMessageId
2. open up the SdkMessageFilter view, filter by SdkMessageId you got from step 1.
3. change IsCustomProcessingStepAllowed to 'True'

update dbo.SdkMessageFilter
set IsCustomProcessingStepAllowed=1
where SdkMessageId=
(select top 1 SdkMessageId from dbo.SdkMessage where name ='Fulfill')

I have a question, why the Fulfill message has been unplugged from customization?

2009-11-02

Parse XML date in CRM date with Javascript

A JavaScript function to parse an XML (ISO-8601) date string (e.g., "2008-01-18") that returns a JavaScript Date object.

// parsing
function parseDate(xmlDate)
{
      if (!/^[0-9]{4}\-[0-9]{2}\-[0-9]{2}/.test(xmlDate)) {
           throw new RangeError("xmlDate must be in ISO-8601 format YYYY-MM-DD.");
      }
      return new Date(xmlDate.substring(0,4), xmlDate.substring(5,7)-1, xmlDate.substring(8,10));
}

// and using
if(retrievedOpp.attributes["estimatedclosedate"] != null && retrievedOpp.attributes["estimatedclosedate"] != undefined){
     crmForm.all.new_estimatedclosedate.DataValue = parseDate(retrievedOpp.attributes["estimatedclosedate"].value);}

Source http://dev.ektron.com/blogs.aspx?id=14140