Introduction:

Side-by-Side Extension in SAP refers to the approach of extending or enhancing existing SAP systems without modifying their core functionality. It allows for the development and deployment of additional custom applications or functionalities alongside the existing SAP landscape, minimizing the risk of system disruptions.

In a recent project, I was assigned the development of an application following the side-by-side extension approach on SAP BTP. The objective was to enable seamless data exchange between the application and both SAP S/4HANA Public Cloud and Private Cloud. Based on the learnings from the project, I will provide a comprehensive explanation of how to successfully make POST calls to SAP S/4 HANA Public System. It will cover the necessary steps and intricacies involved in integrating and exchanging data between the extensions and the S/4HANA Public system.

Watch out for my next blog where I will give details about exchanging data with S/4 HANA Private Cloud.

Scenario: 

Create a CAP service to create a sales order in SAP S4HANA cloud.

Pre-requisite: 

  1. Need to know how to create a basic CAP project.
  2. SAP S/4HANA Cloud Extensibility service entitlement assigned to subaccount with plan api-access.
  3. Destination service entitlement.
  4. S4 HANA Public Cloud system.

Supporting Material:

You can refer this blog to form a connection with SAP S/4HANA Cloud. Consume Remote Services from SAP S/4HANA Cloud Using CAP

Development:

Sales%20Order%20CAP%20Application

Sales Order CAP Application

  1. Upload the Sales Order edmx file to root folder of your basic cap application.
  2. Navigate to your project and run the below command.
    Make sure that you are in root folder of your project
    cds import ./API_SALES_ORDER_SRV.edmx
     ​
  3. Once you execute command, your edmx file will get moved to .src/external folder and API_SALES_ORDER_SRV.csn and API_SALES_ORDER_SRV.edmx file will get created. Additionally, the file will be registered as service definition in the package.json file.
    As we need to pass the x-csrf-token to handle the POST call, include below lines of code into the package.json 

      "cds": {
        "requires": {
          "API_SALES_ORDER_SRV": {
            "kind": "odata-v2",
            "model": "srv/external/API_SALES_ORDER_SRV",
            "csrf": true,
            "csrfInBatch": true,
  4. Start your cap application:
    cds watch​
  5. Open the CAP application in your browser: http://localhost:4004/You can now see the api-sales-order-srv service with all its entities under Service Endpoints.
  6. Expose the Sales Order through your service by adding following lines to your code in the srv/OrderService.cds file
    using {API_SALES_ORDER_SRV as order} from '../srv/external/API_SALES_ORDER_SRV';
    
    service SalesOrderService @(path : '/Sales') {
     
     entity SalesOrder as projection on order.A_SalesOrder;
    
    };​
  7. Inside same file create another service with rest protocal having action
    Create_Order. Action contains the generic import parameter “object” to receive the payload as deep json call.
    @protocol: 'rest'
    service OrderPostService {
    
      @open
      type object {};
    
      action Create_Order(Order : object) returns object;
    }​
  8. Finally your OrderService.cds file should look like this
    using {API_SALES_ORDER_SRV as order} from '../srv/external/API_SALES_ORDER_SRV';
    
    service SalesOrderService @(path : '/Sales') {
     
     entity SalesOrder as projection on order.A_SalesOrder;
    
    };
    
    @protocol: 'rest'
    service OrderPostService {
    
      @open
      type object {};
    
      action Create_Order(Order : object) returns object;
    }​
  9. If your cds watch is still running then your http://localhost:4004/should look like this.
  10. Follow the steps given in the link to register your HANA system to BTP cockpit.
  11. Create order-service-config.json file in root folder of your project.
    {
        "systemName": "<set in mta.yaml>",
        "communicationArrangement": {
            "communicationArrangementName": "SAP_COM_0109",
            "scenarioId": "SAP_COM_0109",
            "inboundAuthentication": "BasicAuthentication",
            "outboundAuthentication": "BasicAuthentication",
            "communicationSystem": {
                "communicationSystemHostname": "default.com",
                "outboundCommunicationUser": {
                    "username": "DefaultUser",
                    "password": "DefaultPassword"
                }
            }
        }
    }
    
  12. Install the node package to mock the external service.
    npm install @sap-cloud-sdk/http-client @sap-cloud-sdk/util
    ​
  13. Now, add the handler code to delegate the call from the SalesOrder service entity to the remote API_SALES_ORDER_SRV service. In this blog we are going to handle Read and POST action.
    Inside the srv folder create OrderService.js file which is default handler method for the OrderService.cds. Ensure that .js and .cds file name are same.
    const cds = require('@sap/cds');
    module.exports = cds.service.impl(async function (srv) {
    
        const { SalesOrder, Create_Order } = this.entities;
    
        // connects to the remote service
        const order = await cds.connect.to('API_SALES_ORDER_SRV');
    
        // Handle GET call
        srv.on('READ', 'SalesOrder', async req => {
    
        const order = await cds.connect.to('API_SALES_ORDER_SRV');
            return order.run(req.query);
            
        });
    
        // Handle POST call
        srv.on('Create_Order', async(req) => {
    
            // Extract the Sales Order payload from the request data
            const OrderData = req.data.Order;
    
            // Map the POST request on remote service
            const SalesOrderResponse = await order.run(INSERT.into('SalesOrderService.SalesOrder', [OrderData]));
            
            // Return the response
            return SalesOrderResponse;
        });
    
    
    });
  14. On root folder execute the below command.This will add the mta.yaml file to your project
    cds mta add​
  15. Add the SAP S/4HANA cloud extensibility service to your mta.yaml. In this system name should match with the system name given in the global account cockpit.
    resources:
      - name: SalesOrder-order
        type: org.cloudfoundry.managed-service
        parameters:
          skip-service-updates:
            plan: true
            parameters: true
            tags: true
          service: s4-hana-cloud
          service-plan: api-access
          system-name: XXXXXXXXXXXXXXXXXXXXXXX
          path: ./order-service-config.json
          config:
            systemName: XXXXXXXXXXXXXXXXXXXXXXX​

     

  16. Update the mta.yaml file requires section with destination service to access the S/4HANA system.
      - name: SalesOrder-destination
        type: org.cloudfoundry.managed-service
        parameters:
          config:
            HTML5Runtime_enabled: true
            init_data:
              instance:
                destinations:
                  - Authentication: NoAuthentication
                    Name: ui5
                    ProxyType: Internet
                    Type: HTTP
                    URL: https://ui5.sap.com
                existing_destinations_policy: update
            version: 1.0.0
          service: destination
          service-plan: lite​

    and update the srv dependancy as shown below

  17. Build the MTA module from your project root folder and deploy your project with below two command one after another.
    mbt build -t ./
    cf deploy SalesOrder_1.0.0.mtar​

 

Test the Service:

Create test.http file in your root project folder and send the payload as shown below.

@host = <<Your service url after deployment>>
@protocol = https

###
POST {{protocol}}://{{host}}/order-post/Create_Order
Content-Type: application/json

{
    "Order": 
        {
        "SalesOrderType": "OR",
        "SalesOrganization": "1710",
        "DistributionChannel": "10",
        "OrganizationDivision": "00",
        "SoldToParty": "1000180",
        "PurchaseOrderByCustomer": "CAP Application-Mujeeb",
        "CustomerPaymentTerms": "",
        "to_Partner": [
            {
                "PartnerFunction": "SP",
                "Customer": "1000187"
            }
        ],
        "to_Item": [
            {
                "Material": "LXF001",
                "RequestedQuantity": "10"
            }
        ]
        }
}

your payload data may vary, here I am showing one sample.

Sales Order from S/4 Public cloud

Conclusion:

Using CAP you can not only fetch the data but also you can post the data to your core system.

I would love to hear from you! Please leave your feedback below in comments section and ask your questions about the topic in sap community using this link.

 

Sara Sampaio

Sara Sampaio

Author Since: March 10, 2022

0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x