简体   繁体   中英

Dynamics 365 WebAPI getting Business Process Flow stages

So I am trying to execute a piece of code on preStageChange event of a Business Process Flow.

For that, I tried to get the workflow ID using the WebAPI, then get the stages of the workflow. If I would manage to do that, I could write a simple if statement to see if I am on the desired stage.

I tried this:

function preStageOnChange(executionContext) {
    var formContext = executionContext.getFormContext();
    var activeStage = formContext.data.process.getActiveStage();

    var stages = null;
    
    Xrm.WebApi.retrieveMultipleRecords("workflow", "?$filter=name eq 'Customer Onboarding'&$select=uniquename&$top=1").then(
        function success(result) {
            var workflowId = result.entities[0]["workflowid"];
            Xrm.WebApi.retrieveMultipleRecords("processstage", "?$select=stagename&$filter=processid/workflowid eq " + workflowId).then(
                function success(result) {
                    stages = result.entities;
                },
                function (error) {
                    console.log(error.message);
                }
            );
        },
        function (error) {
            console.log(error.message)
        }
    );
    
    var socioeconomicStatus = stages.find(stage => stage["stagename"] == "Socioeconomic Status");
    if(activeStage.getId().toString() == socioeconomicStatus["processstageid"]){
        if (formContext.getAttribute("ava_netincome").getValue() == null && formContext.getAttribute("ava_investmentincome").getValue() == null && formContext.getAttribute("ava_otherincome").getValue() == null) {
            formContext.ui.setFormNotification("At least one income value must be populated", "ERROR", "income_error"); //sets form notification in top of the form
            executionContext.getEventArgs().preventDefault(); //prevent navigation to next stage
        }
        else {
            formContext.ui.clearFormNotification("income_error");
        }

        if (formContext.getAttribute("ava_householdexpenses").getValue() == null && formContext.getAttribute("ava_otherexpenses").getValue() == null) {
            formContext.ui.setFormNotification("At least one expense value must be populated", "ERROR", "expense_error"); //sets form notification in top of the form
            executionContext.getEventArgs().preventDefault(); //prevent navigation to next stage
        }
        else {
            formContext.ui.clearFormNotification("expense_error");
        }

        if (formContext.getAttribute("ava_currentloan").getValue() != null && formContext.getAttribute("ava_loanexpenses").getValue() == null)
        {
            formContext.ui.setFormNotification("Loan expenses must be populated", "ERROR", "loan_error"); //sets form notification in top of the form
            executionContext.getEventArgs().preventDefault(); //prevent navigation to next stage
        }
        else {
            formContext.ui.clearFormNotification("loan_error");
        }
    }
}

Basically I am trying to execute the code when I am on the "Socioeconomic Status" stage, before going to the next stage. The reason I'm trying to do this is because I want to prevent the user from going to the next stage if they made any errors while filling out the form.

I realize that the WebAPI call I am using is async, so I tried awaiting it, making the event handler function async, but it doesn't seem to work that way either.

Another thing I tried is placing the error handling code into the success function of the WebAPI call, but if I do that I can't access the outer event so executionContext.getEventArgs().preventDefault(); stops working.

How can I make my error handling code run on a specific stage so that I can still prevent the user from going to the next stage?

Xrm.WebApi.retrieveMultipleRecords is a function that is executed asynchronously. It returns a Promise that is intended to chain subsequent asynchronous handlers.

A call to this promise function returns control to the thread before its asynchronous code is executed. Therefore the line var socioeconomicStatus = stages.find() is executed before stages is set properly.

Once in a promise chain you have to go through it to the end like this:

Xrm.WebApi.retrieveMultipleRecords("workflow", "?$filter=name eq 'Customer Onboarding'&$select=uniquename&$top=1")
    .then(result => {
        const workflowId = result.entities[0]["workflowid"];
        return Xrm.WebApi.retrieveMultipleRecords("processstage", "?$select=stagename&$filter=processid/workflowid eq " + workflowId);
    })
    .then(result => {
        var socioeconomicStatus = result.entities.find(stage => stage["stagename"] == "Socioeconomic Status");

        if (activeStage.getId().toString() == socioeconomicStatus["processstageid"]) {
            if (formContext.getAttribute("ava_netincome").getValue() == null && formContext.getAttribute("ava_investmentincome").getValue() == null && formContext.getAttribute("ava_otherincome").getValue() == null) {
                formContext.ui.setFormNotification("At least one income value must be populated", "ERROR", "income_error"); //sets form notification in top of the form
                executionContext.getEventArgs().preventDefault(); //prevent navigation to next stage
            }
            else {
                formContext.ui.clearFormNotification("income_error");
            }

            if (formContext.getAttribute("ava_householdexpenses").getValue() == null && formContext.getAttribute("ava_otherexpenses").getValue() == null) {
                formContext.ui.setFormNotification("At least one expense value must be populated", "ERROR", "expense_error"); //sets form notification in top of the form
                executionContext.getEventArgs().preventDefault(); //prevent navigation to next stage
            }
            else {
                formContext.ui.clearFormNotification("expense_error");
            }

            if (formContext.getAttribute("ava_currentloan").getValue() != null && formContext.getAttribute("ava_loanexpenses").getValue() == null) {
                formContext.ui.setFormNotification("Loan expenses must be populated", "ERROR", "loan_error"); //sets form notification in top of the form
                executionContext.getEventArgs().preventDefault(); //prevent navigation to next stage
            }
            else {
                formContext.ui.clearFormNotification("loan_error");
            }
        }
    })
    .catch(error => {
        console.log(error.message);
    });

As you can see, there is only one error handler. When the first query fails, it automatically skips the .then functions and proceeds with the .catch .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM