Technical Notes: MDRs in the SAP Cloud Application Studio

This is the first article in a series of technical notes that will be published on the AtlantConsult website. In it, Andrei Matys, a software engineer in the development department of the CX direction of our company, will tell general information about MDRs in SAP Cloud Application Studio.

In this article, I would like to tell you about mass data runs (MDRs) in SAP Sales/Service Cloud.

MDR provides functionality for periodical background data processing. For example: periodical customer analyzing, periodical sending of data to external systems or just updating a huge amount of data. In simple cases, we can use workflows instead of MDRs, but in complex cases we can’t do like this.

Main elements of MDR are business object with query and action and MDR. Query is used for retrieving data from database. Action contains business logic to be executed. This information is shown in picture 1.

 

 

Picture 1 – General structure

 

Sequence of steps is shown in picture 2.

 


 

Picture 2 – Steps of MDR run

 

To start MDR we need to create MDR run and schedule it. At the right time MDR run starts and executes query on business object. Action is executed on the returned data amount. After processing of data MDR run finishes.

In SAP Cloud Application, you can create two types of action:

  • mass enabled – process N records per execution;

  • not mass enabled – process 1 record per execution.

 

An example of mass enabled processing data script:

 

import ABSL;

// Iterate through records

foreach(var i in this) {

       // Do something you want

}

 

An example of not mass enabled processing data script:

 

import ABSL;

 

// Type codes

var EMAIL = "39";

 

// Row with TypeCode is just an example

if(this.TypeCode == EMAIL){

       // Do something you want with the current record

}

 

What type of action should we use in MDR? Let’s figure it out.

Example: we want to send notifications (standard system notifications or emails) from ABSL periodically. We can create a business object, which will store all information about notifications and also will contain action, which will be used for sending notifications.

 

Business object:

businessobject NotificationStore {

 

       [AlternativeKey] element NotificationUUID : UUID;

       element SourceUUID : UUID;

       element SourceName : LANGUAGEINDEPENDENT_ENCRYPTED_EXTENDED_Name;

       element SourceType: BusinessTransactionDocumentTypeCode;

       element RecipientUUID : UUID;

       element RecipientName : LANGUAGEINDEPENDENT_ENCRYPTED_LONG_Name;

       element RecipientType: RecipientTypeCode;

       element Status : StatusCode; // custom codelist

       element ChannelType : ChannelTypeCode; // custom codelist

       element CreationDateTime: GLOBAL_DateTime;

       element SendDateTime: GLOBAL_DateTime;

 

       action SendNotifications;

      

}

 

Action SendNotifications:

 

import AP.Common.GDT as apCommonGDT;

 

// Channel type

var EMAIL = "01";

var NOTIFICATION = "02";

 

// Filter notifications

var notifications = this.Where(n => n.ChannelType == NOTIFICATION);

var emails = this.Where(n => n.ChannelType == EMAIL);

 

// Send notifications

foreach(var oneNotification in notifications){

              // Do something

}

 

// Send emails

foreach(var oneEmail in emails){

              // Do something    

}

 

 

MDR settings will look like in picture 3.

 


 

Picture 3 – MDR settings

 

All these settings will work as in picture 4.

 


 

Picture 4 – Scheme for mass enabled action

 

Mass enabled action is very useful in case if our business object stores data, which we can process per one script execution. For example, select all notifications and send them according to a channel type. Action will receive all rows and process them.

What about cases, when can we use not mass enabled script? One new condition should be added to the task of the previous example: we want to separate business logic and persistence. The solution for this is adding new business object to the existing one:

 

businessobject Sender {

 

       [AlternativeKey] element SenderType : SenderTypeCode; // custom codelist

      

       action SendEmails;

       action SendStandartNotifications;

       action Run;

 

}

 

Action SendStandartNotifications:

 

import AP.Common.GDT as apCommonGDT;

 

// Channel type

var EMAIL = "01";

var NOTIFICATION = "02";

 

// Notification status

var NOT_PROCESSED = "00";

 

// Get notifications using query

var queryNotifications = NotificationStore.QueryByElements; // Use standard query for example

var selParamsNotifications = queryNotifications.CreateSelectionParams();

// Add selection parameters (if needed)

selParamsNotifications.Add(queryNotifications.ChannelType, "E", "EQ", NOTIFICATION);

selParamsNotifications.Add(queryNotifications.Status, "E", "EQ", NOT_PROCESSED);

var resultNotifications = queryNotifications.Execute(selParamsNotifications);

 

// Send notifications

foreach(var oneNotification in resultNotifications){

              // Do something

}

 

Action Run will look like:

import ABSL;

 

var EMAILS_SENDER = "001";

var NOTIFICATIONS_SENDER = "002";

 

switch(this.SenderType){

       case EMAILS_SENDER {

              this.SendEmails();

       }

       case NOTIFICATIONS_SENDER {

              this.SendNotifications();

       }

}

 

MDR settings will look like in picture 5.

 


 

Picture 5 – MDR settings

 

Scheme for the not mass enabled action in this case will look like in picture 6.

 


 

Picture 6 – Scheme for not mass enabled action

 

So, we looked through two main ways of creating MDRs.

1.   Business object + data + action (mass enabled).

2.   Business object + data and Sender + action (not mass enabled).

Also exist:

3.   Business object + data + action (not mass enabled). Action will be called for every row. In script we don’t need to have cycle through this.

4.   Business object + data and Sender business object + action (mass enabled).

5.   In the main (Run) action we should add iteration through this.

 

Main ideas of using not mass enabled action and some additional object are:

-     Separation of logic and persistence (BO for business logic, BO for saving data);

-     Impossibility of dynamic argument usage in MDR run;

-     Standard BO, where we can’t add custom action (example, Account);

-     Complex selection logic and etc.

 

Important: rows in DB should exist for action execution. It means that for sender BO you should create rows manually (using WS or UI).

 

In the end, let’s sum up theoretical information:

-     MDR provides functionality for periodical background data processing;

-     Main elements: BO (action and query required), MDR;

-     For scheduling MDR you should create and schedule run;

-     Mass data run executes query, to get data from business object, query returns data and action on these data is executed.

-     Additional object is not obligatory.

 

P.S

If you need to do a lot of different general tasks in background you can create multifunctional business object:

 

import AP.Common.GDT as apCommonGDT;

 

businessobject MultifunctionalBO raises MsgInfo_EN {

 

       message MsgInfo_EN text "Message: &1": LANGUAGEINDEPENDENT_EXTENDED_Text;

 

       [Label("Type")] element Action : MDRActionCode;

      

       action Run;

       action ActionOne; // Action name is an example

       action ActionTwo; // Action name is an example

      

}

 

And action Run will start needed scripts.