eXXcellent solutions tech blog logoabout

SAP Fiori Notifications - Part 1

Cover Image for SAP Fiori Notifications - Part 1
Posted
by Igor Muntoreanu

In this blog we will explain how to implement SAP Fiori Notifications on your system and provide some real Business Scenarios with the code snippets. So we start with the question: what are SAP Fiori Notifications?

Notifications in enterprise applications are an effective way to make users aware of situations that require their timely action or attention. Examples include workflow scenarios, such as the assignment of new purchase order approvals or a situation that has just arisen. From Fiori 2.0, SAP Fiori Launchpad provides a Notifications area, by clicking the bell icon in the shell bar at the top right of the screen, that lets you know about important tasks and requests requiring your timely action or knowledge.

In the notifications popover, the user can order notifications in various ways, take action, and navigate to the source of a specific notification. SAP Fiori Launchpad can consume notifications from the SAP Gateway Notification Channel, which is part of the SAP_GWFND software component. The SAP Gateway Notification Channel is a framework for applications to deliver notifications to end users through various channels.

Prerequisites

The following prerequisites are required to get full usage of the Fiori Notifications:

• The component SAP_UI with version 751 SP00 and GWFND with version 7.51 SP00 or higher on the Notification Hub system.

• SAP_BASIS with version 7.51 SP01 or higher on the Backend system(See Note: 2356153 - Business Workflow Extensions - Version 2)

• Fiori Launchpad is configured (see note 2456330 - How to configure Fiori Launchpad step-by-step).

• If you want to use the workflow notification, Fiori My Inbox need to be configured(see note 2424054 - How to setup My Inbox 2.0 app).

More details are described in the SAP Note: 2729492.

Architecture

The Launchpad consumes notifications from the notification channel, which is a Backendsystem that aggregates notifications from different notification providers configured in your environment:

The environment consists anmongst other things of a notification center, a notification hub and a notification provider;

There are three concepts to understand when activating notifications:

• Notification Center – the area in the Fiori Launchpad where notifications are displayed.

• Notification Hub – Collects notifications to be shown in the Notification Center.

• Notification Provider – Provides notification content to the Notification Hub.

The Notifications icon button is embedded in the shell bar and is the central access point for all notifications:

An image shows the Notification icon button with ten unread notifications;

Below we have an example of a list of notifications and the explanation of the schematic behind it:

An image shows an Expanded list of notifications;

An image shows the schematic parts of a notification;

  1. Image
  2. Priority
  3. Title
  4. Action
  5. Operation
  6. Subtitle
  7. Author/Source
  8. Timestamp
  9. Show/hide truncated text (Show More, Show Less)

The Schematic above is an example of the version 1.84 of the SAPUI5, depending of the version, the schematic can vary, to see more details about it, check the Fiori Guidelines at the following link: at this link to the Fiori Guidelines.

Implementation

There are mainly 4 steps to enable the Fiori Notifications:

• Creation and assignment of certain PFCG roles.

• Configuration of the Notification Hub.

• Configuration of the Notification Providers.

• Activation of the Notifications in the Fiori Launchpad.

Mainly all the configurations are performed at the SPRO transaction, under the path:

An image shows the path to the SPRO transactions;

All the steps above are very well documented in the SAP support website and can vary depending of your system version. To see the documentation, please check the note 2488945 at at this link to the documentation.

Technical Details

The notifications are collected from the Backend through the Service Id: /IWNGW/NOTIFICATION_SRV under the Service Group /IWNGW/NOTIFICATION. It was developed using the new approach of the OData v4 and can be seen under the transaction /IWFND/V4_ADMIN:

An image shows the SAP output of the /IWFND/V4_Admin transaction;

Getting even more deeply we have some database tables which handle and keep all the fiori notifications:

/IWNGW/NOTIF - HUB Transactional - Notification Instance

/IWNGW/NRECIP - HUB Transactional - Notification Recipients

/IWNGW/NACTION - HUB Metadata - Notification Type Action

/IWNGW/NTYPE - HUB Metadata - Notification Type Cache

/IWNGW/NTYPE_TT - HUB Metadata - Notification Type Text Template

All the technical objects are stored inside the package /IWNGW/FRAMEWORK - SAP Notification Gateway Framework - Structure Package, and its subpackages:

An image shows the subpackages of package /IWNGW/FRAMEWORK;

Real Business Case Scenario 1

In this scenario we have an Organizational Unit which has a Head of Department and also employees of the Sales Team:

An image shows a list of sales team employees;

The requirement is to send a notification to the Head of Department always when a Sales Order is adjusted or created by someone of the Sales Team. As an example the following sales order was created by Derick, sap user DEF and then the Head of Department has checked on his Fiori Launchpad the received Notification:

• Sales order created trough transaction VA01

An image shows the SAP Input form for the transaction;

• Notification on the Fiori Lauchpad of the Head of Department:

An image shows the notification for the created sales order;

This notification is segmented in 2 parts: title and subtitle. Both have informations from the sales order. Here is how the title and subtitle were technically mapped:

TextTable Source
Sales Order: &1 - &2 of &3 &4 was created/adjusted by &5&1: VBAK-BSTNK
&2: VBAK-VBELN
&3: VBAK-NETWR
&4: VBAK-WAERK
&5: USER
&6: &7. Quantity &8 &9 [...]&6: VBAP-MATNR
&7: VBAP-ARKTX
&8: VBAP-KWMENG
&9: VBAP-MEINS

Technically, to implement this requirement the following 3 steps were implemented:

  1. Configuration of the Notification Provider through the SPRO transaction:

An image shows the path to the SPRO transactions;

An image shows the SAP UI for the SPRO transaction;

  1. Implementation of the class ZCL_SALES_ORDER_NOTIFICATION:

    a. There are 2 ways to connect the class with the notification provider. One of them is to make the class /IWNGW/CL_NOTIF_PROVIDER_ABS as super class, this way implementing the interface /IWNGW/IF_NOTIF_PROVIDER_EXT or just by assigning the class /IWNGW/IF_NOTIF_PROVIDER to the class. In this example we have done the first way:

    An image shows the methods tab of the implemented class;

    b. Method /IWNGW/IF_NOTIF_PROVIDER_EXT~GET_NOTIFICATION_TYPE:

    METHOD /iwngw/if_notif_provider_ext~get_notification_type. es_notification_type-is_groupable = abap_true. es_notification_type-type_key = iv_type_key. es_notification_type-version = iv_type_version. ENDMETHOD.

    c. Method /IWNGW/IF_NOTIF_PROVIDER_EXT~GET_NOTIFICATION_TYPE_TEXT

    METHOD /iwngw/if_notif_provider_ext~get_notification_type_text. DATA: lv_text TYPE string, lv_subtitle TYPE string, ls_type_text TYPE /iwngw/if_notif_provider_ext=>ty_s_notification_type_text. lv_text = TEXT-001. "Sales Order: XVBAK-BSTNK - VBAK-VBELN of VBAK-NETWR was created/adjusted by USER" lv_subtitle = TEXT-003. "XVBAP-MATNR: XVBAP-ARKTX. Quantity XVBAP-KWMENG XVBAP-MEINS REPLACE '&1' WITH '{VBAK-BSTNK}' INTO lv_text. REPLACE '&2' WITH '{VBAK-VBELN}' INTO lv_text. REPLACE '&3' WITH '{VBAK-NETWR}' INTO lv_text. REPLACE '&4' WITH '{VBAK-WAERK}' INTO lv_text. REPLACE '&5' WITH '{USER}' INTO lv_text. REPLACE '&6' WITH '{VBAP-MATNR}' INTO lv_subtitle. REPLACE '&7' WITH '{VBAP-ARKTX}' INTO lv_subtitle. REPLACE '&8' WITH '{VBAP-KWMENG}' INTO lv_subtitle. REPLACE '&9' WITH '{VBAP-MEINS}' INTO lv_subtitle. ls_type_text-name = /iwngw/if_notif_provider_ext=>gc_template_names-template_public. ls_type_text-value = lv_text. APPEND ls_type_text TO et_type_text. ls_type_text-name = /iwngw/if_notif_provider_ext=>gc_template_names-template_sensitive. ls_type_text-value = lv_text. APPEND ls_type_text TO et_type_text. ls_type_text-name = /iwngw/if_notif_provider_ext=>gc_template_names-template_grouped. ls_type_text-value = TEXT-002. "Sales Order Notifications APPEND ls_type_text TO et_type_text. ls_type_text-name = /iwngw/if_notif_provider_ext=>gc_template_names-subtitle. ls_type_text-value = lv_subtitle. "Sales Order Notifications APPEND ls_type_text TO et_type_text. ENDMETHOD.

    d. Method SEND_NOTIFICATION

    METHOD send_notification. DATA: lt_nf TYPE /iwngw/if_notif_provider=>ty_t_notification, ls_nf TYPE LINE OF /iwngw/if_notif_provider=>ty_t_notification, lt_user TYPE STANDARD TABLE OF /iwngw/if_notif_provider=>ty_s_notification_recipient, ls_user TYPE /iwngw/if_notif_provider=>ty_s_notification_recipient, lt_parameter_values TYPE /iwngw/if_notif_provider=>ty_t_notification_parameter, ls_parameter_values TYPE LINE OF /iwngw/if_notif_provider=>ty_t_notification_parameter, ls_parameter TYPE LINE OF /iwngw/if_notif_provider=>ty_t_notification_param_bundle, lt_parameter TYPE /iwngw/if_notif_provider=>ty_t_notification_param_bundle, lt_objec TYPE STANDARD TABLE OF objec. FIELD-SYMBOLS: <fs_value> TYPE any. "Get everyone from the Organization Unit CALL FUNCTION 'RH_STRUC_GET' EXPORTING act_otype = 'O' act_objid = '50000077' " eXXcellent Solutions Organization Unit act_wegid = 'AI_ORGUS' " All users of the Organization Unit TABLES result_objec = lt_objec EXCEPTIONS no_plvar_found = 1 no_entry_found = 2 OTHERS = 3. IF sy-subrc = 0. "Send notification only to the Head of Department READ TABLE lt_objec TRANSPORTING NO FIELDS WITH KEY objid = '50000079'. IF sy-subrc = 0. DATA(lv_tabix) = sy-tabix + 1. TRY. DATA(ls_object) = lt_objec[ lv_tabix ]. CHECK sy-uname <> ls_object-realo. "Avoid the Head of sending the notification to himself READ TABLE lt_objec TRANSPORTING NO FIELDS WITH KEY realo = sy-uname. "Make sure that the user is in the Organization Unit IF sy-subrc = 0. TRY. DATA(lv_system_uuid) = cl_uuid_factory=>create_system_uuid( ). ls_nf-id = lv_system_uuid->create_uuid_x16( ). ls_user-id = ls_object-realo. APPEND ls_user TO lt_user. CLEAR ls_user. ls_nf-type_key = 'ZSALES_ORDER_NOTIFICATION'. ls_nf-type_version = '9'. ls_nf-recipients = lt_user[]. ls_parameter_values-name = 'USER'. ls_parameter_values-type = 'Edm.String'. ls_parameter_values-value = sy-uname. ls_parameter_values-is_sensitive = abap_false. APPEND ls_parameter_values TO lt_parameter_values. CLEAR: ls_parameter_values. ls_parameter_values-name = 'VBAK-VBELN'. ls_parameter_values-type = 'Edm.String'. ASSIGN COMPONENT 'VBELN' OF STRUCTURE is_xvbak TO <fs_value>. ls_parameter_values-value = <fs_value>. SHIFT ls_parameter_values-value LEFT DELETING LEADING '0'. ls_parameter_values-is_sensitive = abap_false. APPEND ls_parameter_values TO lt_parameter_values. CLEAR: ls_parameter_values. ls_parameter_values-name = 'VBAK-NETWR'. ls_parameter_values-type = 'Edm.String'. ASSIGN COMPONENT 'NETWR' OF STRUCTURE is_xvbak TO <fs_value>. ls_parameter_values-value = <fs_value>. ls_parameter_values-is_sensitive = abap_false. APPEND ls_parameter_values TO lt_parameter_values. CLEAR: ls_parameter_values. ls_parameter_values-name = 'VBAK-WAERK'. ls_parameter_values-type = 'Edm.String'. ASSIGN COMPONENT 'WAERK' OF STRUCTURE is_xvbak TO <fs_value>. ls_parameter_values-value = <fs_value>. ls_parameter_values-is_sensitive = abap_false. APPEND ls_parameter_values TO lt_parameter_values. CLEAR: ls_parameter_values. ls_parameter_values-name = 'VBAK-BSTNK'. ls_parameter_values-type = 'Edm.String'. ASSIGN COMPONENT 'BSTNK' OF STRUCTURE is_xvbak TO <fs_value>. ls_parameter_values-value = <fs_value>. ls_parameter_values-is_sensitive = abap_false. APPEND ls_parameter_values TO lt_parameter_values. CLEAR: ls_parameter_values. "Send only the first item to the notification READ TABLE it_xvbap ASSIGNING FIELD-SYMBOL(<fs_xvbap>) INDEX 1. IF sy-subrc = 0. ls_parameter_values-name = 'VBAP-MATNR'. ls_parameter_values-type = 'Edm.String'. ls_parameter_values-value = <fs_xvbap>-matnr. SHIFT ls_parameter_values-value LEFT DELETING LEADING '0'. ls_parameter_values-is_sensitive = abap_false. APPEND ls_parameter_values TO lt_parameter_values. CLEAR: ls_parameter_values. ls_parameter_values-name = 'VBAP-ARKTX'. ls_parameter_values-type = 'Edm.String'. ls_parameter_values-value = <fs_xvbap>-arktx. ls_parameter_values-is_sensitive = abap_false. APPEND ls_parameter_values TO lt_parameter_values. CLEAR: ls_parameter_values. ls_parameter_values-name = 'VBAP-KWMENG'. ls_parameter_values-type = 'Edm.String'. ls_parameter_values-value = <fs_xvbap>-kwmeng. ls_parameter_values-is_sensitive = abap_false. APPEND ls_parameter_values TO lt_parameter_values. CLEAR: ls_parameter_values. ls_parameter_values-name = 'VBAP-MEINS'. ls_parameter_values-type = 'Edm.String'. ls_parameter_values-value = <fs_xvbap>-meins. ls_parameter_values-is_sensitive = abap_false. APPEND ls_parameter_values TO lt_parameter_values. CLEAR: ls_parameter_values. ENDIF. ls_parameter-language = sy-langu. ls_parameter-parameters = lt_parameter_values. APPEND ls_parameter TO lt_parameter. ls_nf-parameters = lt_parameter[]. APPEND ls_nf TO lt_nf. TRY. /iwngw/cl_notification_api=>create_notifications( EXPORTING iv_provider_id = 'ZSALES_ORDER_NOTIFICATION' " class ZCL_GENERIC_NF_ANSWER it_notification = lt_nf ). COMMIT WORK AND WAIT. CATCH /iwngw/cx_notification_api INTO DATA(lrx_api). EXIT. ENDTRY. CATCH cx_uuid_error. EXIT. ENDTRY. ENDIF. CATCH cx_sy_itab_line_not_found. ENDTRY. ENDIF. ENDIF. ENDMETHOD.

    e. Text Elements

    An image shows the text symbols tab of the implemented class;

  2. Implementation of the user exit USEREXIT_SAVE_DOCUMENT at MV45AFZZ, via transaction se38

FORM userexit_save_document. zcl_sales_order_notification=>send_notification( EXPORTING is_xvbak = xvbak it_xvbap = xvbap[] ). ENDFORM.

Real Business Case Scenario 2

A requirement has arrived to send simple generic fiori notifications to certain users through an abap report, within specified date and time and its validity and priority. The user will receive the notification and will have 3 possiblities of answers: Accept, Maybe and Reject. As soon as the user answers the notification, a new notification will be sent to inform the owner of the users answer. Example:

An image shows an input form for a new notification;

Notification received on the Fiori Launchpad for the user IMU:

An image shows the received notification with Buttons for Accecpt, Maybe and Reject;

When he accepts the invitation, an action will be raised and will deliver the message back to the owner of the notification:

An image shows the notification for the accepted invitation;

In the Abap Report, the user can plan the notification to be sent in the future, then a job is scheduled to send the notification at the specified time, that’s why have two extra tables to manage this behavior: ZEXX_NF and ZEXX_NF_NRECIP.

The following 5 steps were performed to implement this requirement:

  1. Creation of 2 tables

    a. ZEXX_NF - Notifications for Fiori

    Notifications for Fiori contain information about the client and the notification key;

    b. ZEXX_NF_NRECIP - Notifications for Fiori Recipients

    Notifications for Fiori Recipients contain information about the client, the notification key and the user name;

  2. Report ZEXX_NOTIFICATION

    a. Body of the Report:

    REPORT zexx_notification. INCLUDE zexx_notification_status_top. INCLUDE zexx_notification_status_pbo. INCLUDE zexx_notification_status_pai. INCLUDE zexx_notification_status_f01. INITIALIZATION. "check authorization PERFORM f_check_authorization. "check if provider active PERFORM f_check_provider. START-OF-SELECTION. CALL SCREEN 0001.

    b. Include TOP: ZEXX_NOTIFICATION_STATUS_TOP

    *&---------------------------------------------------------------------* *& Include ZEXX_NOTIFICATION_STATUS_TOP *&---------------------------------------------------------------------* TYPE-POOLS: vrm. "important: it must respect the size wordwrap_position = 55 - check pbo TYPES: ty_line_size TYPE c LENGTH 55. DATA: * reference to wrapper class of control gv_editor TYPE REF TO cl_gui_textedit, gv_ok_code TYPE sy-ucomm, * reference to custom container: necessary to bind TextEdit Control gv_editor_container TYPE REF TO cl_gui_custom_container, gt_mytable TYPE STANDARD TABLE OF ty_line_size, gv_date_from TYPE cpet_validfrom, gv_date_to TYPE cpet_validfrom, gv_priority TYPE /iwngw/notification_priority. * List box DATA: gv_field TYPE vrm_id, gt_listbox TYPE vrm_values, gs_listbox TYPE LINE OF vrm_values, gs_user TYPE uname. * Bapi User DATA: gs_address TYPE bapiaddr3, gt_return TYPE STANDARD TABLE OF bapiret2.

    c. Include PBO: ZEXX_NOTIFICATION_STATUS_PBO

    *&---------------------------------------------------------------------* *& Include ZEXX_NOTIFICATION_STATUS_PBO *&---------------------------------------------------------------------* *&---------------------------------------------------------------------* *& Module STATUS_0001 OUTPUT *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* MODULE status_0001 OUTPUT. DATA: lv_morgen TYPE sy-datum. SET PF-STATUS 'MAIN100'. SET TITLEBAR '0001'. IF gv_date_from IS INITIAL. gv_date_from = sy-datlo && sy-timlo. ENDIF. IF gv_date_to IS INITIAL. lv_morgen = sy-datlo + 1. gv_date_to = lv_morgen && sy-timlo. ENDIF. IF gv_editor IS INITIAL. * create control container CREATE OBJECT gv_editor_container EXPORTING container_name = 'GV_TEXT_EDITOR' EXCEPTIONS cntl_error = 1 cntl_system_error = 2 create_error = 3 lifetime_error = 4 lifetime_dynpro_dynpro_link = 5. IF sy-subrc EQ 0. * create calls constructor, which initializes, creats and links * TextEdit Control CREATE OBJECT gv_editor EXPORTING parent = gv_editor_container wordwrap_mode = cl_gui_textedit=>wordwrap_at_fixed_position wordwrap_position = 55 wordwrap_to_linebreak_mode = cl_gui_textedit=>true. REFRESH gt_mytable. " to initialize table upon OK_CODE 'BACK' at PAI ENDIF. ENDIF. "Users Listbox: REFRESH gt_listbox. SELECT DISTINCT uname FROM agr_users INTO TABLE @DATA(gt_users) WHERE agr_name = 'ZNTUSERPRODU' OR agr_name = 'ZNTUSERCONSU' OR agr_name = 'ZNTNPDEV' OR agr_name = 'ZNTHUBADM' OR agr_name = 'ZNTBEPADM' AND from_dat <= @sy-datum AND to_dat >= @sy-datum. IF sy-subrc = 0. LOOP AT gt_users INTO DATA(ls_users). gs_listbox-key = ls_users-uname. CALL FUNCTION 'BAPI_USER_GET_DETAIL' EXPORTING username = ls_users-uname IMPORTING address = gs_address TABLES return = gt_return. CONCATENATE gs_address-firstname gs_address-lastname INTO gs_listbox-text SEPARATED BY space. APPEND gs_listbox TO gt_listbox. CLEAR gs_listbox. ENDLOOP. gs_listbox-key = '*'. gs_listbox-text = text-006. APPEND gs_listbox TO gt_listbox. CLEAR gs_listbox. gv_field = 'GS_USER'. CALL FUNCTION 'VRM_SET_VALUES' EXPORTING id = gv_field values = gt_listbox. ENDIF. ENDMODULE.

    d. Include PAI: ZEXX_NOTIFICATION_STATUS_PAI

    *&---------------------------------------------------------------------* *& Include ZEXX_NOTIFICATION_STATUS_PAI *&---------------------------------------------------------------------* *&---------------------------------------------------------------------* *& Module USER_COMMAND_0001 INPUT *&---------------------------------------------------------------------* MODULE user_command_0001 INPUT. CASE gv_ok_code. WHEN 'BACK' OR 'LEAVE' OR 'EXIT'. * Destroy Control. IF NOT gv_editor IS INITIAL. CALL METHOD gv_editor->free EXCEPTIONS OTHERS = 1. IF sy-subrc NE 0. FREE gv_editor. ELSE. * free ABAP object also FREE gv_editor. ENDIF. ENDIF. * destroy container IF NOT gv_editor_container IS INITIAL. CALL METHOD gv_editor_container->free EXCEPTIONS OTHERS = 1. IF sy-subrc EQ 0. FREE gv_editor_container. ELSE. * free ABAP object also FREE gv_editor_container. ENDIF. ENDIF. * finally flush CALL METHOD cl_gui_cfw=>flush EXCEPTIONS OTHERS = 1. IF sy-subrc NE 0. LEAVE PROGRAM. ENDIF. LEAVE PROGRAM. WHEN 'SEND'. PERFORM f_send_notification. WHEN OTHERS. ENDCASE. CLEAR gv_ok_code. ENDMODULE.

    e. Include F01: ZEXX_NOTIFICATION_STATUS_F01

    *&---------------------------------------------------------------------* *& Include ZEXX_NOTIFICATION_STATUS_F01 *&---------------------------------------------------------------------* *&---------------------------------------------------------------------* *& Include /PBK/NOTIFICATION_STATUS_F01 *&---------------------------------------------------------------------* *&---------------------------------------------------------------------* *& Form F_SEND_NOTIFICATION *&---------------------------------------------------------------------* FORM f_send_notification . DATA: ls_notification TYPE zexx_nf, lt_selection TYPE STANDARD TABLE OF rsparams, ls_selection TYPE rsparams. IF gv_date_from IS INITIAL OR gv_date_to IS INITIAL. MESSAGE TEXT-003 TYPE 'S' DISPLAY LIKE 'E'. "Fill the validity EXIT. ENDIF. IF gs_user IS INITIAL. MESSAGE TEXT-007 TYPE 'S' DISPLAY LIKE 'E'. "Select an user to receive the notification EXIT. ELSE. ls_selection-selname = 'S_USER'. ls_selection-kind = 'S'. "Select Options = S ls_selection-option = COND #( WHEN gs_user = '*' THEN 'CP' ELSE 'EQ' ). ls_selection-sign = 'I'. ls_selection-low = gs_user. APPEND ls_selection TO lt_selection. CLEAR ls_selection. ENDIF. IF gv_editor IS BOUND. ls_notification-notif_id = /iwngw/cl_med_util=>new_guid( ). ls_notification-valid_from = gv_date_from. ls_notification-valid_to = gv_date_to. ls_notification-created_by = sy-uname. CALL METHOD gv_editor->get_text_as_r3table IMPORTING table = gt_mytable. CONCATENATE LINES OF gt_mytable INTO ls_notification-notification SEPARATED BY cl_abap_char_utilities=>cr_lf. INSERT zexx_nf FROM ls_notification. IF sy-subrc = 0. ls_selection-selname = 'P_ID'. ls_selection-kind = 'P'. "Parameter = P ls_selection-option = 'EQ'. ls_selection-sign = 'I'. ls_selection-low = ls_notification-notif_id. APPEND ls_selection TO lt_selection. CLEAR ls_selection. ls_selection-selname = 'P_PRI'. ls_selection-kind = 'P'. "Select Options = S ls_selection-option = 'EQ'. ls_selection-sign = 'I'. ls_selection-low = gv_priority. APPEND ls_selection TO lt_selection. CLEAR ls_selection. COMMIT WORK AND WAIT. SUBMIT zexx_notification_send WITH SELECTION-TABLE lt_selection AND RETURN. ENDIF. ENDIF. ENDFORM. *&---------------------------------------------------------------------* *& Form F_CHECK_AUTHORIZATION *&---------------------------------------------------------------------* FORM f_check_authorization. SELECT SINGLE agr_name, uname, from_dat, to_dat FROM agr_users INTO @DATA(ls_users) WHERE ( agr_name = 'ZNTUSERPRODU' OR agr_name = 'ZNTUSERCONSU' OR agr_name = 'ZNTNPDEV' OR agr_name = 'ZNTHUBADM' OR agr_name = 'ZNTBEPADM' ) AND uname = @sy-uname AND from_dat <= @sy-datum AND to_dat >= @sy-datum. IF sy-subrc <> 0. "Sie haben keine Berechtigung zum Senden von Benachrichtigungen MESSAGE TEXT-004 TYPE 'S' DISPLAY LIKE 'E'. LEAVE PROGRAM. ENDIF. ENDFORM. *&---------------------------------------------------------------------* *& Form f_check_provider *&---------------------------------------------------------------------* FORM f_check_provider . DATA(ls_pr_config) = /iwngw/cl_notification_api=>get_provider_config( 'ZGENERIC_NOTIFICATION' ). IF ls_pr_config-active IS INITIAL. "Provider is not active MESSAGE TEXT-005 TYPE 'S' DISPLAY LIKE 'E'. LEAVE PROGRAM. ENDIF. TRY. /iwngw/cl_cos_provider_reg_cof=>assert_provider_id( 'ZGENERIC_NOTIFICATION' ). CATCH /iwngw/cx_cos_provider_reg INTO DATA(lx_cos_provider_reg). "Provider is not active MESSAGE TEXT-005 TYPE 'S' DISPLAY LIKE 'E'. LEAVE PROGRAM. ENDTRY. ENDFORM.

    f. Screen 0001

    PROCESS BEFORE OUTPUT. MODULE status_0001. PROCESS AFTER INPUT. MODULE user_command_0001.

    An image shows the parts of a send fiori notification form, including validation dates, a priority, the receiver and the notification text.;

    g. Text Elements

    An image shows the text symbol tab of ZEXX Notification;

  3. Report ZEXX_NOTIFICATION_SEND

    a. Body of the report:

    *&---------------------------------------------------------------------* *& Report ZEXX_NOTIFICATION_SEND *&---------------------------------------------------------------------* *& This program must not be executed manually! * The program can be executed via job or per the main program of notifications * /PBK/NOTIFICATION_SEND *&---------------------------------------------------------------------* REPORT zexx_notification_send. DATA: zexx_nf TYPE zexx_nf, zexx_nf_nrecip TYPE zexx_nf_nrecip. TYPES: ty_zexx_nf TYPE STANDARD TABLE OF zexx_nf, ty_zexx_nf_nrecip TYPE STANDARD TABLE OF zexx_nf_nrecip. DATA: gt_users TYPE /iwngw/if_notif_provider=>ty_t_notification_recipient. PARAMETERS: p_id TYPE zexx_nf-notif_id, p_pri TYPE /iwngw/notification_priority. "used only for the job option SELECT-OPTIONS: s_id FOR zexx_nf-notif_id MODIF ID job, s_user FOR zexx_nf_nrecip-user_id. INITIALIZATION. AT SELECTION-SCREEN OUTPUT. PERFORM f_treat_screen. START-OF-SELECTION. PERFORM f_delete_outdated. PERFORM f_get_users_to_send_nf. IF sy-batch IS INITIAL. PERFORM f_send_notification USING p_id. ELSE. PERFORM f_send_notification_batch. ENDIF. *&---------------------------------------------------------------------* *& Form F_DELETE_OUTDATED *&---------------------------------------------------------------------* FORM f_delete_outdated. GET TIME STAMP FIELD DATA(lv_timestamp). CONVERT TIME STAMP lv_timestamp TIME ZONE sy-zonlo INTO DATE DATA(lv_date) TIME DATA(lv_time). lv_timestamp = lv_date && lv_time. SELECT * FROM zexx_nf INTO TABLE @DATA(lt_zexx_nf) WHERE valid_to < @lv_timestamp. IF sy-subrc = 0. SELECT notif_id, type_id FROM /iwngw/notif INTO TABLE @DATA(lt_/iwngw/notif) FOR ALL ENTRIES IN @lt_zexx_nf WHERE notif_id = @lt_zexx_nf-notif_id. IF sy-subrc = 0. LOOP AT lt_/iwngw/notif ASSIGNING FIELD-SYMBOL(<fs_/iwngw/notif>). DELETE FROM /iwngw/notif WHERE notif_id = <fs_/iwngw/notif>-notif_id. DELETE FROM /iwngw/nrecip WHERE notif_id = <fs_/iwngw/notif>-notif_id. DELETE FROM /iwngw/ntype WHERE type_id = <fs_/iwngw/notif>-type_id. DELETE FROM /iwngw/ntype_tt WHERE type_id = <fs_/iwngw/notif>-type_id. ENDLOOP. COMMIT WORK AND WAIT. ENDIF. DELETE zexx_nf FROM TABLE lt_zexx_nf. IF sy-subrc = 0. COMMIT WORK AND WAIT. ENDIF. ENDIF. ENDFORM. *&---------------------------------------------------------------------* *& Form F_SEND_NOTIFICATION *&---------------------------------------------------------------------* FORM f_send_notification USING p_id TYPE zexx_nf-notif_id. * " Service class /IWNGW/CL_IN_CO_NF_DATA " Notification class to handle data /IWNGW/CL_COS_NOTIF_DBA " Important class /IWNGW/CL_med_ntype_dba DATA: lt_zexx_nf_job TYPE STANDARD TABLE OF zexx_nf, lt_zexx_nf_receips TYPE STANDARD TABLE OF zexx_nf_nrecip. GET TIME STAMP FIELD DATA(lv_timestamp). CONVERT TIME STAMP lv_timestamp TIME ZONE sy-zonlo INTO DATE DATA(lv_date) TIME DATA(lv_time). lv_timestamp = lv_date && lv_time. IF p_id IS INITIAL. SELECT * FROM zexx_nf INTO TABLE @DATA(lt_zexx_nf) WHERE valid_from <= @lv_timestamp AND valid_to >= @lv_timestamp. ELSE. SELECT * FROM zexx_nf INTO TABLE @lt_zexx_nf WHERE notif_id = @p_id. ENDIF. IF lt_zexx_nf IS NOT INITIAL. LOOP AT lt_zexx_nf ASSIGNING FIELD-SYMBOL(<fs_zexx_nf>). IF p_id IS NOT INITIAL AND <fs_zexx_nf>-valid_from > lv_timestamp. "it will be scheduled. APPEND <fs_zexx_nf> TO lt_zexx_nf_job. CONTINUE. ENDIF. PERFORM f_assign_values_nf_standard USING <fs_zexx_nf> CHANGING lt_zexx_nf_receips. ENDLOOP. IF lt_zexx_nf_receips IS NOT INITIAL. MODIFY zexx_nf_nrecip FROM TABLE lt_zexx_nf_receips. COMMIT WORK. ENDIF. IF lt_zexx_nf_job IS NOT INITIAL. PERFORM f_schedule_job USING lt_zexx_nf_job. ENDIF. "Notifications sent. MESSAGE TEXT-002 TYPE 'S'. ELSE. "No notifications to send. MESSAGE TEXT-001 TYPE 'S' DISPLAY LIKE 'E'. ENDIF. ENDFORM. *&---------------------------------------------------------------------* *& Form F_SCHEDULE_JOB *&---------------------------------------------------------------------* FORM f_schedule_job USING lt_zexx_nf_job TYPE ty_zexx_nf. DATA: lv_valid TYPE c, ls_params TYPE pri_params, lv_jobcount TYPE tbtcjob-jobcount, lv_released TYPE btch0000-char1, lv_jobname TYPE tbtcjob-jobname, lt_selection TYPE STANDARD TABLE OF rsparams, ls_selection TYPE rsparams, lv_plantime TYPE tbtcjob-sdlstrttm, lv_plandate TYPE tbtcjob-sdlstrtdt. CALL FUNCTION 'GET_PRINT_PARAMETERS' EXPORTING no_dialog = abap_true IMPORTING out_parameters = ls_params valid = lv_valid EXCEPTIONS archive_info_not_found = 1 invalid_print_params = 2 invalid_archive_params = 3 OTHERS = 4. IF sy-subrc = 0. lv_jobname = sy-repid. CALL FUNCTION 'JOB_OPEN' EXPORTING jobname = lv_jobname IMPORTING jobcount = lv_jobcount EXCEPTIONS cant_create_job = 1 invalid_job_data = 2 jobname_missing = 3 OTHERS = 4. IF sy-subrc = 0. "We will have alway only one LOOP AT lt_zexx_nf_job INTO DATA(ls_zexx_nf_job). ls_selection-selname = 'S_ID'. ls_selection-kind = 'S'. "Select Options = S ls_selection-sign = 'I'. ls_selection-option = 'EQ'. ls_selection-low = ls_zexx_nf_job-notif_id. INSERT ls_selection INTO TABLE lt_selection. CLEAR ls_selection. ENDLOOP. SUBMIT zexx_notification_send WITH SELECTION-TABLE lt_selection VIA JOB lv_jobname NUMBER lv_jobcount TO SAP-SPOOL WITHOUT SPOOL DYNPRO SPOOL PARAMETERS ls_params AND RETURN. "Job will be scheduled according to the System Time Zone CONVERT TIME STAMP ls_zexx_nf_job-valid_from TIME ZONE 'UTC-1' INTO DATE lv_plandate TIME lv_plantime. CALL FUNCTION 'JOB_CLOSE' EXPORTING jobcount = lv_jobcount jobname = lv_jobname sdlstrtdt = lv_plandate sdlstrttm = lv_plantime strtimmed = abap_true IMPORTING job_was_released = lv_released EXCEPTIONS cant_start_immediate = 1 invalid_startdate = 2 jobname_missing = 3 job_close_failed = 4 job_nosteps = 5 job_notex = 6 lock_failed = 7 invalid_target = 8 OTHERS = 9. IF sy-subrc NE 0. MESSAGE TEXT-003 TYPE 'E'. "error ENDIF. ENDIF. ENDIF. ENDFORM. *&---------------------------------------------------------------------* *& Form F_SEND_NOTIFICATION_BATCH *&---------------------------------------------------------------------* FORM f_send_notification_batch. DATA: lt_zexx_nf_receips TYPE STANDARD TABLE OF zexx_nf_nrecip. IF s_id IS NOT INITIAL. SELECT * FROM zexx_nf INTO TABLE @DATA(lt_zexx_nf) WHERE notif_id IN @s_id. IF lt_zexx_nf IS NOT INITIAL. LOOP AT lt_zexx_nf ASSIGNING FIELD-SYMBOL(<fs_zexx_nf>). PERFORM f_assign_values_nf_standard USING <fs_zexx_nf> CHANGING lt_zexx_nf_receips. IF lt_zexx_nf_receips IS NOT INITIAL. MODIFY zexx_nf_nrecip FROM TABLE lt_zexx_nf_receips. COMMIT WORK. ENDIF. ENDLOOP. "Notifications sent. MESSAGE TEXT-002 TYPE 'S'. LOOP AT lt_zexx_nf ASSIGNING <fs_zexx_nf>. WRITE: / <fs_zexx_nf>-notif_id, space, <fs_zexx_nf>-valid_from, space , <fs_zexx_nf>-valid_to, space, <fs_zexx_nf>-notification. ENDLOOP. ELSE. "No notifications to send. MESSAGE TEXT-001 TYPE 'S' DISPLAY LIKE 'E'. ENDIF. ELSE. "No new Notifications MESSAGE TEXT-007 TYPE 'S'. ENDIF. ENDFORM. *&---------------------------------------------------------------------* *& Form F_ASSIGN_VALUES_NF_STANDARD *&---------------------------------------------------------------------* FORM f_assign_values_nf_standard USING ls_zexx_nf TYPE zexx_nf CHANGING lt_zexx_nf_nrecip TYPE ty_zexx_nf_nrecip. DATA: lt_nf TYPE /iwngw/if_notif_provider=>ty_t_notification, lt_parameter TYPE /iwngw/if_notif_provider=>ty_t_notification_param_bundle, lt_parameter_values TYPE /iwngw/if_notif_provider=>ty_t_notification_parameter, ls_nf TYPE LINE OF /iwngw/if_notif_provider=>ty_t_notification, ls_parameter TYPE LINE OF /iwngw/if_notif_provider=>ty_t_notification_param_bundle, ls_parameter_values TYPE LINE OF /iwngw/if_notif_provider=>ty_t_notification_parameter, lv_system_uuid TYPE REF TO if_system_uuid. DATA: ls_zexx_nf_receips TYPE zexx_nf_nrecip. zcl_generic_fiori_notification=>gv_generic_nf = ls_zexx_nf-notification. lv_system_uuid = cl_uuid_factory=>create_system_uuid( ). TRY. ls_nf-id = ls_zexx_nf-notif_id. "lv_system_uuid->create_uuid_x16( ). CATCH cx_uuid_error. ENDTRY. ls_nf-type_key = 'ZGENERIC_NOTIFICATION'. ls_nf-type_version = '9'. ls_nf-recipients = gt_users[]. ls_nf-priority = p_pri. ls_parameter_values-name = 'message'. "Check Class and Method: ZCL_GENERIC_FIORI_NOTIFICATION~/IWNGW/IF_NOTIF_PROVIDER~GET_NOTIFICATION_TYPE_TEXT ls_parameter_values-type = 'Edm.String'. ls_parameter_values-value = ls_zexx_nf-notification. ls_parameter_values-is_sensitive = abap_false. APPEND ls_parameter_values TO lt_parameter_values. CLEAR: ls_parameter_values. ls_parameter_values-name = 'user'. "Check Class and Method: ZCL_GENERIC_FIORI_NOTIFICATION~/IWNGW/IF_NOTIF_PROVIDER~GET_NOTIFICATION_TYPE_TEXT ls_parameter_values-type = 'Edm.String'. ls_parameter_values-value = sy-uname. ls_parameter_values-is_sensitive = abap_false. APPEND ls_parameter_values TO lt_parameter_values. CLEAR: ls_parameter_values. ls_parameter-language = sy-langu. ls_parameter-parameters = lt_parameter_values. APPEND ls_parameter TO lt_parameter. ls_nf-parameters = lt_parameter[]. APPEND ls_nf TO lt_nf. TRY. /iwngw/cl_notification_api=>create_notifications( EXPORTING iv_provider_id = 'ZGENERIC_NOTIFICATION' it_notification = lt_nf ). LOOP AT gt_users INTO DATA(ls_user). ls_zexx_nf_receips-notif_id = ls_nf-id. ls_zexx_nf_receips-user_id = ls_user-id. APPEND ls_zexx_nf_receips TO lt_zexx_nf_nrecip. CLEAR ls_zexx_nf_receips. ENDLOOP. CATCH /iwngw/cx_notification_api INTO DATA(lrx_api). MESSAGE TEXT-008 TYPE 'S' DISPLAY LIKE 'E'. LEAVE LIST-PROCESSING. ENDTRY. ENDFORM. *&---------------------------------------------------------------------* *& Form F_TREAT_SCREEN *&---------------------------------------------------------------------* FORM f_treat_screen . LOOP AT SCREEN. IF screen-group1 = 'JOB'. screen-invisible = 1. screen-active = 0. MODIFY SCREEN. ENDIF. ENDLOOP. ENDFORM. *&---------------------------------------------------------------------* *& Form F_GET_USERS_TO_SEND_NF *&---------------------------------------------------------------------* FORM f_get_users_to_send_nf . SELECT DISTINCT uname FROM agr_users INTO TABLE gt_users WHERE ( agr_name = 'ZNTUSERPRODU' OR agr_name = 'ZNTUSERCONSU' OR agr_name = 'ZNTNPDEV' OR agr_name = 'ZNTHUBADM' OR agr_name = 'ZNTBEPADM' ) AND from_dat <= sy-datum AND to_dat >= sy-datum AND uname IN s_user. IF sy-subrc <> 0. "There are no users to receive notifications. Check the roles. MESSAGE TEXT-004 TYPE 'S' DISPLAY LIKE 'E'. LEAVE LIST-PROCESSING. ENDIF. ENDFORM.

    b. Text elements:

    An image shows the text symbol tab of ZEXX Notification Send;

  4. Provider Configuration at SPRO transaction

    An Image shows the registered backend notification provider;

    An image shows the view for maintenance of activated notification providers. The Provider with the ID ZGENERIC NF ANSWER and the provider with the ID ZGENERIC NOTIFICATION are highlighted.;

  5. Class ZCL_GENERIC_FIORI_NOTIFICATION

    a. Assign the interface /IWNGW/IF_NOTIF_PROVIDER to the class

    b. Method /IWNGW/IF_NOTIF_PROVIDER~HANDLE_ACTION: This method will perform the logic after the user decides if he will accept the question of the notification or not.

    METHOD /iwngw/if_notif_provider~handle_action. DATA: ls_zexx_nf_nrecip TYPE zexx_nf_nrecip. "Update the DB according with the button the user has clicked CASE iv_action_key. WHEN 'Accept'. SELECT SINGLE * FROM zexx_nf_nrecip INTO ls_zexx_nf_nrecip WHERE notif_id = iv_notification_id AND user_id = sy-uname. IF sy-subrc = 0. ls_zexx_nf_nrecip-accepted = abap_true. UPDATE zexx_nf_nrecip FROM ls_zexx_nf_nrecip. ENDIF. send_nf_answer( EXPORTING iv_nf_id = iv_notification_id iv_action_key = iv_action_key ). WHEN 'Reject'. SELECT SINGLE * FROM zexx_nf_nrecip INTO ls_zexx_nf_nrecip WHERE notif_id = iv_notification_id AND user_id = sy-uname. IF sy-subrc = 0. ls_zexx_nf_nrecip-rejected = abap_true. UPDATE zexx_nf_nrecip FROM ls_zexx_nf_nrecip. ENDIF. send_nf_answer( EXPORTING iv_nf_id = iv_notification_id iv_action_key = iv_action_key ). WHEN 'Maybe'. SELECT SINGLE * FROM zexx_nf_nrecip INTO ls_zexx_nf_nrecip WHERE notif_id = iv_notification_id AND user_id = sy-uname. IF sy-subrc = 0. ls_zexx_nf_nrecip-maybe = abap_true. UPDATE zexx_nf_nrecip FROM ls_zexx_nf_nrecip. ENDIF. send_nf_answer( EXPORTING iv_nf_id = iv_notification_id iv_action_key = iv_action_key ). WHEN OTHERS. ENDCASE. es_result-success = abap_true. ENDMETHOD.

    c. Method /IWNGW/IF_NOTIF_PROVIDER~HANDLE_BULK_ACTION: This action will be performed when the user decides do accept all, reject all and so on. To clarify take a look at this picture:

    An Image shows multiple notifications that are combined in a group notification. The group notification has buttons to perform the Accept, Maybe and Reject actions on all its subnotifications.;

    METHOD /iwngw/if_notif_provider~handle_bulk_action. "Bulk actions are actions like: Approve all, reject all. TYPES: BEGIN OF ty_ids, id TYPE zexx_nf_nrecip-notif_id, END OF ty_ids. DATA: lt_ids TYPE STANDARD TABLE OF ty_ids, ls_ids TYPE ty_ids. CHECK it_bulk_notif IS NOT INITIAL. LOOP AT it_bulk_notif ASSIGNING FIELD-SYMBOL(<fs_bulk_notif>). ls_ids-id = <fs_bulk_notif>-id. APPEND ls_ids TO lt_ids. ENDLOOP. SELECT * FROM zexx_nf_nrecip INTO TABLE @DATA(lt_zexx_nf_nrecip) FOR ALL ENTRIES IN @lt_ids WHERE notif_id = @lt_ids-id AND user_id = @sy-uname. CHECK sy-subrc = 0. LOOP AT it_bulk_notif ASSIGNING <fs_bulk_notif>. READ TABLE lt_zexx_nf_nrecip ASSIGNING FIELD-SYMBOL(<fs_zexx_nf_nrecip>) WITH KEY notif_id = <fs_bulk_notif>-id. IF sy-subrc = 0. CASE <fs_bulk_notif>-action_key. WHEN 'Accept'. <fs_zexx_nf_nrecip>-accepted = abap_true. send_nf_answer( EXPORTING iv_nf_id = <fs_bulk_notif>-id iv_action_key = <fs_bulk_notif>-action_key ). WHEN 'Reject'. <fs_zexx_nf_nrecip>-rejected = abap_true. send_nf_answer( EXPORTING iv_nf_id = <fs_bulk_notif>-id iv_action_key = <fs_bulk_notif>-action_key ). WHEN 'Maybe'. <fs_zexx_nf_nrecip>-maybe = abap_true. send_nf_answer( EXPORTING iv_nf_id = <fs_bulk_notif>-id iv_action_key = <fs_bulk_notif>-action_key ). WHEN OTHERS. ENDCASE. ENDIF. ENDLOOP. UPDATE zexx_nf_nrecip FROM TABLE lt_zexx_nf_nrecip. ENDMETHOD.

    d. Method /IWNGW/IF_NOTIF_PROVIDER~GET_NOTIFICATION_TYPE_TEXT:

    METHOD /iwngw/if_notif_provider~get_notification_type_text. DATA: lv_text TYPE string, lv_subtitle TYPE string. DATA: ls_action_text TYPE LINE OF /iwngw/if_notif_provider=>ty_t_notification_action_text. lv_text = TEXT-001. "New message: &1 REPLACE '&1' WITH '{message}' INTO lv_text. lv_subtitle = TEXT-003. "from: &1 REPLACE '&1' WITH '{user}' INTO lv_subtitle. es_type_text-subtitle = lv_subtitle. es_type_text-template_public = lv_text. es_type_text-template_grouped = TEXT-002. "You have new notifications. es_type_text-template_sensitive = lv_text. ls_action_text-action_key = 'Accept'. ls_action_text-display_text = TEXT-004. "Accept ls_action_text-display_text_grouped = TEXT-007. "Accept all APPEND ls_action_text TO et_action_text. ls_action_text-action_key = 'Maybe'. ls_action_text-display_text = TEXT-005. "Maybe ls_action_text-display_text_grouped = TEXT-008. "Maybe to all APPEND ls_action_text TO et_action_text. ls_action_text-action_key = 'Reject'. ls_action_text-display_text = TEXT-006. "Reject ls_action_text-display_text_grouped = TEXT-009. "Reject all APPEND ls_action_text TO et_action_text. ENDMETHOD.

    e. Method /IWNGW/IF_NOTIF_PROVIDER~GET_NOTIFICATION_TYPE:

    METHOD /iwngw/if_notif_provider~get_notification_type. DATA: ls_action TYPE LINE OF /iwngw/if_notif_provider=>ty_t_notification_action. es_notification_type-is_groupable = abap_true. es_notification_type-type_key = iv_type_key. es_notification_type-version = iv_type_version. ls_action-action_key = 'Accept'. ls_action-nature = /iwngw/if_notif_provider=>gcs_action_natures-positive. APPEND ls_action TO et_notification_action. ls_action-action_key = 'Maybe'. ls_action-nature = /iwngw/if_notif_provider=>gcs_action_natures-neutral. APPEND ls_action TO et_notification_action. ls_action-action_key = 'Reject'. ls_action-nature = /iwngw/if_notif_provider=>gcs_action_natures-negative. APPEND ls_action TO et_notification_action. ENDMETHOD.

    f. Method SEND_NF_ANSWER:

    METHOD send_nf_answer. DATA: lt_nf TYPE /iwngw/if_notif_provider=>ty_t_notification, ls_nf TYPE LINE OF /iwngw/if_notif_provider=>ty_t_notification, lt_user TYPE STANDARD TABLE OF /iwngw/if_notif_provider=>ty_s_notification_recipient, ls_user TYPE /iwngw/if_notif_provider=>ty_s_notification_recipient, lt_parameter_values TYPE /iwngw/if_notif_provider=>ty_t_notification_parameter, ls_parameter_values TYPE LINE OF /iwngw/if_notif_provider=>ty_t_notification_parameter, ls_parameter TYPE LINE OF /iwngw/if_notif_provider=>ty_t_notification_param_bundle, lt_parameter TYPE /iwngw/if_notif_provider=>ty_t_notification_param_bundle. TRY. DATA(lv_system_uuid) = cl_uuid_factory=>create_system_uuid( ). ls_nf-id = lv_system_uuid->create_uuid_x16( ). CATCH cx_uuid_error. EXIT. ENDTRY. SELECT SINGLE * FROM zexx_nf INTO @DATA(ls_zexx_nf) WHERE notif_id = @iv_nf_id. CHECK sy-subrc = 0. ls_user-id = ls_zexx_nf-created_by. APPEND ls_user TO lt_user. CLEAR ls_user. ls_nf-type_key = 'ZGENERIC_NOTIFICATION'. ls_nf-type_version = '9'. ls_nf-recipients = lt_user[]. "Answer of the user: "X" to notification "Y": "Z". ls_parameter_values-name = 'notification'. ls_parameter_values-type = 'Edm.String'. ls_parameter_values-value = ls_zexx_nf-notification. ls_parameter_values-is_sensitive = abap_false. APPEND ls_parameter_values TO lt_parameter_values. CLEAR: ls_parameter_values. ls_parameter_values-name = 'user'. ls_parameter_values-type = 'Edm.String'. ls_parameter_values-value = sy-uname. ls_parameter_values-is_sensitive = abap_false. APPEND ls_parameter_values TO lt_parameter_values. CLEAR: ls_parameter_values. ls_parameter_values-name = 'decision'. ls_parameter_values-type = 'Edm.String'. ls_parameter_values-value = iv_action_key. ls_parameter_values-is_sensitive = abap_false. APPEND ls_parameter_values TO lt_parameter_values. CLEAR: ls_parameter_values. ls_parameter-language = sy-langu. ls_parameter-parameters = lt_parameter_values. APPEND ls_parameter TO lt_parameter. ls_nf-parameters = lt_parameter[]. APPEND ls_nf TO lt_nf. TRY. /iwngw/cl_notification_api=>create_notifications( EXPORTING iv_provider_id = 'ZGENERIC_NF_ANSWER' " class ZCL_GENERIC_NF_ANSWER it_notification = lt_nf ). COMMIT WORK AND WAIT. CATCH /iwngw/cx_notification_api INTO DATA(lrx_api). EXIT. ENDTRY. ENDMETHOD.

    g. Text elements

    An image shows the text symbols tab of ZCL Generic Fiori Notification;

  6. Class ZCL_GENERIC_NF_ANSWER:

    a. Implement the interface /IWNGW/IF_NOTIF_PROVIDER

    b. Method /IWNGW/IF_NOTIF_PROVIDER~GET_NOTIFICATION_TYPE_TEXT

    METHOD /iwngw/if_notif_provider~get_notification_type_text. DATA: lv_text TYPE string, lv_subtitle TYPE string. lv_text = TEXT-001. "Answer of notification: &1 lv_subtitle = TEXT-003. "&2, from user: &3. REPLACE '&1' WITH '{notification}' INTO lv_text. REPLACE '&2' WITH '{decision}' INTO lv_subtitle. REPLACE '&3' WITH '{user}' INTO lv_subtitle. es_type_text-template_public = lv_text. es_type_text-template_grouped = TEXT-002. "Answers of the generic notifications es_type_text-template_sensitive = lv_text. es_type_text-subtitle = lv_subtitle. ENDMETHOD.

    c. Method /IWNGW/IF_NOTIF_PROVIDER~GET_NOTIFICATION_TYPE

    METHOD /IWNGW/IF_NOTIF_PROVIDER~GET_NOTIFICATION_TYPE. es_notification_type-is_groupable = abap_true. es_notification_type-type_key = iv_type_key. es_notification_type-version = iv_type_version. ENDMETHOD.

    d. Text elements:

    An image shows the text symbols tab of ZCL GENERIC NF ANSWER;

Conclusion

The SAP Fiori Notifications is a powerful tool to catch the attention of the users. In one place it is possible to configure the activities that should be performed in the system, categorized by priority, date or type. The notification can even be a simple message or a important decision to be made, for example, an approval of purschase requisitions or sales orders. It is well connected with standard workflows and can be very well customizable.

References

The content of this article was based in some SAP Notes, that were along the documentation described and the Fiori Guidelines.

Table of note references:

NoteDescription
2488945How to setup notifications in Fiori 2.0
2356153Business Workflow Extensions - Version 2
2456330How to configure Fiori Launchpad step-by-step
2424054How to setup My Inbox 2.0 app
2729492Configuring notifications in Fiori Launchpad and known restrictions

Table of link references:

Link
https://wiki.scn.sap.com/wiki/display/SAPMOB/How+to+Setup+Notifications+in+Fiori+2.0+step-by-step
https://experience.sap.com/fiori-design-web/notification-center/

Image sources

The cover image used in this post was created by SAP under the following license. All other images on this page were created by eXXcellent solutions under the terms of the Creative Commons Attribution 4.0 International License