Tuesday, March 3, 2020

Generic way to Refresh Rollup field in Dynamic CRM

Opportunity Roll-up fields




Opportunity Products Grid




Roll-up fields Definition





Generic method to re-calculate and refresh the Rollup field.

refreshRoleupField: function (executionContext, entityName, entityId, rollup_fieldName)
{
 debugger;
 var formContext = executionContext.getFormContext();           
 var clientUrl = formContext.context.getClientUrl();

 // Method Calling and defining parameter
 var rollupAPIMethod = "/api/data/v9.1/CalculateRollupField(Target=@tid,FieldName=@fn)";

 // Passing Parameter Values
 rollupAPIMethod += "?@tid={'@odata.id':'" + entityName + "(" + entityId + ")'}&@fn='" +   rollup_fieldName + "'";

 var req = new XMLHttpRequest();
 req.open("GET", clientUrl + rollupAPIMethod, false);
 req.onreadystatechange = function ()
 {
    if (this.readyState === 4) 
    {
        req.onreadystatechange = null;
        if (this.status === 200) 
        {
          console.log("Field Recalculated successfully");                       
        }
    }
 };

 req.send();           
 formContext.data.entity.save();
}

Syntax for calling the method

onLoad: function (executionContext)
{
    var entityId = formContext.data.entity.getId().replace('{''').replace('}''');
    opty.Functions.refreshRoleupField(executionContext, 'opportunities', entityId, 'new_totalunitcost');
    opty.Functions.refreshRoleupField(executionContext, 'opportunities', entityId, 'new_sumextendedcost');

}

I hope you find this useful.

Thanks.

Update BPF Stage from JavaScript code


Business Scenario:

We had Lead to Opportunity Sales Process (BPF) having 5 stages define on Lead and Opportunity entity.




Now, requirement is such that when any quotes attached to opportunity get lost then BPF stage to be brought back to Propose stage.

Quote is another entity and it had its own form and events and as BPF is not present on quote entity we are required to use the script to update the stage of BPF.


Technical Concept Understanding:

Let’s understand a little concept before we jump to code.

1) BPF is an Entity

Each BPF is considered as an entity in Dynamic CRM and it maintains relationship with the entities involved in it.

In our case we have leadid and opportuntyid




2) BPF instances can be retrieved using advanced find



3) BPF stage name can be accessed from Code only

We cannot see the entity under customizations, but we can query its data.

var apiQry = "/api/data/v9.1/processstages?";
apiQry += "$select=processstageid,stagename";
apiQry += "&$filter=primaryentitytypecode eq 'opportunity'";

Here is a JSON output


  "value": [
    {
      "@odata.etag": "W/\"2500100\"",
      "processstageid": "650e06b4-789b-46c1-822b-0da76bedb1ed",
      "stagename": "Develop"
    },
    {
      "@odata.etag": "W/\"2500098\"",
      "processstageid": "6b9ce798-221a-4260-90b2-2a95ed51a5bc",
      "stagename": "Qualify"
    },
    {
      "@odata.etag": "W/\"835939\"",
      "processstageid": "3a275c22-fc45-4e89-97fc-41e5ec578743",
      "stagename": "Propose"
    },
    {
      "@odata.etag": "W/\"1840305\"",
      "processstageid": "e81cba7c-2dc3-4862-8f2b-88a29c809484",
      "stagename": "Price Negotiation"
    },
    {
      "@odata.etag": "W/\"2500104\"",
      "processstageid": "bb7e830a-61bd-441b-b1fd-6bb104ffa027",
      "stagename": "Close"
    }

  ]


Code Solution:

Now we need to register our event on Quote Close.
For simplicity I registered code on some field change event to test the functionality.


var Quote = {
    Functions: {

quoteClose: function () {

var opportunity = Xrm.Page.getAttribute("opportunityid").getValue();

if (opportunity != null) {

    var opportunityId = opportunity[0].id;

    var apiQuery = "/api/data/v9.1/leadtoopportunitysalesprocesses?";
    apiQuery += "$select=_activestageid_value,businessprocessflowinstanceid";
    apiQuery += "&$filter=_opportunityid_value eq " + opportunityId;

    var req = new XMLHttpRequest();
    req.open("GET", Xrm.Page.context.getClientUrl() + apiQuery, false);
    req.setRequestHeader("OData-MaxVersion", "4.0");
    req.setRequestHeader("OData-Version", "4.0");
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"");
    req.onreadystatechange = function () {
        if (this.readyState === 4) {
            req.onreadystatechange = null;
            if (this.status === 200) {
                var results = JSON.parse(this.response);
                for (var i = 0; i < results.value.length; i++) {
                    var _activestageid_value = results.value[i]["_activestageid_value"];
                    var businessprocessflowinstanceid = results.value[i]["businessprocessflowinstanceid"];

                    // To just have a concept, I have hard-coded Process Stage here
                    // or else you can retrieve it using above mentioned web api query.
                    var proposeStageId = '3a275c22-fc45-4e89-97fc-41e5ec578743';

                    if (_activestageid_value != proposeStageId) {
        
Quote.Functions.updateLeadToOptySalesStage_To_Propose(businessprocessflowinstanceid, proposeStageId);
                    }
                }
            }
            else {
                Xrm.Utility.alertDialog(this.statusText);
            }
        }
    };
    req.send();
}
},

updateLeadToOptySalesStage_To_Propose: function (businessprocessflowinstanceid, proposeStageId) {
var entity = {};
entity["activestageid@odata.bind"] = "/processstages(" + proposeStageId + ")";

var req = new XMLHttpRequest();
req.open("PATCH", Xrm.Page.context.getClientUrl() + "/api/data/v9.1/leadtoopportunitysalesprocesses(" + businessprocessflowinstanceid + ")", false);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.onreadystatechange = function () {
    if (this.readyState === 4) {
        req.onreadystatechange = null;
        if (this.status === 204) {
            //Success - No Return Data
            alert('Opportunity Sales stage is back to Propose stage, please act accordingly');
        } else {
            Xrm.Utility.alertDialog(this.statusText);
        }
    }
};
req.send(JSON.stringify(entity));
}
}

}

I hope this help you.

Thanks.
Vipin Jaiswal

Monday, March 2, 2020

File migration tool by Microsoft


Now, one more prominent and convincing reason to help business migrate to Microsoft 365.



           "Mover acquired by Microsoft"


Price: Free
The Mover app is now free for use with any supported migration scenario!

Supported Countries: Worldwide
As of February 2020, Mover is available worldwide!


Here are steps to try it now

Step 1: Browse - https://mover.io and create your account.

Step 2: Login to mover and you will see Transfer Wizard page.




Step 3: Select Source Connector.

Mover can migrate data from the following Microsoft and Third-party services at present:
I hope the list will go more and we would have search connector feature soon.




Step 4: Select Destination Connector.
Here is a list of destination connectors to go with it.




Step 5: Though you can transfer root to root folder, Mover allowed to select specific folder for source and destination. I tested it for a single folder.





Step 6: Proceed with Start Copy and you will be landed to Migration Manager Dashboard.

Scan and migrate your data with just a click and see the complete migration activity.




Here are some more articles related to Migrations




I hope you enjoy this new amalgamation.



Regards,

Vipin Jaiswal