SAP Builders Blog Posts
Learn from peers about their low-code journey and write your own blog posts to share your thoughts and experiences as you become an SAP Builder.
cancel
Showing results for 
Search instead for 
Did you mean: 
mlauber
Product and Topic Expert
Product and Topic Expert

Welcome to a full end-to-end scenario on SAP Business Technology Platform integrating an S/4HANA system with SAP Build Apps , SAP Build Process Automation and AWS.

We use SBA for a simple expense entry app, including the capability to take/select a photo for the receipt, which will be uploaded to an AWS S3 bucket (file storage). This then triggers an Expense Request Approval process in SBPA, where the appropriate approver gets all needed information with the possibility to check the receipt to make a decision. Let's check it out!

 

Prerequisite

For this end-to-end scenario to fully work, an AWS account is needed with an S3 bucket and an API Gateway REST API, for uploading (PUT) and retrieving (GET) files from the S3 bucket. In short:

  1. AWS account
  2. Create an S3 bucket
  3. Create an API Gateway API for the S3 bucket and deploy it

I won't go into the AWS details here and there are a lot of guides out there. One example you can find at openSAP: Build Resilient Applications on SAP BTP with AWS (week 2).

 

SAP Build Apps

Setup

  • On-device storage for keeping track of the Expense Request workflows sent by the user, called SBPA Processes
  • Integration to an SAP S/4HANA system via SAP BTP Destination and authorization. I included company code (A_CompanyCode) and cost center read (A_CostCenterText) (public APIs offered by my S/4HANA system, refer to SAP Accelerator Hub).
  • SAP Build Apps classic data entities for creating the trigger for the SBPA process (called Process Trigger with sub-object expenserequest (which has the same name and fields as the API trigger of the SBPA process we will look at below)) and for reading the current process status (called Process Info) (this is setup via a destination in SAP BTP to the SBPA instance; refer to Create SBPA Instance Destination)

UI

  1. Start screen, displaying a button to create a new expense request and a list of all on-device storage SBPA Processes:
    mlauber_0-1707821022031.png
  2. Expense request screen to enter all information:
    mlauber_1-1707821144498.png

Logic

Start screen

Here we have 2 main logic flows:

  • Data variable to read the on-device storage SBPA Processes collection (on Page mounted) which is then linked to the repeating Container component, displaying the ID of the process, the status and a refresh icon. The refresh icon has a Component tap logic to get the current status from Process Info:
    • Get Record Process Info
    • Check if status changed: only if yes, continue
    • Update record SBPA Processes on-device with new status 

  • The button for New Expense Request simply navigates to the Expense request screen

Expense Request screen

There is quite a bit happening here, in more or less this order:

  • Data variables for our integrations:
    • Process Trigger as new data record, to be filled through the input fields on the UI (all UI input fields are linked to this variable)
    • A_CompanyCode as a collection of records, reading the collection when page it mounted. Once this read is done, we check if only 1 company code was returned (user is only assigned to 1 in S/4HANA), and then we prefill the company code as well as the currency of the company code on Process Trigger-expenserequest
    • A_CostCenterText as a collection of records, reading the collection when page it mounted

  • Page variables for various needs:
    • receiptPhoto of type any for either taking a photo with a phone camera, or selecting a photo from a phone library or PC explorer.
    • uploadUrl of type text for AWS S3 API: this is the URL for the PUT request on AWS, for uploading a file to AWS S3 bucket
    • s3APIKey of type text: API key needed to use the API on AWS

  • Build the UI as shown in the screenshot above (you are just missing the Submit button in the screenshot as it didn't fit). Here are a few tips for good UX:
    • Company Code and Cost Center are Combo box components (download from Marketplace) to allow user to type and filter result and linked to the appropriate S/4HANA integration A_CompanyCode and A_CostCenterText respectively
    • Requestor name and email are prefilled with system variables systemVars.currentUser.firstname, systemVars.currentUser.lastname and  systemVars.currentUser.email respectively (but possible to change for user)
    • With receipt is a simple toggle button that starts as true. If the user switches to false, the button to upload/take/chose a photo is no longer displayed to save space:
      mlauber_2-1707823049762.png
    • The Submit button is greyed out (disabled) until all mandatory fields are filled in Process Trigger-expenserequest so we cannot send a faulty request/API trigger to SBPA (this isn't achieved automatically and needs to be manually handled!)
    • Here is the logic flow for the upload/take/chose a photo button:mlauber_3-1707823536537.png
      • (Upper part) Depending on the device (phone or not) the app either opens the windows explorer pop-up to select a file, or lets the user choose through an Action Sheet whether the camera should be opened to take a photo, or to select an existing photo from the library.
      • (Lower part) If the windows explorer was opened, we add an extra mime type check to make sure that only images were selected (for this specific case. S3 on AWS can save any kind of file so for example we could allow PDF documents etc.). Regardless how the photo/image was chosen, it is finally put into page variable receiptPhoto
    • So far, we have not sent any process trigger to to SBPA and we have not yet uploaded any file to AWS S3 bucket. Only once the Submit button is pressed, are we doing all that. Here is the flow logic for Submit:
      mlauber_4-1707823867139.png
      • We start by checking whether or not we even have a receipt file. If yes, now we upload to AWS with the flow function Upload files, which can be downloaded from the Marketplace. Important in this flow function is to set the full upload URL (from page variable uploadUrl + the name of the file which we have stored in receiptPhoto) and to set two request headers:
        • Content-Type: page variable receiptPhoto.mimeType
        • x-api-key: page variable s3APIKey

      • If we have a receipt, we only continue if the upload was successful and shout out a toast with the success message. Otherwise we stay on the page and display the upload error.
      • Once either the photo was uploaded correctly or we had no file to handle at all, then we create the trigger for SBPA via Create record of Process Trigger. Important here is to map the record correctly and according to the API trigger in SBPA. For example, instead of sending currency and amount as two separate fields, in my case I sent one field called "amountString" and mapped it accordingly: 
        amountString: data["Process Trigger1"].expenserequest.amount +" "+ data["Process Trigger1"].expenserequest.currency
      • The same was done for the URL to the uploaded image of the receipt (if any), so that we can display the image in SBPA approval form:
        receipt: pageVars.uploadURL + pageVars.receiptPhoto.name
      • Only if triggering the SBPA process worked, do we continue, otherwise we show the error message in a toast.
      • Next, we create a new record for the on-device storage SBPA Processes, using the response of the previous Create record. This way we have the ID of the just created, currently running workflow, and thus we can then get Process Info whenever we press refresh on the first screen for that process

And that's all on the SAP Build Apps site. Let's continue.

 

SAP Build Process Automation

Actions

We start with creating the needed actions to integrate with our S/4HANA system. In this scenario I created one action for G/L Account read (refer to SAP Accelerator Hub A_GLAccountText). I used the text entity to get the name but I could have used the regular entity and expanded the text association. Both ways work. But because I used the text one, I added a static filter to always only return English texts (this could be solved in various ways). Important to remember in Action projects that are meant to be used in a drop-down list is to tag the result array as Main Output Array.

Process

Next we create a process project. I started by creating the data type for the expense request, setting certain fields as required (those which I also made required on SAP Build Apps, otherwise the Submit button remained disabled). In my example it looks like this:

mlauber_0-1707991069051.png

Inside my process, I created an API trigger and used the data type just created as Process Input, with the same name as described for SBA, expenserequest:

mlauber_1-1707991141813.png

(Quick note: you could just add each field manually into the process inputs and not have a data type at all. But then the trigger creation for the process would need to change as it would not have the object expenserequest).

Then I created my process:

mlauber_2-1707991334541.png

Here is what's going on step by step:

  1. Once the process is triggered, an approver is determined depending on the cost object (cost center etc.). As a side note: we could have a more complex scenario here if needed, for example an action to read the responsible user of a cost center or project and determine the approver that way; there are a lot of possibilities!
  2. The approver receives an approval form notification with all the information of the expense request, including the link to the receipt if there is one (which will open in a new browser tab and display the image once pressed). Here is what it could look like in the inbox of an approver:
    mlauber_3-1707991978721.png
    1. We list all the most important data in a simple, easy to read way (thus the string of amount with the number and currency in one, instead of having it as two fields on two separate rows).
    2. If we have a receipt, the link to it is displayed, which is the URL to the GET request of the AWS API. Important here is that for this GET request we do not require an API key (otherwise just a link to an URL would not work); this needs to be setup correctly on AWS side.
    3. Lastly, I decided to add Debit and Credit G/L account for journal posting right onto the form, using the Action integration I created before. But because the approver could reject, the fields should not be mandatory
  3. If the approver rejects, a simple mail is sent to the process initiator and informing of the rejection
  4. If the approver approves, we have a simple control IF statement to make sure that both the Credit and Debit G/L accounts were entered. If at least one of them is missing, we send a new notification from to the same approver, asking to enter them. And now on this form the fields are set as required, meaning the user can only submit, once both accounts are provided.
  5. In the very last step, the process initiator is informed of the approval via a form notification.

 

Summary

And that's all for now. We have a simple to use app that collects information from S/4HANA upon opening (company codes, cost center) and integrates with phones seamlessly for easy handling of receipts. We store files on AWS and can then display them within our process.

As a final step we could add the actual journal entry post after the approval. But because there is no public OData API for creating journal entries, I've left this out for now. We could achieve this by creating a clean core extension with ABAP Cloud development, where we create our own service for simple expense GL postings. If you are interested in such an example let me know and I'll consider making a blog post for that too.

I hope this helps and gives some ideas for innovation with your solutions. Get building 😉

1 Comment
Manuel_Namyslo
Product and Topic Expert
Product and Topic Expert

Nice Blogpost! Thanks for sharing 🙂