An Example Of Extending SAP FSM With SCP Extension Factory

Share on facebook
Share on twitter
Share on linkedin

An Example Of Extending SAP FSM With SCP Extension Factory

Introduction

This blog is a look at what you can do with the SAP Cloud Platform Extension Factory in the context of SAP Field Service Management at this point in time.

We will discuss a practical example of how to implement a Lambda function, use a Service API from the FSM Instance within it and do something with the resulting message.

We will not cover how to set up the connection as this is documented quite extensively and clearly in the official SAP documentation, this is more to get a feel for how you can go about developing an extension yourself. 

Why?

At times you may need to implement some custom logic that cannot be handled by the standard cloud offering.  In order to allow flexibility, we implement additional handlers or extensions to the existing functionality.

Most of the time this comes in the form of events.  Currently, for Field Service Management, there is only 1 event outside of the Crowd Sourcing; activity.closed which occurs when an activity is closed or completed.

In this blog, we will aim to show you the process of developing a Lambda function to take the data from the Activity.closed event, call the Query API to get the Activity details and then send the details to a Slack channel.  

What?

SAP Cloud Platform Extension Factory essentially uses a Kyma runtime to allow you to implement ‘serverless’ functions or lambdas. 

In this blog, we will look at one event and one API and show how you could use these together in a lambda function.

Setup

The initial setup is fairly simple.  Overall the steps are to

  1. Provision or use an existing Kyma runtime in the C/4 HANA Cockpit
  2. Connect your FSM instance to a runtime
  3. Create instances of the supplied services in a namespace in Kyma
  4. Finally, create a Lambda implementing one of the events

For the purposes of this blog we will not go through the first three setup steps in detail as you can find more info here:

Application Help SAP C/4HANA Foundation

SAP Field Service Management Help System

We will, however, go through the finer details of how to make use of the events and services.  

From here on we assume you have set up the connection between FSM and Kyma, and have created instances of the Service API and Query API in your namespace at minimum.

Creating a Lambda Function

Purpose:

Our purpose is to implement a function that will notify a Slack channel with activity details on completion.

In the Kyma runtime, in the namespace with the FSM Services and Events, click on Lambdas.  

Create a new function and in the function trigger you should see the following options (or more)

SCP Extension Factory

Today we will use the fsm.activity.closed event trigger as this is triggered when an activity is closed.

Let’s not worry too much about the Code just yet, scroll down to dependencies. 

Dependencies:

This section is exactly the dependencies section of a Node.js application. We are going to want to use Axios, util and slack-node.  

Axios:

This is used to make a post request to the Query API, you can use your favourite handler

Slack-Node:

This is used to post a message to a Slack webhook

Util:

This is used to easily decode the response object from Axios into a string.  

Service Bindings:

Here is where we can specify which services we are going to make use of.  

We are going to use the Query API from FSM here

SCP Extension Factory

What this does is take the API connection from the provided Services (complete with authentication) and give us a URL we can use in our code.

Code:

So let’s break down the code we need. Let’s remember our end goal of sending some Activity data to Slack on completion of an activity in the context of what we have available.

Events:

The first thing we need to know is what information we get when this event is triggered. 

If we go to the Service Management catalogue and check the Service API we can see it provides 1 event with the following signature:

SCP Extension Factory

What this means is that when an activity is closed, the FSM system will provide the activity ID in a JSON data format for users to use.  

However, we want to be able to provide more information about the activity in the message to Slack, so we need some way to get the data from FSM.  

Query API:

This is where the Query API service comes in to play. This API can retrieve all sorts of data from FSM.  

Looking at the Query API we can see there is one endpoint and it takes some JSON data with a query string:

The provided documentation link also provides info about the DTO objects in question, and you can also provide more complex queries.  

For our purposes though we will retrieve the main details of the activity, not the Service Call or Business Partner.

Code Snippets:

Activity ID

So step one is to get the event data provided to retrieve the Activity ID.  This is relatively simple.  The main function provides an input called event, which is a JSON object, and since we know it contains an activity ID we can simply access it like so:

module.exports = {

    main: function(event, context) {

       var activityId = event.data.activityId;

Now of course in a production scenario we would add some error handling but I will leave this as an exercise for the reader in this case

Retrieve Activity Details

Now that we have the activity ID, we need to post a query to the Query API to get more details. To do this we will use Axios to make the posting a bit simpler.  Step one we will build an asynchronous function to return data, this way we can make use of await.  Ideally, this function would then return data which we would then post to Slack, but for the purposes of simplicity I have combined this method with the call to Slack.

async function postQuery(url, data) {

    // send the request

    try {

        var res = await axios.post(url, data, {

            headers: {

                “X-Client-Id”: ‘KYMA’,

                “X-Client-Version”: 1

            },

            params: {

                account: ‘fair….’,

                company: ‘FAIR_….’,

                clientIdentifier: ‘COR_CON_NONE’,

                dtos: ‘Activity.30’

            }

        });

    } catch (error) {

        postSlackMsg(util.inspect(error));

        return;

    }

    postSlackMsg(util.inspect(res.data,true,null));

}

Some key information here, even though the API has the authentication parameters sorted for you, we still need to supply some headers, otherwise we get an error response.  X-Client-Id can be used to identify where the calls are coming from and the version is again simply for informational purposes but needs to be supplied.

In the Params we are setting up the URL parameters, if you look at the documentation this is how this information is supplied.

SCP Extension Factory

So now we need to supply this method with the Query string to pass to the API and implement the method to send it to Slack.

One enhancement here might be to supply environment variables for the Company and Account to limit the hardcoding and enable you to easily tweak it as required along the way.

Query String and URL

This part is super simple, we know we need a JSON object with a query field and data.  The URL comes from the Service Bindings.  To retrieve this is as simple as retrieving an environment variable.

var data = {

            query: “SELECT a FROM Activity a where a.id = ‘” + event.data.activityId + “‘”

        };

 

        var url = `${process.env.GATEWAY_URL}` + “/v1”;

So the first line sets up our body for the Query request, selecting all activity details from the Activity DTO for our given activity ID.

The second line generates our URL from the process environment variable GATEWAY_URL, this is the service endpoint.  Note: It is an ‘endpoint’ internal to Kyma. We add the “/v1” to the end as this is shown in the Query API section above.

The “GATEWAY_URL” comes from the Service Bindings -> Environment Variable Name.  Note that when we create a binding, we can supply a prefix, this way we can have multiple services if we need to access other APIs. 

Posting a Message to Slack

function postSlackMsg(slackMsg){

    const webhookUri = ‘https://hooks.slack.com/services/TAX0X9J49/B…………’;

    const slack = new Slack();

    slack.setWebhook(webhookUri);

    slack.webhook({

      text: slackMsg

     }, function(err, response) {

       console.log(err, response)

     })

}

This is relatively simple using the slack-node package.  Setting up a webhook for Slack is not covered in this blog, but you could also set up any other endpoint to post your data to.

What If It doesn't Work?

One place to start would be the Kyma Logs, you can filter by your function or other labels:

This is where you will see entries from console.log or other loggers.  For example, if you log the error response from the Axios call with no X-Client-ID posted you can see this in the logs:

You could also post the error message to Slack in which case you will see this:

SCP

You could also run the Node.js code standalone however you’d need to substitute in the API URL in the environment for something you can access.  

Results

Putting this all together we are now able to take the event data from FSM, identify which activity was completed, retrieve the data about the activity from FSM and post this information to Slack.  

Here is what one such message looks like:

SCP Extension Factory

The query response structure is defined in the DTOs on the Coresystems documentation, the root entity is named according to the parameters in the query.

Sending this information as is to Slack is probably not going to be useful but you can see how you could pass this data to potentially anything, perhaps you could identify closed activities and send out surveys or mark contacts with repeated closures, etc.  

As more events are implemented for you to extend, the more power and flexibility you have to implement extensions like this.

Author:

David Till

David Till

Subscribe to our newsletter