Conditional BPF Switching in Dynamics 365 with JavaScript


Need different Business-Process-Flows (BPFs) for the same entity record depending on a field value?  The article below shows how to switch flows dynamically whenever the Appeal Type option-set changes—without hard-coding GUIDs. Drop this into your Blogger post and publish.


1  Why you might need this

  • Multiple flows – The dfa_appeal entity follows different BPFs for Amount versus Eligibility appeals.
  • Late decisions – Users can create a record first, choose the appeal type later, so the BPF must switch on change.
  • No GUID brittleness – We query by name; moves between environments just work.

2  Prerequisites

ItemNotes
Model-driven form for dfa_appeal Classic or modern designer
Two activated BPFs Give each a unique, clear name
JavaScript web-resource Add it as a form library

3  Core code (generalised names)


/**
 * setBPFBasedOnAppealType
 * -----------------------
 * Switches the active BPF according to the value of option-set
 */
function setBPFBasedOnAppealType (executionContext)
{
    var formContext = executionContext?.getFormContext();
    if (!formContext) { return; }

    /* 1 ▸ read Appeal Type */
    var appealType = formContext.getAttribute("dfa_appealtype")?.getValue();
    if (appealType == null) { return; }

    /* 2 ▸ map option-set → target BPF name */
    var BPF_BY_TYPE = {
        222710000: "BPF_NAME_FOR_AMOUNT",      // Amount
        222710001: "BPF_NAME_FOR_ELIGIBILITY"  // Eligibility
        // 222710002 = "Other" → leave flow unchanged
    };
    var targetBpfName = BPF_BY_TYPE[appealType];
    if (!targetBpfName) { return; }

    /* 3 ▸ already on that BPF? exit */
    var activeProcess = formContext.data.process.getActiveProcess();
    if (activeProcess &&
        activeProcess.getName &&
        activeProcess.getName() === targetBpfName)
    {
        return;                               // nothing to do
    }

    /* 4 ▸ look up BPF GUID by name, then activate it */
    var query =
        "?$select=workflowid" +
        "&$filter=category eq 4 and statecode eq 1 and " +
        "name eq '" + targetBpfName.replace(/'/g, "''") + "'";

    Xrm.WebApi.retrieveMultipleRecords("workflow", query)
        .then(function (res)
        {
            if (!res.entities.length)
            {
                console.warn("BPF not found:", targetBpfName);
                return;
            }
            var bpfId = res.entities[0].workflowid;

            formContext.data.process.setActiveProcess(
                bpfId,
                function (ok)
                {
                    if (!ok)
                    {
                        console.warn("Failed to activate BPF:", targetBpfName);
                    }
                });
        })
        .catch(function (e)
        {
            console.error("BPF lookup error:", e.message);
        });
}

/* ---------- thin wrappers ---------- */

function onChange_AppealType (executionContext)
{
    setBPFBasedOnAppealType(executionContext);
}

function onLoad_AppealForm (executionContext)
{
    var formContext = executionContext?.getFormContext();
    if (!formContext) { return; }

    var appealAttr = formContext.getAttribute("dfa_appealtype");
    if (appealAttr) { appealAttr.addOnChange(onChange_AppealType); }

    setBPFBasedOnAppealType(executionContext);   // initial check
}

4  Registering the script

EventFunctionPass ExecutionContext?
Form OnLoadonLoad_AppealFormYes
Field dfa_appealtype OnChangeonChange_AppealTypeYes

5  What makes this pattern solid

  • GUID-free – Flow names survive across environments.
  • Synchronous active-flow read – simpler than old callbacks.
  • Null-safe & style-compliant – braces on new lines, explicit returns.
  • Single mapping object – adding a new appeal type is one edit.

6  Troubleshooting tips

SymptomLikely causeFix
Console logs “BPF not found” Name typo or flow not activated Check spelling, activate BPF
Switch fails silently Security role lacks access to target BPF Add flow privilege to role
“Other” type still switches Mapping object includes it Remove or guard in BPF_BY_TYPE

7  Reference

Microsoft Docs: formContext.data.process.getActiveProcess() returns the active Process synchronously (no callback required).


Happy automating!

No comments:

Post a Comment