Tuesday, March 3, 2020

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

No comments: