SAP S/4HANA, SAP BTP, SAP ABAP

[Feature]Side-by-side extensiblity to adjust the received transmission (ABAP)

Background

Some suppliers may have special logic to enhance the outbound delivery number, customer material, header VAT amount and so on in the received transmsion from customer. This blog would introduce how to make use of the side-by-side extensibility offered by SAP Self-Billing Cockpit. SAP Self-Billing Cockpit allows you to implement your custom business logic by using RESTful APIs.You can create your RESTful APIs on BTP or SAP S/4HANA.

Solution

Create one Restful API in S/4HANA system

1. Create structures and tables for restful API import parameters in t-code “SE11”.

The field name of the fields in the S/4HANA structure shall be the same as the fields in the documents.

Later on, we would use the format coversion function module directly to covert the JSON request body to the ABAP structure.

If not, you need to implement the covertion logic by yourself.

Example for Self-Billing with automatic posting.

Create structure ZSBCITEM for self-billing document item

Create table type ZSBCITEMS for self-billing document items

Create structure type ZSBCDOCUMENT for Self-Billing document

Create table type ZSBCDOCUMENTS for self-billing documents

Create structure type ZSBCTRANSMISSION for Self-Billing transmission

Create table type ZSBCTRANSMISSIONS for Self-Billing transmissions

Create structure type ZSBWAPTRANSEXTENSIONDTO for the request body.

2. In the restful API, we need to create two class in t-code “SE24” as below.

One request handle class “ZCL_SBC_REQ_HANDLER” which inherit from CL_REST_HTTP_HANDLER

This class would be maintain in the SICF service node later on to handle the restful API.

Overwrite the method “Get_ROOT_HANDLER”, add the route logic. iv_template “/sbctestclark” is the restful API URL patch. iv_handler_class is the handler class of this restful API.

DATA(io_router) = NEW cl_rest_router( ).

    io_router->attach(
      EXPORTING
        iv_template      =  '/sbctestclark'                " Unified Name for Resources
        iv_handler_class =      'ZCL_SBC_REQ_PROVIDER_CLARK'            " Object Type Name
*        it_parameter     =                  " Resource contructor parameters
    ).

    ro_root_handler = io_router.

Then you need to create the handler class “ZCL_SBC_REQ_PROVIDER” which inherit from CL_REST_RESOURCE.

Overwrite the POST method as Self-Billing cockpit would call this restful API by POST

Example code:

1. Get the SBWAP transmission from request body. lo_entity and lv_data.

2. Use /ui2/cl_json=>deserialize to cover the SBWAP transmission from JSON format to the transmission structure which we create before in SE11.

3. Adjust the SBWAP transmission base on your requirements.

In this example, i update the delivery number in case the delivery number is less than 7 digit. Also remove the special character in customer materials

4. Use /ui2/cl_json=>serialize to cover the SBWAP transmisison from structure to JSON format

5. Add the adjusted transmission in response body. SBC would recive this body and run the self-billing process on it.

DATA(lo_entity) = mo_request->get_entity( ).
    DATA(lv_data) = lo_entity->get_string_data( ).
    DATA ls_sbcdto TYPE ZSBWAPTRANSEXTENSIONDTO.
    DATA ls_response TYPE string.
    DATA: ls_specialchart TYPE char50 value '-'''.

    /ui2/cl_json=>deserialize(
      EXPORTING
        json             =  lv_data                " JSON string
      CHANGING
        data             =  ls_sbcdto               " Data to serialize
    ).
   LOOP AT ls_sbcdto-transmissions ASSIGNING FIELD-SYMBOL(<ls_sbctransmission>).
*Update delivery
    LOOP AT <ls_sbctransmission>-sddocuments ASSIGNING FIELD-SYMBOL(<ls_sddocument>).
      IF STRLEN( <ls_sddocument>-delivery ) EQ 7.
        CONCATENATE '1YY' <ls_sddocument>-delivery INTO <ls_sddocument>-delivery.
      ENDIF.

      LOOP AT <ls_sddocument>-sddocumentitems ASSIGNING FIELD-SYMBOL(<ls_sddocumentitem>).
*Remove special chara in customer material
        replace all occurrences of '-' in <ls_sddocumentitem>-CUSTOMERMATERIAL with ''.
        replace all occurrences of '_' in <ls_sddocumentitem>-CUSTOMERMATERIAL with ''.
        replace all occurrences of '@' in <ls_sddocumentitem>-CUSTOMERMATERIAL with ''.
        replace all occurrences of '#' in <ls_sddocumentitem>-CUSTOMERMATERIAL with ''.
        replace all occurrences of '*' in <ls_sddocumentitem>-CUSTOMERMATERIAL with ''.
        CONDENSE <ls_sddocumentitem>-CUSTOMERMATERIAL NO-GAPS.
      ENDLOOP.
    ENDLOOP.
   ENDLOOP.


    /ui2/cl_json=>serialize(
      EXPORTING
        data             =     ls_sbcdto              " Data to serialize
      RECEIVING
        r_json           =     ls_response            " JSON string
    ).

  mo_response->create_entity( )->set_string_data( iv_data = ls_response ).

Create one service node for restful API in t-code SICF

Logon Data maintain the client, user and password. Later on, we would maintain this user and password in BTP destination.

In the handler list, maintain the handle class “ZCL_SBC_REQ_HANDLER” created before with the URL patch and router

Save and active the service

In case the restful API development done. You can use POSTMAN to test the API authroization and function firstly.

Example request body:

{
    "TRANSMISSIONS": [
        {
            "TRANSMISSIONID": "TRANSMISSION",
            "SENDERID": "Sender",
            "PREVIOUSTRANSMISSIONID": null,
            "TRANSMISSIONDATE": "20200106",
            "SDDOCUMENTS": [
                {
                    "HEADERACTIONCODE": "000",
                    "HEADERREFERENCE": null,
                    "ISOCURRENCY": "EUR",
                    "SOLDTOPARTY": null,
                    "SUPPLIER": null,
                    "PARTNERDESCRIPTION": null,
                    "UNLOADINGPOINTNAME": null,
                    "DELIVERY": "DEL7C37",
                    "EXTERNALDELIVERYNOTE": null,
                    "DELIVERYRELEVANCEDATE": "2022-01-06T12:36:31",
                    "HEADERDOCUMENTREFERENCEDATE": null,
                    "CUSTOMERVATREGISTRATIONNUMBER": null,
                    "SUPPLIERVATREGISTRATIONNUMBER": null,
                    "SHIPPINGDATE": null,
                    "PAYMENTDUEDATE": null,
                    "GOODSRECEIPTDATE": null,
                    "DOCUMENTDATE": null,
                    "CREDITADVICEID": null,
                    "CHEQUENUMBER": null,
                    "SUPPLIERPOSTINGNUMBER": null,
                    "DELIVERYNETVALUE": null,
                    "DELIVERYVATAMOUNT": null,
                    "SDDOCUMENTITEMS": [
                        {
                            "PRODUCT": "GT8887",
                            "CUSTOMERMATERIAL": "GT_8 887",
                            "ITEM": null,
                            "ITEMACTIONCODE": null,
                            "QUANTITY": null,
                            "ISOUNITOFMEASURE": null,
                            "ITEMDOCUMENTREFERENCEDATE": null,
                            "VATINDICATOR": null,
                            "VATRATE": null,
                            "VATAMOUNT": null,
                            "NETVALUE": null,
                            "NETPRICE": null,
                            "NETPRICEUNIT": null
                        },
                        {
                            "PRODUCT": "GT8888",
                            "CUSTOMERMATERIAL": "GT88*8",
                            "ITEM": null,
                            "ITEMACTIONCODE": null,
                            "QUANTITY": null,
                            "ISOUNITOFMEASURE": null,
                            "ITEMDOCUMENTREFERENCEDATE": null,
                            "VATINDICATOR": null,
                            "VATRATE": null,
                            "VATAMOUNT": null,
                            "NETVALUE": null,
                            "NETPRICE": null,
                            "NETPRICEUNIT": null
                        }
                    ]
                }
            ]
        }
    ]
}

How to get the restful API URL patch?

1. Domain: SICF->Go to-> ICM Monitor-> Services

Use the one domain with HTTPS

2. The service node we created before “ZSBC”

3. The restful API URL patch in the handler class “/sbctestclark”

URL = Domain + Service node + URL patch

Create the destination on SAP BTP

1. Log on to the SAP BTP Cockpit (Cloud Foundry environment) with your registered subaccount.

2. Choose Connectivity Destination New Destination to create a new destination for aligning transmission data.

3. In the Destination Configuration wizard, configure the destination as follows:

  • For self-billing with automatic posting:

Destination Property

Value
Name

SBWAP_TRANS_EXT

Type  HTTP 
Description  Destination for transmission data alignment in self-billing with automatic posting 
URL  <The URL path of the RESTful API created in the previous step> 
Proxy Type 
  • For the RESTful API created in SAP S/4HANA, choose OnPremise.
  • For the RESTful API created on SAP BTP, choose Internet 
Authentication 

Basic Authentication

User  <User with the authorization of the RESTful API created in the previous step> 
Password 

<Password of the user>

Test in Self-Billing Cockpit

Until now, you can start to send one transmission with specify customer material to Self-Billing Cockpit.

In transmission we send the customer material TG80***01 which had been updated to TG8001 by extension in S/4HANA.

Click the display change log button, we can see the change been done by custom extension