As of the February 2023 release for SAP Integrated Business Planning for Supply Chain (SAP IBP), you can replicate planning tasks from process management in SAP IBP to Microsoft Teams. Please see our short product video on this.
In the previous blog post about the integration topic, we reviewed the advantages and disadvantages of the different modelling options that large enterprises could use for supporting process participants who are organized into different communities and where teams are spread over different locations.
In this article, we will explore how an organization could use Microsoft Teams to take their process management to the next level.
It’s important to understand the basic flow that’s involved when you use the additional automation capabilities of Microsoft Teams by leveraging Microsoft Power Automate to build an automatic flow that augments the process modelled within SAP IBP. In SAP IBP, the supply chain planning processes are modelled in process templates that break down the processes into process steps and then tasks. When SAP IBP is integrated with Microsoft Teams, these tasks are also generated on the Microsoft Teams side as the SAP IBP system is making various Microsoft Graph API calls. It is important to highlight that in such an integrated scenario, the process orchestration and, very importantly, the creation of tasks and the process are still driven by the process automation capability of SAP IBP. The tasks of one process step are created only when the process reaches that step and the step status is manually or automatically set to “In Progress”. The tasks are first created in SAP IBP. Immediately after this, a Microsoft Graph API is called to create their identical twins in Microsoft Teams. The process management backend ensures that changes made to tasks in Microsoft Teams or SAP IBP are synchronized. This applies to most changes like updating the task name or description, assignees, priority, and most importantly, the status (or rather the Percent Complete property). However, there are certain task properties or entities that are valid only within Microsoft Teams, such as attachments, comments, or lists; these are not synchronized back to SAP IBP. Similarly, there is information stored in SAP IBP that connects the tasks to a process instance and step that is not visible in Microsoft Teams when you’re looking at the task (unless it’s reflected by the bucket names).
So, when we use Microsoft Power Automate, we can extend the process automation and orchestration capabilities by using event triggers related to tasks, for example, when a task is created or completed.
Let’s look at two simple examples that can extend the interaction and process management capabilities by leveraging the Microsoft Teams environment:
Example 1: We would like to notify the planning community through a channel message that a task was completed.
For this we would go through a step-by-step description on how to create this in Microsoft Power Automate.
If you recall from the previous blog post, we can model the planning communities as teams and the processes within SAP IBP in different ways if they’re located in multiple countries. Let’s use option 2A where the planning community is modelled as one large team:
This setup option could be enriched in Microsoft Teams by having dedicated private channels, one channel for the European supply chain planning community and one channel for the planners in the Americas region:
When we start Microsoft Power Automate from within Microsoft Teams and create a new flow, we can use a template. We will search for the word “tasks” and select the template “Notify a team when Planner tasks change status”.
At this point we give our flow a name and click Next:
We will select which plan will be monitored for completing the tasks. Previously we added the Tasks by Planner and To Do app as a new tab to the General channel so that all community members can have a look at the tasks. At the same time, we created a new plan called “SAP IBP Planning Tasks”.
This is the plan that we will be selecting now in the flow for our unified team called “All Demand Planners”. Then we select who we want to notify, for example, the whole team and we select the General channel for this example, so that everyone sees this message:
When you create a flow, default content is generated. To edit your flow, you can select it from the Home tab and edit it there.
At this point we see that the default flow that was created is based on the template with a standard three steps: the trigger condition at the top is that the task is completed, we then read the user profile of the task creator, and then we post an adaptive card to the respective channel:
Note: If you click the first step, you’ll see some details, like the team/group and the plan for which the status changes of tasks are monitored.
We don’t need to read the user profile of the task creator, so we can remove the second step. Click the three dots on the right-hand side of that step of the flow and delete this one:
Let’s remove the last step as well, as we don’t want to use an adaptive card, just a simple message. Now we’ve removed all steps of the flow, except the trigger. Add a new action step, select the action to post a message in the chat or channel, and In the search field enter the word “message”:
We can specify the General channel of our team as the channel we want to use for posting the message. We can also specify what information is being posted there. We will use some of the dynamic content in the message:
Now let’s test the workflow. We will need to work with two browser windows for this.
In a separate browser tab, open the Microsoft Teams web app again. Go to your team and its General channel.
Switch back to the browser window that has your Microsoft Power Automate open. Save the flow we have edited and press Test. This is now waiting for a task to be completed.
Switch to the other browser tab where the General channel is displayed. Within your General channel, switch to the tab in Microsoft Teams that has the Tasks Planner and To Do app (this tab usually bears the name of your plan, for example, “IBP Planning Tasks”). As you open this app to display the tasks, you’ll see that, upon first usage, it will have by default a bucket called “To Do”. Let’s rename the “To Do” bucket to “Create Local Demand Plan” to match the step name of your process in SAP IBP.
Let’s add a new task here. Assign it to some colleagues and add a due date. Now change the task status to Complete.
Switch back to the browser tab that has your Microsoft Power Automate open. Notice that the flow has been executed in test mode and you see checkmarks next to each step that ran successfully:
If you look at your other browser tab where the General channel is being used, switch to the Posts tab. Notice that as the flow was executed, it posted a new message that’s visible to your planning community. This lets the demand planners know that a task was completed:
This simple example shows you that you can notify your planning community about completed tasks very easily. This flow will also execute when these tasks in Microsoft Teams come from SAP IBP. The prerequisite is that the integration is set up in SAP IBP and in Microsoft Azure. In SAP IBP in the process template, ensure that you linked the “Create Local Demand Plan” process step to this triad of team + plan + bucket from Microsoft Teams (so All Demand Planners + IBP Planning Tasks + Create Local Demand Plan). In SAP IBP, the tasks are created and replicated to Microsoft Teams when the planning process progresses to the “Create Local Demand Plan” step. When the users complete the tasks, the whole community is notified through the channel.
Example 2: In this example, we build a flow that will notify the planning community through a specified channel about new tasks being created. New tasks will be created in SAP IBP when the process reaches a process step that has tasks or when process owners or step owners add and assign additional tasks within SAP IBP for a process that is already running. In this example, we will use some sophistication in Microsoft Power Automate as we will rely on more advanced features like using variables, branching based on conditions, and even adaptive cards.
We start to create this workflow from scratch as there isn’t a template that suits our needs. As the first step, we will choose the trigger. Search for “Planner” and select “When a task is created”. Set your team and the plan to be used that is being tracked for new tasks, in our case that would be “All Demand Planners” and the plan we created before, called “IBP Planning Tasks”.
In the adaptive card that we are posting to the selected channel, we would like to display the bucket to which the new task belongs and its creator.
First, let’s determine the user who created the task, read the user’s profile using the Created By User ID from the dynamic content panel and then in the subsequent step, store the display name of the creator in a variable. Up to now the flow looks like this:
Next, we would, in a similar way, need to collect the bucket name and put it temporarily in a variable.
We would initialize a new variable, read all buckets of our plan, and collect and read the name of the bucket that has the same identifier as the bucket containing our new task. The “List Buckets” step returns an array variable called “value” that contains the buckets. This entity has the fields ID and Name, which correspond to bucket identifiers and human readable bucket names. These are the things we are interested in. When you add the action component “Apply To Each”, you need to select the “value” content element from the Dynamic content panel. Within the loop we would use a condition block to identify the bucket that we are looking for (value ID = Bucket ID, where Bucket ID is the bucket identifier of the new task) and store the human readable bucket name in the variable. This block would look like this:
Next up, we want to read the task description to be later displayed in the adaptive card. This is contained in the description field of the task detail entity. We will initialize a new string variable, call the Get Task Details action with the ID of the new task, and then put the task description in our new variable.
This block should look like this:
Now, in the flow we would like to use a couple of variables to collect the names of the task assignees of the new task.
For this, we add actions to the flow to initialize variables. We will name the variables UserNames and UserIDs:
The variables are of type Array, as there can be more than one task assignee for the new task.
Now we would like to process each task assignee and add the respective user ID and user name to the respective array. In order to retrieve a user’s display name, you need to read the user’s profile information.
This block would look like this. First, you add the action component Apply To Each and select this to be executed for each task assignee by selecting the “assignments” content element from the Dynamic content panel. Then, in this action block you append the new information to the arrays. You use the dynamic content information like the “assignments Assigned To User ID” twice, to add the user to the UserIDs array and to read the respective user’s profile and then, from the profile content you will add the “Display Name” to the other array:
In order to add the task assignees to our adaptive card, we would concatenate the user names contained in the UserNames array into a single string. We will use the Compose action with the “join” function and using semicolons as separator characters, like this:
Now, if you look at the modelling proposal at the beginning of the blog post, we can have the task names containing the respective region that needs to process the task. (For example, “Task 1 – Europe”)
We want to achieve the following behavior: If the task title contains the word “Europe”, we will post an adaptive card about the new task in the DP – Europe channel. If the task title contains the word “Americas”, we will post the adaptive card in the DP – Americas channel. If none of these are in the task title, we will post the card in the General channel. This way, we will notify the right planning community.
So next up, we add an action to the flow of type Condition. We will use the task title from the dynamic content and the contains logical operator. Automatically, two branches are created, depending on whether the condition is true or false:
- In the “yes” branch, we will add the action to post an adaptive card in the DP – Europe Important to note here, since our target channel DP – Europe is defined as a private channel, you cannot post a message or an adaptive card as a flow bot. Instead, you need to post it in the name of the user. So, the user who is building this flow will need to be part of both private teams (DP – Europe and DP – Americas in this case).
- In the “No” branch (when the task title does not contain the word “Europe”), we would again add a condition. This condition enables the system to check whether the task title contains the word “Americas”. If yes, we would post in the DP – Americas private channel. If neither the word “Europe” nor the word “Americas” is contained in the task title, we will post in the General
So, after enhancing this flow with multiple, additional conditional steps, this section would look like this:
Now that we have implemented these branches for deciding which channel will be used to post the adaptive card, let’s focus on the content of the adaptive card. This will be the same regardless of what the title contains. You can copy the code below to the Adaptive Card field for each of the branches shown above that start with “Post adaptive card in a chat or channel”:
{
"type": "AdaptiveCard",
"msTeams": {
"width":"full"
},
"body": [
{
"type": "TextBlock",
"text": "A new task was created",
"size":"Large",
"weight": "Bolder"
},
{
"type": "TextBlock",
"text": "@{triggerOutputs()?['body/title']}",
"spacing":"None",
"size":"Large",
"weight": "Bolder",
"color": "Accent"
},
{
"type": "FactSet",
"facts": [
{
"title": "Task Description",
"value": "@{variables('TaskDescription')}"
},
{
"title": "Bucket",
"value": "@{variables('BucketName')}"
},
{
"title": "Created By",
"value": "@{variables('CreatorName')}"
},
{
"title": "Assigned To",
"value": "@{outputs('Compose')}"
},
]
},
{
"type": "ActionSet",
"actions": [
{
"type": "Action.OpenUrl",
"title": "View task",
"url": "https://tasks.office.com/Home/Task/@{triggerOutputs()?['body/id']}"
}
]
}
],
"version": "1.2",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json"
}
If you made it this far and completed this flow, you will know by now how to save and test your new flow. Create a new task that has various task titles and see that the adaptive card is posted in the right channel.
It should look as below. You’ll see that the adaptive card contains information such as the task title, task description, bucket, user who created the task, and the task assignees.
The obvious advantage of using adaptive cards instead of simple messages, as seen in the first example, is that you can immediately access and navigate to the task object to start working on it.
Conclusion
By going through two in-depth examples, we have shown you how you can extend the process management capabilities of SAP IBP when you synchronize tasks from SAP IBP to Microsoft Teams. We looked at how easily you can create flows using Microsoft Power Automate / Flow to extend capabilities of process management in SAP IBP in a “side car” manner.
There could be other examples, not illustrated here, that you could achieve using Microsoft Power Automate in relation to SAP IBP tasks, such as:
- Sending email notifications using Microsoft Outlook when tasks are created/updated, or new assignees are added
- Exporting overdue tasks to Microsoft Excel
- Exporting completed tasks for analytical reports into Microsoft Power BI
- Automatically adjusting the due date of tasks based on the calendar if there are holidays to consider
- Automatically attaching some documents based on rules.