Thursday, June 26, 2025

Moving BPF Stages Backward in Dynamics 365 with Power Automate

A step-by-step guide to dynamically control BPF stages using Power Automate

Introduction

Business Process Flows (BPFs) in Microsoft Dynamics 365 and Dataverse guide users through predefined stages, but moving backward isn’t supported natively in the BPF designer or connectors. For example, moving from stage 2 to stage 1 based on a field value like "No" requires custom logic. Power Automate offers a low-code solution to achieve this by updating the activestageid field. In this post, we’ll show you how to create a flow that moves a BPF stage backward or forward based on a field value.

Why This Matters: Power Automate enables non-developers to implement complex BPF logic, making it accessible and maintainable without writing code.

The Requirement

For an account entity with a BPF named "Account Process Flow," we need to:

  • Monitor a choice field (new_decisionfield).
  • If "Yes," move from stage 2 to stage 3.
  • If "No," move back to stage 1.

Since the BPF designer and standard connectors only support forward movement, we’ll use Power Automate to update the BPF instance’s activestageid.

Step-by-Step Guide

Step 1: Gather Required Information

Before building the flow, collect these details:

  • BPF Stage IDs: Find the GUIDs for stage 1 and stage 3 in the processstages table using XrmToolBox or FetchXML. Example:
    • Stage 1: 12345678-1234-1234-1234-1234567890ab
    • Stage 3: 98765432-4321-4321-4321-9876543210ba
  • BPF Instance Table: Identify the logical name (e.g., accountprocessflows).
  • Field Values: Confirm the new_decisionfield OptionSet values (Yes = 100000000, No = 100000001).

Step 2: Set Up Power Automate

Create a flow in Power Automate:

  1. Create a Flow: Go to make.powerautomate.com and create a new automated cloud flow.
  2. Add Trigger: Use "When a row is added, modified, or deleted" (Dataverse connector):
    • Table name: Accounts
    • Change type: Modified
    • Filter attributes: new_decisionfield
  3. Add Condition: Check if new_decisionfield equals 100000000 (Yes) or 100000001 (No).
  4. Retrieve BPF Instance: Add a "List rows" action:
    • Table name: accountprocessflows
    • Filter rows: regardingobjectid eq @{triggerOutputs()?['body/accountid']}
    • Select columns: activestageid,accountprocessflowid
  5. Update BPF Stage:
    • Yes Branch: Add "Update a row" action:
      • Table name: accountprocessflows
      • Row ID: @{first(body('List_rows')?['value'])['accountprocessflowid']}
      • Active Stage: 98765432-4321-4321-4321-9876543210ba (Stage 3)
    • No Branch: Add "Update a row" action:
      • Table name: accountprocessflows
      • Row ID: @{first(body('List_rows')?['value'])['accountprocessflowid']}
      • Active Stage: 12345678-1234-1234-1234-1234567890ab (Stage 1)

Step 3: Sample Flow Configuration

Below is a JSON representation of the Power Automate flow for reference (you can import this as a starting point):

{
  "definition": {
    "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
    "actions": {
      "Condition": {
        "actions": {
          "Yes_Update_Stage_3": {
            "type": "ApiConnection",
            "inputs": {
              "host": {
                "connection": {
                  "name": "@parameters('$connections')['dataverse']['connectionId']"
                }
              },
              "method": "patch",
              "path": "/v9.2/accountprocessflows(@{first(body('List_BPF_Instance')?['value'])['accountprocessflowid']})",
              "body": {
                "activestageid": "98765432-4321-4321-4321-9876543210ba"
              }
            }
          }
        },
        "else": {
          "actions": {
            "No_Update_Stage_1": {
              "type": "ApiConnection",
              "inputs": {
                "host": {
                  "connection": {
                    "name": "@parameters('$connections')['dataverse']['connectionId']"
                  }
                },
                "method": "patch",
                "path": "/v9.2/accountprocessflows(@{first(body('List_BPF_Instance')?['value'])['accountprocessflowid']})",
                "body": {
                  "activestageid": "12345678-1234-1234-1234-1234567890ab"
                }
              }
            }
          }
        },
        "expression": {
          "and": [
            {
              "equals": [
                "@triggerOutputs()?['body/new_decisionfield']",
                100000000
              ]
            }
          ]
        },
        "type": "If"
      },
      "List_BPF_Instance": {
        "type": "ApiConnection",
        "inputs": {
          "host": {
            "connection": {
              "name": "@parameters('$connections')['dataverse']['connectionId']"
            }
          },
          "method": "get",
          "path": "/v9.2/accountprocessflows",
          "queries": {
            "$filter": "regardingobjectid eq @{triggerOutputs()?['body/accountid']}",
            "$select": "activestageid,accountprocessflowid"
          }
        }
      }
    },
    "triggers": {
      "When_a_row_is_modified": {
        "type": "ApiConnection",
        "inputs": {
          "host": {
            "connection": {
              "name": "@parameters('$connections')['dataverse']['connectionId']"
            }
          },
          "method": "get",
          "path": "/v9.2/rows",
          "queries": {
            "table": "accounts",
            "changeType": "Modified",
            "filterAttributes": "new_decisionfield"
          }
        }
      }
    }
  }
}

Step 4: Test the Flow

Save and test the flow by updating new_decisionfield on an account record. Verify the BPF stage moves to stage 3 (Yes) or stage 1 (No). Check the flow’s run history for errors.

Pro Tip: Add an error-handling step (e.g., send an email if no BPF instance is found) to make the flow more robust. Use the flow’s run history to debug issues.

Key Notes

  • Replace GUIDs: Update stage GUIDs in the flow with actual values from your processstages table.
  • BPF Table: Use the correct logical name for your BPF instance table (e.g., accountprocessflows).
  • Option Set Values: Adjust 100000000 (Yes) and 100000001 (No) to match your field’s values.
  • Permissions: Ensure the flow’s connection has permissions to read and update accountprocessflows records.

Conclusion

Power Automate provides a low-code way to move BPF stages backward in Dynamics 365, overcoming the designer’s forward-only limitation. This solution is ideal for non-developers and offers flexibility for dynamic process control. Try it out, and share your feedback or questions in the comments!

© 2025 Your Name. All rights reserved.

No comments:

Post a Comment

Power Automate Optimization: Filter Rows vs Trigger Conditions - When and Why to Use Each

Filter Rows vs Trigger Conditions in Power Automate Filter Rows vs Trigger Conditions in Power Automate Why your flow...