Skip to Content
Technical Articles

Providing ESS in MSS functionality in Fiori

Introduction

I often get the question from clients asking if SAP provides ESS in MSS functionality as a standard functionality. Customers want the possibility to have a manager enter a leave request for their employees (for example blue collar workers that don’t have access to a PC). The answer to the question is often simple… No. SAP says that Fiori is simple to use and available on mobile so accessible by everybody, but it’s not always so straightforward.

I got the same question recently from my customer where Time Administrators fill in the timesheets of their employees (CATS). Luckily there is still the possibility to develop custom functionality! Part of the solution was briefly explained in my previous blog https://blogs.sap.com/2018/07/10/updateset-fiori-application-title-with-dynamic-content/

 

Solution

Previous mentioned blog only explains how to update the title of the application, in this blog we will look more into the complete setup of the “on-behalf-of” CATS solution in Fiori.

 

oData to get the employee list

I designed an oData project that will retrieve employees based on a certain scenario. The idea here is to get different lists based on the application. A custom report might show the direct subordinates of a manager while the custom Timesheet application has to show the employees for which the current user is the Time Administrator.

A custom table was setup to define the class and method that is called per scenario (the employee list oData is used by multiple applications).

 

UI5 application to show the employee list

The next step is showing the employees to the users which will be done in a UI5 application built from scratch. This application will use the employee oData and show the results in a smart table (Smart Table Example).

When the user clicks on a row we trigger the navigation to the extended My Timesheet application by passing the personnel number that was selected. To achieve this the following code was added to the manifest.json file:

"crossNavigation": {
	"inbounds": {
		"toCats": {
			"signature": {
				"parameters": {
					"PersonnelNumber": {},
					"Keydate": {},
					"Scenario": {}
				},
				"additionalParameters": "allowed"
			},
			"semanticObject": "Timesheet",
			"action": "change"
		}
	}
}

With the crossNavigation property “toCats” we can trigger the Timesheet~change semanticObject which will execute the navigation to the actual Timesheet application. 3 parameters are available where PersonnelNumber is of course the most important one.

When the user clicks on an employee the following function will provoke the “toCats” navigation:

handleToCats: function(oEvent) {
    //Get personal number of selected employee
    var sPernr = oEvent.getSource().getBindingContext().getProperty("Pernr");
    if (sPernr) {
        // Get keydate
        var dKeydate = this.getView().getModel("local").oData.startDate;
        // get a handle on the global XAppNav service
        if (sap.ushell) {
            var oCrossAppNavigator = sap.ushell.Container.getService("CrossApplicationNavigation");
            oCrossAppNavigator.isIntentSupported(["Timesheet-change"])
                .done(function(aResponses) {})
                .fail(function() {
                    MessageToast.show(this.getModel("i18n").getResourceBundle().getText("intentIssue"));
                });
            // generate the Hash to display the to CATS 
            var sHash = (oCrossAppNavigator && oCrossAppNavigator.hrefForExternal({
                target: {
                    semanticObject: "Timesheet",
                    action: "change"
                },
                params: {
                    "PersonnelNumber": sPernr,
                    "Keydate": dKeydate,
                    "Scenario": S_SCENARIO
                }
            })) || "";
            //Generate a  URL for the Cats application
            var sUrl = window.location.href.split('#')[0] + sHash;
            //Navigate to Cats app
            sap.m.URLHelper.redirect(sUrl, false);
        } else {
            MessageToast.show(this.getModel("i18n").getResourceBundle().getText("intentIssue"));
        }
    }
},

The semanticObject navigation has to be maintained in order to trigger the link to the extended Timesheet application:

extended UI5 application of standard My Timesheet (version 2)

The enhanced Timesheet application was heavily adapted but in this blog I’ll focus on the interaction between the 2 applications. The following picture shows the result of clicking on a certain employee:

You can see that the standard title is changed to “Timesheet – Name of selected employee” and that a panel was added with details of the selected employee.

The personnel number is read via the following code in the onAfterRendering function:

onAfterRendering: function() {
    if (!this.oApplication.pernr) {
        var sComponentId = sap.ui.core.Component.getOwnerIdFor(this.getView());
        var oStartUpParameters = sap.ui.component(sComponentId).getComponentData().startupParameters; //Get pernr from the cross app nav
        // Read parameters from custom app
        var oParameters = this.getOwnerComponent().getComponentData().startupParameters;
        if (oParameters.PersonnelNumber) {
            this.oApplication.pernr = oParameters.PersonnelNumber[0];
        } else {
            if (oStartUpParameters.pernr) {
                this.oApplication.pernr = oStartUpParameters.pernr[0];
            }
        }
        this.initializeView();
        this.updateData();
    }
}

extended oData to remove standard checks

For different requirements I already had to enhance the standard oData service of My Timesheet, but I had to create redefinitions of almost all the standard methods to enable ESS in MSS. The reason for this is that in standard, SAP always checks if the personnel number is connected to the current logged-on user. As it is clear this is not the case in our scenario, I had to remove the following piece of code in my custom class multiple times:

  IF lv_pernr IS INITIAL.
**********************************************************************
* Fallback case
**********************************************************************
      CALL METHOD lo_hcm_assignments_api->GET_ASSIGNMENTS
        EXPORTING
          IV_APPLICATION = gc_app_name
        IMPORTING
          ET_ASSIGNMENTS = lt_assignments
          ET_MESSAGES    = lt_messages.

      IF lt_assignments IS NOT INITIAL.
        READ TABLE lt_assignments INTO ls_assignments INDEX 1.
          lv_pernr = ls_assignments-pernr.
      ENDIF.

  ELSE.

**********************************************************************
* Check if Pernr is valid or not
**********************************************************************
*    Checks if entry is present for the entered pernr

  CALL METHOD lo_hcm_assignments_api->VALIDATE_PERNR
    EXPORTING
      IV_PERNR       = LV_PERNR
      IV_APPLICATION = gc_app_name
    IMPORTING
      ET_MESSAGES    = lt_messages.


  ENDIF.

Should you want to implement the same functionality as I did, be sure that you add security since a clever person can change the parameter of the personnel number in the URL. One option is to catch this and route to an error page as shown below and explained here: Step 3: Catch Invalid Hashes and Message Page Example

Conclusion

A lot of development time was invested into the dynamic employee selection oData service, but we re-use this service in multiple application providing Managers and Administrators with all kind of applications like Timesheet on-behalf-of but also custom reports and more.

3 Comments
You must be Logged on to comment or reply to a post.
  • Hi Andy,

    Thanks for the blog. I know its not easy to achieve this MSS functionality. We can have implicit enhancement in VALIDATE_PERNR method and skip the Employee logged in check as well right?

    Any reason for not going for implicit enhancement.

    Thanks,

    Kishore.

    • Hey.

       

      The implicit enhancement is powerful but it’s still a “sneaky” way of doing a repair without the modification key request. In a way this is more annoying during an upgrade because the repairs are shown in the SPAU and the enhancements are not.

      Changing the odata is annoying too but it’s the cleanest imo.