Send SAP workflow notifications to Microsoft Teams

Send SAP workflow notifications to Microsoft Teams using Looply

This is a step-by-step guide to triggering a notification in Teams from an SAP workflow.

In this example we have defined a simple workflow that is triggered from an event.  We start by identifying the event for a customer master change, using the Event Trace (SWEL).

The event trace shows that event BUS1006 – CHANGED is triggered, so we take that as the starting place for the workflow definition.

Next we add binding from the triggering object to the workflow container.

In this case we just take one field, the customer number. We create a custom variable in the SAP workflow ‘PARTNER’ for this purpose.

Next we add a step to trigger Looply.  Normally we would add this step to an existing workflow.

The Looply step is based on a standard task to trigger Looply using /LOOPLY/WF_OUT->TRIGGER

We need these 4 fields in the Looply binding.

Optionally you could pass in partner number or other data to &IM_DATA&.

Now the SAP workflow can be activated.

The final step for the SAP workflow is to activate the event type linkages.

We use the same object type and event as in the workflow triggering event, and set the receiver to be the workflow ID.

Next we set up the Looply Process Determination table.

The key is based on the fields we set in the workflow binding.

This table is used to determine the Looply Workflow ID and the function to prepare the data for Looply.

The trigger function can include lots of process-specific data lookup, or pass the contents of the SAP workflow container.

FUNCTION zlooply_wf_trigger_generic.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IM_WORKITEMID) TYPE  SWW_WIID
*"     VALUE(IM_DATA) TYPE  SWF_STRING
*"  EXPORTING
*"     VALUE(EX_CONT_DATA) TYPE  SWF_STRING
*"     VALUE(EX_SUBRC) TYPE  SYSUBRC
*"     VALUE(EX_MESS) TYPE  BAPIRET2
*"  CHANGING
*"     VALUE(CH_LOOPLY_DATA) TYPE  /LOOPLY/TRIGGER_DATA_T
*"----------------------------------------------------------------------

* This function is called by Looply Core when task 90000004 is used inside an SAP Workflow.
* The parameters can be used as follows:

*  IM_WORKITEMID: This will contain the workitem id (assuming you bound it to it in swdd when creating the wf). It can be used to get data from the workflow container using fm SAP_WAPI_READ_CONTAINER
*  IM_DATA: This can be used to pass in any (string) data from the workflow container via the appropriate binding
*  EX_CONT_DATA: Use to pass back any (string) data to the Workflow container - bind it to whatever (string) variable of the container you need to
*  EX_SUBRC: Assuming parameter IM_IGNORE_ERRRORS of the standard task has not been set to X, setting a subrc != 0, will cause the LOOPLY core method to raise an exception
*  EX_MESS: When the exception is raised you can use this parameter to stick a certain message in the workflow log
*  CH_LOOPLY_DATA: This table can be prefilled by the sap workflow. Looply will be triggered once for each row on this table. Contains the following fields which will get passed to Looply:
*        PROCESS_ID: The process id of the Looply workflow that will get triggered. You can only have one active workflow per process id
*        RECIPIENT_EMAIL: Can be used to send a card to a certain user (of course you can bind the recipient to any field in the data you like on the looply side)
*        RECIPIENT_UNAME: Not actually passed to Looply. Used in here in case you want to get data for a certain sap user  (OPTIONAL)
*        DATA: Data string we pass to Looply. You can use method /ui2/cl_json=>serialize to convert an itan to a json string if needed (OPTIONAL)
*        UTIL_DATA: In case you'd like to pass a second/seperate string to Looply (OPTIONAL)

*-----------------------------------------------------------------------------------------
* Generic function - all we have here is the workflow workitem

* Data Declarations

DATA: ls_looply_data TYPE /looply/trigger_data_s,
lv_subrc       TYPE sysubrc,
ls_wf          TYPE sww_wi2obj,
lv_wi_id       TYPE sww_wiid,
lv_wi_top_id   TYPE sww_wiid,
lt_simple_cont TYPE TABLE OF swr_cont,
ls_simple_cont TYPE swr_cont,
lt_subcont_obj TYPE TABLE OF swr_cont,
ls_subcont_obj TYPE swr_cont,
ls_recipients  TYPE swragent,
lt_recipients  TYPE TABLE OF swragent,
lv_approver    TYPE xubname,
lv_username    TYPE bapiusdesc,
ls_address     TYPE bapiaddr3,
lt_return      TYPE bapiret2_t.

*----------------------------------------------------------------------------------------*
* Set process id.
ls_looply_data-process_id = im_workitemid.

*----------------------------------------------------------------------------------------*
* Read Workflow Container

CALL FUNCTION 'SAP_WAPI_READ_CONTAINER'
EXPORTING
workitem_id              = im_workitemid
IMPORTING
return_code              = lv_subrc
TABLES
simple_container         = lt_simple_cont
subcontainer_all_objects = lt_subcont_obj.

* Transform to JSON
ls_looply_data-data = /ui2/cl_json=>serialize( data = lt_simple_cont pretty_name = 'X' ).

* Get the latest workitem
SELECT * FROM sww_wi2obj UP TO 1 ROWS INTO ls_wf WHERE top_wi_id = lv_wi_top_id ORDER BY wi_id DESCENDING.
ENDSELECT.
lv_wi_id = ls_wf-wi_id.

* Get the approver(s)
CALL FUNCTION 'SAP_WAPI_WORKITEM_RECIPIENTS'
EXPORTING
workitem_id = lv_wi_id
IMPORTING
return_code = lv_subrc
TABLES
recipients  = lt_recipients.

IF lt_recipients IS INITIAL.
* No agent found, trigger looply without an agent.
APPEND ls_looply_data TO ch_looply_data.
ELSE.

LOOP AT lt_recipients INTO ls_recipients.
lv_approver = ls_recipients-objid.

* Read approver email address
CALL FUNCTION 'BAPI_USER_GET_DETAIL'
EXPORTING
username    = lv_approver
IMPORTING
description = lv_username
address     = ls_address
TABLES
return      = lt_return.

ls_looply_data-recipient_email = ls_address-e_mail.
APPEND ls_looply_data TO ch_looply_data.

ENDLOOP.

ENDIF.

ENDFUNCTION.

 

To the above generic code, we add this code to make the partner number easier to map in Looply

* Get partner number
read table lt_simple_cont into ls_simple_cont with key element = 'PARTNER'.
ls_looply_data-UTIL_DATA = ls_simple_cont-value.

 

In the Looply Workflow Studio we define the Looply Workflow.  Once created, this gives us the workflow ID to put into the Looply Process Determination table.

In this example we just show a card, wait a minute, and then delete it.

We can use data from SAP in the card definition.

This card consists of two text fields, and the second one is bound to the ‘util_data’ field that we filled in the triggering function.

In this way, we can add the customer number field to the adaptive card.

That’s it – now we’re ready to test or add more information, links and actions to the card.

See the result in the video: