Skip to content

Latest commit

 

History

History
625 lines (497 loc) · 25.6 KB

quest1.md

File metadata and controls

625 lines (497 loc) · 25.6 KB

Quest 1 - Novice's path

< Quest 0 - 🏠Home - Quest 2 >

🌟🌟🌟🌟 🕒 1 h

Introduction

Throughout the next exercises we will use an Office 365 user, an Azure subscription and some Office 365 tools. In order to make sure that everything is fine, it is best to quickly try and verify all used resources.

Video guide provided by our Mentors

Walkthrough video link

The video shall provide hints where lore, poetic code snippets, and narrative cannot.

The path

  1. Open up your Office 365 Outlook Inbox. Make sure to authenticate with your Developer Office 365 user, not with your corporate / personal user. One of the last emails in the Inbox should be the invitation email for the Contoso YAAC Azure subscription.

Invitation Email

Note: If you have not done so yet, accept the invite. You will be asked to Accept certain permissions to read your profile.

  1. Open Microsoft Teams. When doing that it is best to use the Browser experience (in order not to interfere with any other local Teams and Accounts that you might have installed).

  2. Check if you have Excel on-prem installed. Here you do not need to authenticate and it is fine to use the rich-client. In Quest 4 we will connect to an OData service and read data from our Online Store.

Note: if you want you can go to Office.com and click on "Install Apps" to run the OfficeSetup.exe which will install the rich clients for Excel (and other Office apps)

  1. For the last exercise we are going to integrate in Microsoft Word. You can open and create a Blank document from there.

  2. For every participant a resource group in Azure has been created in a central Azure subscription. In order to not interfere with other users, please always make sure that you only operate in the resource group assigned to you.

Note - To log-on to the Azure portal, please use your Microsoft 365 users which has been assigned as a contribute to the central Azure subscription.

Make sure that the Directory shown in the upper right corner of your user says "Contoso YAAC".

Contoso YaaC

If not switch to this Directory, by clicking on your user, selecting Switch directory and then clicking on Switch for the Contoso YAAC Directory.

Switch Directory

Provision your workflow orchestrator - Azure Logic Apps

📺Jump to the video

  1. From the Azure portal, use the Search bar at the top, search for Logic Apps and click on the Logic Apps under Services.

Search Logic Apps

  1. Click on + Add

Add Logic Apps

  1. Enter the required Logic Apps information

Property Value
Resource Group Select the resource group available to you, e.g. Developer<XX>
Logic App Name Use a unique name, e.g. Developer<XX>-OrderItem
Region Select North Europe
Plan Type Select Consumption

Create Logic App

  1. Click on Review + Create/ Create

  2. Once the creation is done, click on Go to resource

Create Logic App

Design your workflow in Azure Logic Apps

Setting up the Flow

📺 Jump to the video

  1. On the welcome screen, select When a HTTP request is received. In the first step we will trigger the Logic Apps flow manually, but later on the SAP system can trigger the request automatically when a new order has been created in the Online Shop.

Start with HTTP Trigger

Note - Sometimes it takes a long time to load the Logic Apps Designer for the first time. If this happens, just click on Refresh on your browser.

Note - Please start by switching back to the "old" Canvas to ensure consistency with the following screenshots.

Start with HTTP Trigger

  1. Click on + New Step

New Step

  1. Search for and select SAP in the Choose an operations box.

Select SAP

  1. Select [RFC] Call function in SAP (preview), select the on-prem data Gateway system and also provide the SAP System detail information as mentioned below.

Call RFC

  1. Create the Connection using the following values.

Property Value
Connection name Use a unique name, e.g. Dev<XX>-SAPConnection
Connection Gateway Select AKDevelopmentWithJohnWin4
Client 100
SAP Username Developer<XX>
SAP Password <YourPassword>
AS Host 10.0.0.34
AS Service 3200
AS System Number 00

Connection Details

  1. Click on Create

  2. Click on the Add new parameter drop down and select RFC Filter Group

Note - You need to click "somewhere" else so that the dialog box closes.

RFC Filter Group

Warning - Fetching all the filter groups from the SAP system may take some time. Use "Enter Custom Value" to enter the technical name Z_ONLINESHOP_MSF:msf.

Enter Custom Value

  1. Enter the Filter group name Z_ONLINESHOP_MSF:msf

Select Filter Group

  1. From the RFC Name field, select the RFC ZF_RFC_ONLINESHOP_GET_ORDER:order:Z_ONLINESHOP_MSF.

Enter Custom Value

  1. As a first step we want to lookup a specific Order ID by IM_ORDER number. For the first test, enter Order ID 12 (feel free to select a number of an order that you have previously created!)
<ZF_RFC_ONLINESHOP_GET_ORDER xmlns="http://Microsoft.LobServices.Sap/2007/03/Rfc/">
<IM_ORDER>       12</IM_ORDER>
</ZF_RFC_ONLINESHOP_GET_ORDER>

Warning - watch out for the leading spaces in the XML payload.

Call SAP Function

  1. From the top of the flow click on Save and Run Trigger to execute the Flow.

Save and run

  1. As a result you will see the OrderID and some additional information coming back from the SAP System.

First results

  1. Copy results from the Json Response to your Clipboard. We will use it in the next steps.
{
  "EM_ORDER": [
    {
      "CLIENT": "",
      "ORDERUUID": "44g8idhTHt2oxgLO5ZOh1w==",
      "ORDERID": "00000012",
      "ORDEREDITEM": "Laptop",
      "PURCHASEREQN": "0010001417",
      "PRSTATUS": "In Process",
      "CREATED_AT": 0,
      "CREATED_BY": "",
      "LAST_CHANGED_BY": "",
      "LAST_CHANGED_AT": 0,
      "LOCAL_LAST_CHANGED_AT": 0
    }
  ]
}

Working with the results from SAP

📺 Jump to the video

  1. With the results from the RFC call, we can now take this data and use it to publish to Teams. Click on Designer to return to the Logic Apps Designer view.

Back to Designer

  1. The first step is that we need to parse the results from the RFC call. Click on the + New Step

Open Action

  1. Type Parse JSON and select the Parse JSON Action.

Open Action

  1. Select the Content Field and from the Dynamic content pane on the right select JsonResponse Then click on Use sample payload to generate schema. This allows us to leverage the output of the RFC call from the SAP system and generate a Schema directly out of it.

Open Action

  1. Next we can paste the sample payload from the first run.
{
  "EM_ORDER": [
    {
      "CLIENT": "",
      "ORDERUUID": "44g8idhTHt2oxgLO5ZOh1w==",
      "ORDERID": "00000012",
      "ORDEREDITEM": "Laptop",
      "PURCHASEREQN": "0010001417",
      "PRSTATUS": "In Process",
      "CREATED_AT": 0,
      "CREATED_BY": "",
      "LAST_CHANGED_BY": "",
      "LAST_CHANGED_AT": 0,
      "LOCAL_LAST_CHANGED_AT": 0
    }
  ]
}

Paste Sample

  1. The Parse JSON Action should now look like this:

Paste Sample

Create Adaptive Card in Teams

📺 Jump to the video

  1. In order to create an Adaptive Card to Teams, we now need to add another Action. As before, click on + New Step and search for Post adaptive card. Select the Post adaptive card in a chat or channel

Open Action

  1. Click on the Sign-In button, to Sign-in with your Office 365 user in Teams

Open Action

  1. Select your User and Authenticate

Open Action

  1. In the Post in drop-down select Channel

Open Action

Note: Please make sure to select the value from the drop-down. Don't type it in!

  1. Select a Team and Channel (just remember which combination you selected)

Open Action

  1. For convenience, leverage below json created with the Adaptive Card Designer and paste the content into the respective field.

⤵️AdaptiveCard code block

{
    "type": "AdaptiveCard",
    "body": [
        {
            "type": "TextBlock",
            "size": "Medium",
            "weight": "Bolder",
            "text": "New Order has been placed in the Online Shop"
        },
        {
            "type": "ColumnSet",
            "columns": [
                {
                    "type": "Column",
                    "items": [
                        {
                            "type": "TextBlock",
                            "weight": "Bolder",
                            "text": "Hi, ",
                            "wrap": true
                        }
                    ],
                    "width": "stretch"
                }
            ]
        },
        {
            "type": "TextBlock",
            "text": "A new order has been placed in the Online Shop URL. Please review the provided information. ",
            "wrap": true
        },
        {
            "type": "FactSet",
            "facts": [
                {
                    "title": "Order ID",
                    "value": "${value}"
                },
                {
                    "title": "Status Purchase Requisition",
                    "value": "${value}"
                },
                {
                    "title": "Ordered Items",
                    "value": "${value}"
                },
                {
                    "title": "Quantity",
                    "value": "${value}"
                },
                {
                    "title": "Description Text: ",
                    "value": "${value}"
                },
                {
                    "title": "Purchase Requisition: ",
                    "value": "${value}"
                }
            ]
        }
    ],
    "actions": [
        {
            "type": "Action.OpenUrl",
            "title": "View",
            "url": "URL"
        }
    ],
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "version": "1.3"
}

Open Action

Note - Feel free to switch over to the Adaptive Card Designer and create your own Adaptive Card. Just make sure that you have several "placeholder" for Order ID, Status Purchase Requisition, Ordered Items and Purchase Requisition.

  1. The adaptive Card has some hard coded "placeholder" in it. Find the place for Order ID and replace the ${value} with the Dynamic Content from the Parsed JSON response from the SAP System.

Do the same for the other properties (we are not yet updating Description Text or Quantity since these values are not returned by the RFC).

  • Order ID -> ORDERID
  • Status Purchase Requisition -> PRSTATUS
  • Ordered Items -> ORDEREDITEM
  • Purchase Requisition -> PURCHASEREQN

Replace Placeholder

Note - You might have seen that when adding the first OrderID dynamic variable, the Adaptive Card was put in a For each loop. That is because the schema of the resulting Json returns an array and potentially we could get multiple Orders back when filtering for a specific Order ID.

For each section

  1. Save and Run* the Logic App flow again via Run Trigger -> Run. As a result you should see an Adaptive Card in Teams showing the information from the Order specified (make sure to navigate to your Teams Channel, e.g. Contoso -> General)

For each section

Note - If not all properties are shown, go back to the Teams action in the Logic Apps and validate the configuration.

Note - You can find a template for the Logic App flow for Quest 1 (you still need to adjust to your specific SAP Connector and Teams connection):


⤵️Block for the full Logic App Code for Quest 1
{
    "definition": {
        "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
        "actions": {
            "For_each": {
                "actions": {
                    "Post_adaptive_card_in_a_chat_or_channel": {
                        "inputs": {
                            "body": {
                                "messageBody": "{\n    \"type\": \"AdaptiveCard\",\n    \"body\": [\n        {\n            \"type\": \"TextBlock\",\n            \"size\": \"Medium\",\n            \"weight\": \"Bolder\",\n            \"text\": \"New Order has been placed in the Online Shop\"\n        },\n        {\n            \"type\": \"ColumnSet\",\n            \"columns\": [\n                {\n                    \"type\": \"Column\",\n                    \"items\": [\n                        {\n                            \"type\": \"TextBlock\",\n                            \"weight\": \"Bolder\",\n                            \"text\": \"Hi, \",\n                            \"wrap\": true\n                        }\n                    ],\n                    \"width\": \"stretch\"\n                }\n            ]\n        },\n        {\n            \"type\": \"TextBlock\",\n            \"text\": \"A new order has been place in the Online Shop URL. Please review the provided information. \",\n            \"wrap\": true\n        },\n        {\n            \"type\": \"FactSet\",\n            \"facts\": [\n                {\n                    \"title\": \"Order ID\",\n                    \"value\": \"@{items('For_each')?['ORDERID']}\"\n                },\n                {\n                    \"title\": \"Status Purchase Requisition\",\n                    \"value\": \"@{items('For_each')?['PRSTATUS']}\"\n                },\n                {\n                    \"title\": \"Ordered Items\",\n                    \"value\": \"@{items('For_each')?['ORDEREDITEM']}\"\n                },\n                {\n                    \"title\": \"Quantity\",\n                    \"value\": \"${value}\"\n                },\n                {\n                    \"title\": \"Description Text: \",\n                    \"value\": \"${value}\"\n                },\n                {\n                    \"title\": \"Purchase Requisition: \",\n                    \"value\": \"@{items('For_each')?['PURCHASEREQN']}\"\n                }\n            ]\n        }\n    ],\n    \"actions\": [\n        {\n            \"type\": \"Action.OpenUrl\",\n            \"title\": \"View\",\n            \"url\": \"URL\"\n        }\n    ],\n    \"$schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\",\n    \"version\": \"1.3\"\n}",
                                "recipient": {
                                    "channelId": "19:a38680470d95481685c064f36a146e24@thread.tacv2",
                                    "groupId": "c1eedb2a-3a35-4f0e-98e3-898c2d5e907c"
                                }
                            },
                            "host": {
                                "connection": {
                                    "name": "@parameters('$connections')['teams']['connectionId']"
                                }
                            },
                            "method": "post",
                            "path": "/v1.0/teams/conversation/adaptivecard/poster/Flow bot/location/@{encodeURIComponent('Channel')}"
                        },
                        "runAfter": {},
                        "type": "ApiConnection"
                    }
                },
                "foreach": "@body('Parse_JSON')?['EM_ORDER']",
                "runAfter": {
                    "Parse_JSON": [
                        "Succeeded"
                    ]
                },
                "type": "Foreach"
            },
            "Parse_JSON": {
                "inputs": {
                    "content": "@body('[RFC]_Call_function_in_SAP')?['JsonResponse']",
                    "schema": {
                        "properties": {
                            "EM_ORDER": {
                                "items": {
                                    "properties": {
                                        "CLIENT": {
                                            "type": "string"
                                        },
                                        "CREATED_AT": {
                                            "type": "integer"
                                        },
                                        "CREATED_BY": {
                                            "type": "string"
                                        },
                                        "LAST_CHANGED_AT": {
                                            "type": "integer"
                                        },
                                        "LAST_CHANGED_BY": {
                                            "type": "string"
                                        },
                                        "LOCAL_LAST_CHANGED_AT": {
                                            "type": "integer"
                                        },
                                        "ORDEREDITEM": {
                                            "type": "string"
                                        },
                                        "ORDERID": {
                                            "type": "string"
                                        },
                                        "ORDERUUID": {
                                            "type": "string"
                                        },
                                        "PRSTATUS": {
                                            "type": "string"
                                        },
                                        "PURCHASEREQN": {
                                            "type": "string"
                                        }
                                    },
                                    "required": [
                                        "CLIENT",
                                        "ORDERUUID",
                                        "ORDERID",
                                        "ORDEREDITEM",
                                        "PURCHASEREQN",
                                        "PRSTATUS",
                                        "CREATED_AT",
                                        "CREATED_BY",
                                        "LAST_CHANGED_BY",
                                        "LAST_CHANGED_AT",
                                        "LOCAL_LAST_CHANGED_AT"
                                    ],
                                    "type": "object"
                                },
                                "type": "array"
                            }
                        },
                        "type": "object"
                    }
                },
                "runAfter": {
                    "[RFC]_Call_function_in_SAP": [
                        "Succeeded"
                    ]
                },
                "type": "ParseJson"
            },
            "[RFC]_Call_function_in_SAP": {
                "inputs": {
                    "body": "<ZF_RFC_ONLINESHOP_GET_ORDER xmlns=\"http://Microsoft.LobServices.Sap/2007/03/Rfc/\">\n<IM_ORDER>       10</IM_ORDER>\n</ZF_RFC_ONLINESHOP_GET_ORDER>",
                    "host": {
                        "connection": {
                            "name": "@parameters('$connections')['sap']['connectionId']"
                        }
                    },
                    "method": "post",
                    "path": "/CallRfc",
                    "queries": {
                        "autoCommit": false,
                        "rfcGroupFilter": "Z_ONLINESHOP_MSF:msf",
                        "rfcName": "ZF_RFC_ONLINESHOP_GET_ORDER:order:Z_ONLINESHOP_MSF"
                    }
                },
                "runAfter": {},
                "type": "ApiConnection"
            }
        },
        "contentVersion": "1.0.0.0",
        "outputs": {},
        "parameters": {
            "$connections": {
                "defaultValue": {},
                "type": "Object"
            }
        },
        "triggers": {
            "manual": {
                "inputs": {
                    "schema": {}
                },
                "kind": "Http",
                "type": "Request"
            }
        }
    },
    "parameters": {
        "$connections": {
            "value": {
                "sap": {
                    "connectionId": "/subscriptions/22a9ba10-8328-4f21-baeb-50728288a33c/resourceGroups/Developer103/providers/Microsoft.Web/connections/sap",
                    "connectionName": "sap",
                    "id": "/subscriptions/22a9ba10-8328-4f21-baeb-50728288a33c/providers/Microsoft.Web/locations/northeurope/managedApis/sap"
                },
                "teams": {
                    "connectionId": "/subscriptions/22a9ba10-8328-4f21-baeb-50728288a33c/resourceGroups/Developer103/providers/Microsoft.Web/connections/teams",
                    "connectionName": "teams",
                    "id": "/subscriptions/22a9ba10-8328-4f21-baeb-50728288a33c/providers/Microsoft.Web/locations/northeurope/managedApis/teams"
                }
            }
        }
    }
}

Where to next?

< The Journey - 🏠Home - Quest 2 >

🔝