Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
LudoNoens
Product and Topic Expert
Product and Topic Expert
3,727

This blog post is the fifth in a series of posts that cover the connectivity options available for SAP Build Apps to interface with SAP systems. The series will cover connecting SAP Build Apps with the following:

  1. CAP-based services
  2. S/4HANA systems
  3. ABAP systems

The format of this post is similar to a tutorial. However, I'll provide more comprehensive details, tips and the opportunity for you to provide feedback. Based on the feedback we will be able to adjust and enhance this post and future parts of the series, and might even be able to improve the products involved as well. 

Introduction 

Before we get into the details of setting up connections between SAP Build Apps and SAP Systems, I intend to introduce a couple of SAP technology components in each post that are relevant for the use cases covered in the series. 

SAP Business Accelerator Hub

SAP Business Accelerator Hub is a web application hosted by SAP to help discover, explore, and test SAP and partner APIs (application programming interfaces) that are required to build extensions or process integrations. It also hosts Integration content, Events, CDS views, and more.

In the context of this blog post, SAP Business Accelerator Hub offers us an easy way to find and explore APIs available on S/4HANA Cloud, which can be used in our application.

SAP S/4HANA Cloud

SAP S/4HANA Cloud is a ready-to-run cloud-based enterprise resource planning (ERP) system that provides business application solutions and industry best practices. It's a software as a service (SaaS) solution that's flexible, scalable, and easy to use, making it suitable for businesses of all sizes and industries. It offers an efficient, agile, and affordable solution for connecting your workforce, suppliers, customers, markets, and assets without adding complexity. With preconfigured end-to-end processes and innovative data management solutions, you can build your own breakthroughs, reshape business models, and redefine work on the fly.

Although this ERP system is using a SAP HANA Cloud database for storing information, it should be clear that it is offering more than just a database.

Use case E : Consume data from an SAP S/4HANA Cloud system in our SAP Build Apps application

For this use case, we will extend the application previously created in SAP Build Apps with additional screens where we show information retrieved from an S/4 HANA Cloud system

Solution diagram

Like in the previous blog post, we will start with a quick look into what needs to change in our solution overview to retrieve information from a cloud-based ERP system. I have added Business Accelerator Hub to the diagram as it helps to discover, explore and try out the APIs available in SAP systems. After identifying the required APIs, we create BTP destinations that can be used in our design time environments, as well as in our apps. These destinations form a bridge to the SAP S/4HANA Cloud ERP system we have added. 

LudoNoens_2-1715587831408.png


The end result (web app)

Before we get into the details, let's take a look at what functionality we will be adding the our application.

2024-06-04_20-59-25 (2).gif


Using SAP Business Accelerator Hub to identify the APIs we need

Let's explore which APIs we can use in our application by using SAP Business Accelerator Hub. Open api.sap.com and log in.

Choose the product SAP S/4HANA Cloud Public Edition. Select the APIs tab and select ODATA V2. Search for "business partner".

LudoNoens_3-1715588941845.png

Select the Business Partner (A2X) tile to view various details of the API. You can view the API reference and even try out the API. In API Resources, you'll find a few items relevant for our use case:

  1. Configuration Details - copy the sandbox url. This url points to the OData service endpoint on a sandbox S/4HANA Cloud system that exposes the API called API_BUSINESS_PARTNER.

    LudoNoens_4-1715589650670.png
  2. Authentication Methods - Shows which authentication methods are supported by this API.

    LudoNoens_5-1715590283151.png

     

  3. In the top right corner there is a button called "Show API Key". Use this to obtain the key that provides you access to the API.

 

Besides the Business Partner entity, we are also going to use the Purchase Order entity provided by the S/4HANA Cloud system as OData V4 source.

In SAP Business Accelerator Hub, choose the product SAP S/4HANA Cloud Public Edition. Select the APIs tab and select ODATA V4 and search for "purchase order".

LudoNoens_0-1716864925034.png

Select the Purchase Order tile to view various details of the API. You can view the API reference and even try out the API. In API Resources, you'll find a few items relevant for our use case:

  1. Configuration Details - copy the sandbox url. This url points to the OData service endpoint on the sandbox S/4HANA Cloud system that exposes the API called API_BUSINESS_PARTNER.

    LudoNoens_1-1716865099224.png

  2. Authentication Methods - Shows which authentication methods are supported by this API.

 

Creating a Destination to access data from S/4HANA Cloud

In the BTP Cockpit of your subaccount, please navigate to Connectivity > Destinations and select Create Destination.

Provide a name that makes it clear what the source is and what data it exposes. For the URL, please use the sandbox URL we've found in the configuration details in SAP Business Accelerator Hub. For the authentication, we will select NoAuthentication. This doesn't mean everyone has access to the data sources exposed by this S/4HANA sandbox system. Users need an API key to get access. This API key is to be stored in the Additional Properties of the Destination Configuration. 

The additional properties to configure are:

PropertyDescriptionValue
AppgyverEnabledDestination can be used in SAP Build Appstrue
HTML5.DynamicDestination

This enables the managed application router to dynamically adjust the destination based on the incoming request’s host or path information. This is beneficial for scenarios where the destination URL may change or need to be determined at runtime. 

Link to Work Zone documentation.

true
MobileEnabledDestination can be discovered in SAP Mobile Services and is accessible for mobile applications.true
URL.headers.APIKeyThis adds the API key for accessing the S/4HANA Cloud APIs in the header of HTTP requests.API key copied from SAP Business Accelerator Hub
WebIDEEnabledDestination can be discovered in SAP Build Apps, SAP Build Code, SAP Business Application Studio, SAP Web IDEtrue

 

With the above information, we create a BTP Destination for accessing Business Partner.

LudoNoens_2-1716865377190.png

Similarly, we create a BTP Destination for accessing Purchase Order.

LudoNoens_3-1716865404921.png

Adding the data sources in SAP Build Apps

Going back to SAP Build Apps, we navigate to the DATA tab and select ADD INTEGRATION, followed by BTP DESTINATIONS. You should now be able to select the newly added destinations.

LudoNoens_0-1724048423995.png

 

Business Partner

Select the Business Partner data source. You will notice that this data source contains several data entities. For each of them, you can browse real data coming from the S/4HANA Cloud sandbox system. For our app, we are going to show a list of suppliers. Take note that at this point, there is no relationship between the products entity we have created earlier. We will cover this in an upcoming blog post.

Search for 'supplier' and select the data entity A_Supplier. Select INSTALL INTEGRATION and ENABLE DATA ENTITY to use this particular data entity in your app. All other data entities in the data service are not relevant and will be ignored in our app. Notice that data entities contain several fields, also referred to as properties. Not all these fields are used in the sandbox system.

LudoNoens_1-1716892826733.png

You can browse the data stored in the S/4HANA Cloud system by selecting the BROWSE REAL DATA button. The can help you in deciding which field to use in your UI application.

LudoNoens_2-1716893017025.png

Purchase Order

Go back to the DATA > SAP Systems and add another integration for Purchase Order, which is exposed as an OData V4 service. For this blog post, we'll pick the data entity PurchaseOrder. Again, there is currently no relationship between Products, Suppliers and Purchase Orders in the app.

LudoNoens_4-1716899212081.png

Now that we are done, we have 3 SAP System integrations in our project, all having one single data entity enabled for consumption in our app:

LudoNoens_1-1724048833286.png



Creating new pages in the app to show the newly added data sources

Open the pages overview in SAP Build Apps by clicking on the name of the current page. This will bring you to an overview of all pages defined for your application. You'll see that besides the main page, we already have a page for SAP BTP Authentication. This page was automatically added when we enabled the BTP authentication.

LudoNoens_1-1716962808812.png

Supplier list

Select ADD NEW PAGE and provide a name. As we intend to show a list of suppliers, we create a page with the name "Supplier list".

We are going to make use of a table that is available in the marketplace. It is not part of the standard set of Core components. Select the MARKETPLACE and search for basic table with data adapter. Select INSTALL.

LudoNoens_2-1716963317938.png

Once installed, the UI component is visible in the INSTALLED tab, and you can drag and drop the component into the canvas.

LudoNoens_4-1716963713383.png

Select the basic table with data adapter on this page. Configure the properties. Show a spinner while this component is loading data. We also need to pick the data entity fields we want to display. Not all fields are relevant for our use case, and besides that, keep in mind that on mobile devices we don't have that much screen real estate to work with. Besides that, the sandbox S/4HANA Cloud system does not contain useful data for all fields.

LudoNoens_0-1717381522198.png

For our application, in the Field Configuration we pick SupplierName and VATRegistration. Change the display name to something shorter and more readable. 

We switch to the Properties to configure the behaviour of the table.

When we started developing our app, we've created a simple database with a limited set of rows containing sample data. We could quickly and easily query and store all data in our app. However, now that we have connected to an S/4HANA Cloud system, the chances are high that our queries result in lots of data. As you might have noticed when browsing the real data of the A_Supplier data source, the system contains 1490 rows. The amount of rows for Purchase Orders is much higher. This will take more time to load, store and process; especially on mobile devices. As we are only showing a limited set of information to the user, we don't have to load all this data at once. We could simply limit our query to a set that is visible to the user. This will greatly improve the responsiveness of the app. For this, we need to configure Pagination. However, we need to make some more preparations before we can actually do this.

Add page variables to manage the table

For the table, we want to keep track of the current page and how many pages there are in total. Take note that the initial value of CurrentPage is defined as 1.

We also need to know when to refresh the data in the table. More on this later.

LudoNoens_1-1717384913031.png


Add buttons to navigate the pages

Drag and drop a container onto the page below the table, and two buttons and a text field into the container. Change the layout of the container to Horizontal.

LudoNoens_2-1717385383510.png

We'll disable the left button to prevent the user from navigating to anything before page one. For this, we configure the Disabled property and bind it to the formula

IF(pageVars.CurrentPage>1, false, true)

For the right button, we'll disable it to prevent the user from navigating beyond the last page. For this, configure the Disabled property and bind it to the formula

IF(pageVars.CurrentPage<pageVars.TotalPageCount, false, true)

For the displaying the current and total amount of pages, we simply bind the Content property to the formula

"Page Number: "+pageVars.CurrentPage + " of "+pageVars.TotalPageCount

We'll need to add some logic to increase or decrease the current page number to both buttons. Select the button and open the logic canvas.

LudoNoens_4-1717485265146.png

For the left button, we set the page variable CurrentPage as follows:

pageVars.CurrentPage-1

Since we disable the button once CurrentPage is 1, we can keep this formula simple.

For the right button, we set the page variable CurrentPage as follows:

pageVars.CurrentPage+1

As we disable the button once we reach that maximum page count, we can keep this formula simple as well.

So now the user can only navigate to valid pages between 1 and the maximum amount available. But how do we know the total amount?


Getting the total amount of records (and pages)

How do we find out the total amount of records available in the OData service ? We can actually query this information from the OData service. Select the page we've created for Supplier List and open the logic canvas. Drag and drop DATA > Get record collection and VARIABLES > Set page variable. Connect the events as follows.

LudoNoens_3-1717386741590.png

For this application I am going to use a fixed table size of 10 rows. A better implementation would be to figure out how much space we have on the screen and then fit the table accordingly. However, I am keeping things easy for now and will just use a fixed table size. This table will not fit on a mobile device. We'll adjust this in an upcoming blog post.

Use the following formula for setting the TotalPageCount:

INTEGER(outputs["Get record collection"].totalCount / 10) + 1

As you can see, the formula uses the output of "Get record collection" to find out the total amount of records. If we don't customise this, it will actually load ALL data. This is totally unnecessary overhead for this case. Also, loading way too much data will likely crash your mobile app ! To avoid all of this, we configure the property Paging. 

LudoNoens_0-1717404718893.png

For the binding, select Object with properties, configured as below.

LudoNoens_1-1717404853471.png

As the basis for pagination we will use pageIndex. We set the page size and page number to zero, as we don't need to load any data at this point. The only thing we are interested in now, is the total count, which we include in the query. 

Now that we have defined the current page, we can go back to configuring the table's properties and set the Pagination for the table.

LudoNoens_1-1717483492927.png

In the custom object, we set the page size to 10 to keep things simple. For the Page number, we use the page variable CurrentPage. Assuming the total amount of records for this entity will not change, we don't include total count in the query. 

LudoNoens_2-1724051034893.png

We have now defined the buttons and logic for navigating the pages. However, if you would run this, you will notice that the table does not get updated. This is because the table is only showing data queried upon the first render.

Extending the table with a refresh property

In order to trigger a refresh of the table's contents, we need to extend the logic of the table. Select the table and open the component template editor (2nd icon below the Advanced Properties).

LudoNoens_0-1717653071850.png

In the template editor, switch the PROPERTIES view, navigate to the Properties tab and select ADD PROPERTY. Add the property Refresh of type boolean, and provide a title and description.

 

LudoNoens_2-1717656112002.png

Still in the template editor, switch back to VIEW and navigate to the Properties tab and open the logic canvas for the component 'Basic table with data adapter'.  Drag and drop Advanced component 'Receive event' onto the canvas and connect it to DATA | Get record collection. From the event properties, select the Event source as Internal property 'Refresh table' changed.

LudoNoens_4-1717660642797.png

Refreshing the table

The table now has a property called Refresh, which can be used to trigger a refresh of the table's contents. We will bind this property to the page variable refresh that we have created earlier.

LudoNoens_2-1717493281653.png

We are going to toggle the page variable refresh when the user taps the previous and next buttons. For each of the buttons, adapt the logic as follows:

LudoNoens_3-1717493647528.png

To toggle the value of refresh, we use the formula:

NOT(pageVars.refresh)


Purchase Orders

We follow the same steps as above to create another page showing Purchase Orders. 

For the data entity fields, I will be using PurchaseOrder, PurchaseOrderDate, PurchaseProcessingStatus and Supplier. I've shortened the display name of these fields, to keep the table header crisp and clean.

LudoNoens_4-1717494661651.png

 

Page Navigation

Our application now has 3 pages. We can configure page navigation in the NAVIGATION tab. For each page we can configure an icon and the tab name.

LudoNoens_6-1717495155884.png

Summary – use case E

In this use case we have used the SAP Business Accelerator Hub site to identify APIs available on our S/4HANA Cloud 'sandbox' ERP system. We've picked an OData V2 and an OData V4 data source and created BTP Destinations to access these destinations in our cloud development environment. We have then added these data sources in SAP Build Apps and selected the data entities to be used in our application.

We have add two pages to display selected data properties in a table and implemented pagination, as the amount of data stored in the cloud ERP system can be significant and we don't need all this data in the app. For table refresh to work, we extended the component available in marketplace. We also created a query to find out the total amount of records in the system that can be retrieved. And finally, we have defined the application's page navigation.

What's next

In the next blog post, we will continue on the connectivity topic and explore how we can use relationships between data entities.

6 Comments