Monday, November 14, 2011

Status Duration


if you're statistics of your opportunities that counting status duration can be very useful for you.
Status Duration - this is how many days opportunity is the current status.


Add new field on opportunity form "new_statusduration" to set Status Duration value.

function getDuration() {
 var thetime = new Date();
 var oneday = 1000 * 60 * 60 * 24;
 var currentMonth = thetime.getMonth() + 1;
 var currentYear = thetime.getFullYear();
 var currentDay = thetime.getDate();
 var currentdate = currentMonth + "/" + currentDay + "/" + currentYear;
 var newdate = new Date(currentdate);



 if (Xrm.Page.getAttribute("opportunityratingcode").getValue() == null) {
  Xrm.Page.getAttribute("new_statusduration").setValue(null);
 }
 else {
  var statusduration = "";
  var xml = "";
  xml += '';
  xml += '';
  xml += '';
  xml += '';
  xml += '';
  xml += '';
  xml += '';
  xml += ''
  xml += '';
  xml += '';
  xml += '';



  var doc = Fetch(xml);
  var nodes = doc.selectNodes("//resultset/result/createdon");
  if (nodes[0] != null) {
   var statusnode = nodes[0].getAttribute("date");
   var statusdate = new Date(statusnode);
   var duration = Math.round((newdate - statusdate) / oneday);
   if (duration < 1) {
    statusduration = duration + " d";
   }
   else {
    statusduration = Math.floor(duration / 30) + " m " + (duration % 30) + " d";
   }
   Xrm.Page.getAttribute("new_statusduration").setSubmitMode("always");
   Xrm.Page.getAttribute("new_statusduration").setValue(statusduration);
  }
 }
}
To use this script you need "Fetch" function
function Fetch(xml) {
 var Xml = "";
 Xml += GenerateAuthenticationHeader();
 Xml += "";
 Xml += "";
 Xml += "";
 Xml += CrmEncodeDecode.CrmXmlEncode(xml); // Microsoft _HtmlEncode function
 Xml += "";
 Xml += "";
 Xml += "";
 Xml += "";
 var XmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); // Microsot CreateXmlHttp function
 XmlHttp.open("POST", "/mscrmservices/2007/crmservice.asmx", false); //Sync Request
 XmlHttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
 XmlHttp.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Fetch");
 XmlHttp.send(Xml);
 var XmlDoc = new ActiveXObject("Msxml2.DOMDocument");
 XmlDoc.async = false;
 XmlDoc.resolveExternals = false;
 XmlDoc.loadXML(XmlHttp.responseXML.text);
 return XmlDoc;
}
Result:
Don't forget enable auditing for Opportunity entity!

Tuesday, November 8, 2011

Don't allow complete appointment unless "Status" is empty

You can don't allow close appointment as completed or cancelled unless user don't specify necessary field. 
Use following script:
function closeAppointment()
{
 var CRM_FORM_SAVE_MODE_SAVEASCOMPLETED = 58;
 var CRM_FORM_SAVE_MODE_CLOSE = 5;
 if ((event.Mode == CRM_FORM_SAVE_MODE_SAVEASCOMPLETED) ||
    (event.Mode == CRM_FORM_SAVE_MODE_CLOSE))
 {
  var qualifiedstatus = Xrm.Page.getAttribute("new_qualifiedstatus");
  if (!IsNull(qualifiedstatus))
  {
   var option = qualifiedstatus.getSelectedOption();
   if (IsNull(option) || IsNull(option.value) || IsNull(option.text))
   {
    alert("Please provide a value for the Qualified Status!");
    document.all.new_qualifiedstatus.focus();
    event.returnValue = false;
    return false;
   }
  }
 }
}

Hide control "Est. Revenue" on Opportunity form

If you want to hide "Est. Revenue" field for all except special CRM role and owner of this opportunity you can use following javascript code:
function GetCurrentUserRoles()
{
 var xml = "" +
"" +
"" +
GenerateAuthenticationHeader() +
" " +
" " +
" " +
" role" +
" " +
" " +
" name" +
" " +
" " +
" false" +
" " +
" " +
" roleid" +
" role" +
" systemuserroles" +
" roleid" +
" Inner" +
" " +
" " +
" systemuserid" +
" systemuserroles" +
" systemuser" +
" systemuserid" +
" Inner" +
" " +
" And" +
" " +
" " +
" systemuserid" +
" EqualUserId" +
" " +
" " +
" " +
" " +
" " +
" " +
" " +
" " +
" " +
" " +
"" +
"";
 var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
 xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
 xmlHttpRequest.setRequestHeader("SOAPAction", " http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");
 xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
 xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
 xmlHttpRequest.send(xml);
 var resultXml = xmlHttpRequest.responseXML;
 return (resultXml);
}


function hideRevenue()
{
 UserID = Xrm.Page.context.getUserId();
 OwnerID = Xrm.Page.getAttribute("ownerid").getValue()[0].id;
 if (UserHasRole("Boss") || UserID == OwnerID)
 {
  Xrm.Page.ui.controls.get("estimatedvalue").setVisible(true);
 }
 else
 {
  Xrm.Page.ui.controls.get("estimatedvalue").setVisible(false);
 }
}

Set disabled opportunity "Close as Won" button unless probability is not 100 or status is not "A"

To prevent accidental closing of opportunity I present to you method how can set disabled opportunity "Close as Won" button unless probability is not 100% or status is not "A". 

First of all you should export solution with your "Opportunity" entity customization.
Unzipp you solution and open "customizations" file with any XML editor.
Find in this file <RibbonDiffXml> tag and replace its content with the following xml: 

<RibbonDiffXml>
         <CustomActions>
          <CustomAction Id="ABC.Mscrm.HomepageGrid.opportunity.MainTab.Actions.Controls" Location="Mscrm.HomepageGrid.opportunity.MainTab.Actions.Controls._children">
            <CommandUIDefinition>
              <Button Id="Mscrm.HomepageGrid.opportunity.MarkAsWon" Command="Mscrm.HomepageGrid.opportunity.MarkAsWon" Sequence="5" Alt="$Resources:Ribbon.Form.opportunity.MainTab.Actions.MarkAsWon" LabelText="$Resources:Ribbon.Form.opportunity.MainTab.Actions.MarkAsWon" Image16by16="/_imgs/SFA/MarkAsWon_16.png" Image32by32="/_imgs/SFA/MarkAsWon_32.png" TemplateAlias="o1" ToolTipTitle="$Resources:Mscrm_HomepageGrid_opportunity_MainTab_Actions_MarkAsWon_ToolTipTitle" ToolTipDescription="$Resources:Mscrm_HomepageGrid_opportunity_MainTab_Actions_MarkAsWon_ToolTipDescription" />
            </CommandUIDefinition>
          </CustomAction>
          <CustomAction Id="ABC.Mscrm.Form.opportunity.MainTab.Actions.Controls" Location="Mscrm.Form.opportunity.MainTab.Actions.Controls._children">
            <CommandUIDefinition>
              <Button Id="Mscrm.Form.opportunity.MarkAsWon" Command="Mscrm.Form.opportunity.MarkAsWon" Sequence="3" Alt="$Resources:Ribbon.Form.opportunity.MainTab.Actions.MarkAsWon" LabelText="$Resources:Ribbon.Form.opportunity.MainTab.Actions.MarkAsWon" Image16by16="/_imgs/SFA/MarkAsWon_16.png" Image32by32="/_imgs/SFA/MarkAsWon_32.png" TemplateAlias="o1" ToolTipTitle="$Resources:Mscrm_Form_opportunity_MainTab_Actions_MarkAsWon_ToolTipTitle" ToolTipDescription="$Resources:Mscrm_Form_opportunity_MainTab_Actions_MarkAsWon_ToolTipDescription" />
            </CommandUIDefinition>
          </CustomAction>
        </CustomActions>
        <Templates>
          <RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates>
        </Templates>
        <CommandDefinitions>
          <CommandDefinition Id="Mscrm.Form.opportunity.MarkAsWon">
            <EnableRules>
              <EnableRule Id="ABC.Mscrm.CheckImportCustomizationRule" />
            </EnableRules>
            <DisplayRules />
            <Actions />
          </CommandDefinition>
          <CommandDefinition Id="Mscrm.HomepageGrid.opportunity.MarkAsWon">
            <EnableRules>
              <EnableRule Id="ABC.Mscrm.CheckImportCustomizationRule" />
            </EnableRules>
            <DisplayRules />
            <Actions />
          </CommandDefinition>
        </CommandDefinitions>
     <RuleDefinitions>
  <TabDisplayRules />
  <DisplayRules />
    <EnableRules>
    <EnableRule Id="ABC.Mscrm.CheckImportCustomizationRule">
    <OrRule>
  <Or>
     <ValueRule
Field="closeprobability"
Value="100"
Default="0" />
</Or>
  <Or>
     <ValueRule
Field="opportunityratingcode"
Value="1"
Default="0" />
</Or>
</OrRule>
    </EnableRule>
    </EnableRules>
  </RuleDefinitions>
        <LocLabels />
 </RibbonDiffXml> 
Result: