Enterprise Resource Planning Blogs by SAP
Get insights and updates about cloud ERP and RISE with SAP, SAP S/4HANA and SAP S/4HANA Cloud, and more enterprise management capabilities with SAP blog posts.
cancel
Showing results for 
Search instead for 
Did you mean: 
696

Overview

This sample scenario shows how you can create and update sales orders in SAP S/4HANA Cloud Public Edition from an ABAP development environment in SAP BTP. You process the sales orders with the Sales Order (A2X) OData V4 API using a service consumption model.

Preparation

You need two systems:

  • A provisioning system: This is your SAP S/4HANA Public Edition system, the system in which you want to create and update sales orders.
  • A consuming system: This is your BTP development system.

Preparation in the Provisioning System

  1. In the Maintain Communication Users app, create a communication user.
  2. In the Communication Systems app, create a communication system.
  3. In the Communication Arrangements app, create an communication arrangement for inbound APIs of scenario SAP_COM_0109.

For more information, see also Enable connection from a remote instance of SAP BTP, ABAP Environment.

Preparation in the Consuming System

  1. In ABAP Development Tools (ADT), create an outbound service, for example, Z_SO_ODATA_V4_REST.
  2. In ADT, create an outbound communication scenario, for example, Z_SO_ODATA_V4_CSCEN.
  3. In the Communication Systems app, create a communication system, for example, ZSDSLS_SCM_0109.
  4. In the Communication Arrangements app, create an communication arrangement for the scenario that you created in step 2.

For more information, see also Prepare Consuming System and Service Consumption Model.

Download of the EDMX Specification

Entity Data Model XML files (in short EDMX) define the entities of the OData services that you want to consume in the application. You can download the EDMX for the Sales Order (A2X) OData V4 API from the SAP Business Accelerator Hub.

Implementation in the Consuming System

Creation of the Service Consumption Model

In ADT, you create the service consumption model in the consuming system, using the EDMX that you downloaded in the previous step.

1. Select your package and choose New > Other ABAP Repository Object in the context menu.

2. For filtering, enter “service “, and select Service Consumption Model. Then, choose Next.

Katsiaryna_Darapeika_0-1735896263713.png

3. Enter a name and a description. For Remote Consumption Mode, select OData, and choose Next.

Katsiaryna_Darapeika_0-1735896357574.png

4. Choose Browse… to navigate to your saved EDMX. Choose Open, enter a class name, then choose Next.

Katsiaryna_Darapeika_1-1735896428882.png

5. The entities and their type are displayed. Choose Next.

Katsiaryna_Darapeika_2-1735896489364.png

6. The flag ETag Support is automatically set for the API entities that support ETag. Choose Next.

7. Select your transport request and choose Finish.

In an editor, the service consumption model is displayed. You can see the model class, the entity sets, and code samples for CRUD operations.

Katsiaryna_Darapeika_0-1735897816347.png

Creation of the Implementation Class

In ADT, you create an ABAP Console application class that instantiates a proxy. This passes an OData request to the Sales Order (A2X) API (from the consuming system to the provisioning system).

1. Open your package in ADT and choose New > ABAP Class.

2. Enter a name and a description. Add the interface if_oo_adt_classrun and choose Next.

Katsiaryna_Darapeika_0-1735899032716.png

3. Select your transport request and choose Finish.

4. Copy the following code and paste it into your class:

 

CLASS zcl_scm_so_scenarios_v4 DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
  PROTECTED SECTION.
  PRIVATE SECTION.

    TYPES t_business_data TYPE z_salesorder_v4=>tys_sales_order_type.

    TYPES: BEGIN OF ty_so_deep.
             INCLUDE    TYPE z_salesorder_v4=>tys_sales_order_type.
    TYPES    item TYPE z_salesorder_v4=>tyt_sales_order_item_type.
    TYPES    text       TYPE z_salesorder_v4=>tyt_sales_order_text_type.
    TYPES    partner    TYPE z_salesorder_v4=>tyt_sales_order_partner_type.
    TYPES    pricing_element TYPE z_salesorder_v4=>tyt_sales_order_pricing_elem_2.
    TYPES  END OF ty_so_deep.

    METHODS create_client_proxy
      RETURNING VALUE(ro_client_proxy) TYPE REF TO /iwbep/if_cp_client_proxy
      RAISING   cx_root.

    METHODS read_entity_by_key
      IMPORTING
        io_client_proxy  TYPE REF TO /iwbep/if_cp_client_proxy
        iv_entity        TYPE /iwbep/if_cp_runtime_types=>ty_entity_set_name
        is_entity_key    TYPE any
      EXPORTING
        es_business_data TYPE t_business_data
        eo_client_proxy  TYPE REF TO /iwbep/if_cp_client_proxy.

    METHODS create_deep_so
      IMPORTING
        io_client_proxy  TYPE REF TO /iwbep/if_cp_client_proxy
      EXPORTING
        es_business_data TYPE ty_so_deep.

    METHODS update_so
      IMPORTING
        iv_etag         TYPE string
        iv_sales_order  TYPE vbeln
        io_client_proxy TYPE REF TO /iwbep/if_cp_client_proxy.

ENDCLASS.


CLASS zcl_scm_so_scenarios_v4 IMPLEMENTATION.

  METHOD if_oo_adt_classrun~main.

    "This is an executable method in which we create a deep sales order and update a field using the Service Consumption Model
    DATA: ls_entity_key TYPE z_salesorder_v4=>tys_sales_order_type.

    TRY.

        " Create client proxy for OData V4 consumption
        create_client_proxy( RECEIVING ro_client_proxy = DATA(lo_client_proxy) ).

        " Create deep sales order using Service Consumption Model
        create_deep_so( EXPORTING io_client_proxy = lo_client_proxy
                        IMPORTING es_business_data = DATA(ls_deep_so) ).

        out->write( ls_deep_so ).

        " Retrieve the sales order ID from the response of the create request and set entity key
        ls_entity_key = VALUE #( sales_order  = ls_deep_so-sales_order ).

        " Read sales order header after create request
        read_entity_by_key( EXPORTING io_client_proxy  = lo_client_proxy
                                      iv_entity        = 'SALES_ORDER'
                                      is_entity_key    = ls_entity_key
                            IMPORTING es_business_data = DATA(ls_so_info) ).

        out->write( ls_so_info ).

        " Update an already created sales order by specifying a new value for the PURCHASE_ORDER_BY_CUSTOMER field
        update_so( EXPORTING iv_sales_order   = ls_deep_so-sales_order
                     iv_etag          = ls_so_info-etag
                     io_client_proxy  = lo_client_proxy ).

        " Read sales order header after the update request
        read_entity_by_key( EXPORTING io_client_proxy  = lo_client_proxy
                              iv_entity        = 'SALES_ORDER'
                              is_entity_key    = ls_entity_key
                    IMPORTING es_business_data = DATA(ls_updated_so_info) ).

        out->write( ls_updated_so_info ).

      CATCH cx_root INTO DATA(exception).
        out->write( cl_message_helper=>get_latest_t100_exception( exception )->if_message~get_text( ) ).

    ENDTRY.

  ENDMETHOD.

  METHOD create_client_proxy.

    " Create client proxy for OData V4 consumption
    DATA:
      lo_http_client  TYPE REF TO if_web_http_client.

    TRY.
        " 1. Get the destination of remote system and create http client
        DATA(lo_destination) = cl_http_destination_provider=>create_by_comm_arrangement(
                                                     comm_scenario  = 'Z_SO_ODATA_V4_CSCEN'
                                                     comm_system_id = 'ZSDSLS_SCM_0109'
                                                     service_id     = 'Z_SO_ODATA_V4_REST' ).

        lo_http_client = cl_web_http_client_manager=>create_by_http_destination( lo_destination ).

        " 2. Create client proxy
        ro_client_proxy = /iwbep/cl_cp_factory_remote=>create_v4_remote_proxy(
          EXPORTING
             is_proxy_model_key       = VALUE #( repository_id       = 'DEFAULT'
                                                 proxy_model_id      = 'Z_SALESORDER_V4'
                                                 proxy_model_version = '0001' )
            io_http_client             = lo_http_client
            iv_relative_service_root   = '' ).

        ASSERT lo_http_client IS BOUND.

      CATCH /iwbep/cx_cp_remote INTO DATA(lx_remote).
        " Handle remote Exception
        " It contains details about the problems of your http(s) connection
        RAISE EXCEPTION TYPE /iwbep/cx_cp_remote
          EXPORTING
            previous = lx_remote.
      CATCH /iwbep/cx_gateway INTO DATA(lx_gateway).
        " Handle Exception
        RAISE EXCEPTION TYPE /iwbep/cx_gateway
          EXPORTING
            previous = lx_gateway.
      CATCH cx_web_http_client_error INTO DATA(lx_web_http_client_error).
        " Handle Exception
        RAISE SHORTDUMP lx_web_http_client_error.

    ENDTRY.

  ENDMETHOD.

  METHOD create_deep_so.

    " Create deep sales order with one item, one header text, one header partner and one header pricing element
    DATA:
      lo_request      TYPE REF TO /iwbep/if_cp_request_create,
      lo_response     TYPE REF TO /iwbep/if_cp_response_create,
      ls_deep_so_data TYPE ty_so_deep.

    TRY.

        " Prepare business data for a create operation
        ls_deep_so_data = VALUE #( sales_order_type_2                           = 'TA'
                                   sales_organization                           = '1010'
                                   distribution_channel                         = '10'
                                   organization_division                        = '00'
                                   sold_to_party                                = '10100001'
                                   purchase_order_by_customer                   = 'Created from BTP system (ODATA v4)'

                                   item = VALUE #( ( product                    = 'TG11'
                                                     requested_quantity         = '2'
                                                     requested_quantity_isounit = 'PCE'
                                                    ) )

                                   text =  VALUE #( ( language                  = 'EN'
                                                      long_text_id              = 'TX02'
                                                      long_text                 = 'Test Text from BTP system using ODATA v4 call'  ) )

                                   partner = VALUE #( ( partner_function        = 'ZM'
                                                        personnel               = '50000025' ) )

                                   pricing_element = VALUE #( ( condition_type        = 'DRV1'
                                                                condition_rate_amount = '12.50'
                                                                condition_currency    = 'USD' ) ) ).

        " Navigate to the resource and create a request for the create operation
        lo_request = io_client_proxy->create_resource_for_entity_set( 'SALES_ORDER' )->create_request_for_create( ).

        " Return a data description node for the deep sales order
        DATA(lo_data_desc_node_so) = lo_request->create_data_descripton_node( ).
        " Set the properties of the Header node
        lo_data_desc_node_so->set_properties( VALUE #( ( |SALES_ORDER_TYPE_2| )
                                                       ( |SALES_ORGANIZATION| )
                                                       ( |DISTRIBUTION_CHANNEL| )
                                                       ( |ORGANIZATION_DIVISION| )
                                                       ( |SOLD_TO_PARTY| )
                                                       ( |PURCHASE_ORDER_BY_CUSTOMER| ) )  ).

        " Add a child node Item for a navigation property
        DATA(lo_data_desc_node_so_item) = lo_data_desc_node_so->add_child( 'ITEM' ).
        " Set the properties of the Item node
        lo_data_desc_node_so_item->set_properties( VALUE #( ( |PRODUCT| )
                                                            ( |REQUESTED_QUANTITY| )
                                                            ( |REQUESTED_QUANTITY_ISOUNIT| )
                                                            ) ).

        " Add a child node Header Text for a navigation property
        DATA(lo_data_desc_node_so_text) = lo_data_desc_node_so->add_child( 'TEXT' ).
        " Set the properties of the Header Text node
        lo_data_desc_node_so_text->set_properties( VALUE #( ( |LANGUAGE| )
                                                            ( |LONG_TEXT_ID| )
                                                            ( |LONG_TEXT| )  ) ).

        " Add a child node Header Partner for a navigation property
        DATA(lo_data_desc_node_so_partner) = lo_data_desc_node_so->add_child( 'PARTNER' ).
        " Set the properties of the Header Partner node
        lo_data_desc_node_so_partner->set_properties( VALUE #( ( |PARTNER_FUNCTION| )
                                                               ( |PERSONNEL| ) ) ).

        " Add a child node Header Pricing Element for a navigation property
        DATA(lo_data_desc_node_so_pr_el) = lo_data_desc_node_so->add_child( 'PRICING_ELEMENT' ).
        " Set the properties of the Header Pricing Element node
        lo_data_desc_node_so_pr_el->set_properties( VALUE #( ( |CONDITION_TYPE| )
                                                             ( |CONDITION_RATE_AMOUNT| )
                                                             ( |CONDITION_CURRENCY| ) ) ).

        " Set deep business data of a sales order for the create operation
        lo_request->set_deep_business_data( is_business_data    = ls_deep_so_data
                                            io_data_description = lo_data_desc_node_so ).

        " Execute the request
        lo_response = lo_request->execute( ).

        " Get the response business data of the sales order
        lo_response->get_business_data( IMPORTING es_business_data = es_business_data ).

      CATCH /iwbep/cx_cp_remote INTO DATA(lx_remote).
        " Handle remote Exception
        " It contains details about the problems of your http(s) connection

      CATCH /iwbep/cx_gateway INTO DATA(lx_gateway).
        " Handle Exception

      CATCH cx_web_http_client_error INTO DATA(lx_web_http_client_error).
        " Handle Exception
        RAISE SHORTDUMP lx_web_http_client_error.

    ENDTRY.

  ENDMETHOD.

  METHOD read_entity_by_key.

    DATA:
      ls_entity_key    TYPE z_salesorder_v4=>tys_sales_order_type,
      ls_business_data TYPE z_salesorder_v4=>tys_sales_order_type,
      lo_resource      TYPE REF TO /iwbep/if_cp_resource_entity,
      lo_request       TYPE REF TO /iwbep/if_cp_request_read,
      lo_response      TYPE REF TO /iwbep/if_cp_response_read.

    TRY.

        " Navigate to the resource
        lo_resource = io_client_proxy->create_resource_for_entity_set( iv_entity )->navigate_with_key( is_entity_key ).

        " Execute the request and retrieve the business data
        lo_response = lo_resource->create_request_for_read( )->execute( ).
        lo_response->get_business_data( IMPORTING es_business_data = es_business_data ).

        eo_client_proxy = io_client_proxy.

      CATCH /iwbep/cx_cp_remote INTO DATA(lx_remote).
        " Handle remote Exception
        " It contains details about the problems of your http(s) connection

      CATCH /iwbep/cx_gateway INTO DATA(lx_gateway).
        " Handle Exception

      CATCH cx_web_http_client_error INTO DATA(lx_web_http_client_error).
        " Handle Exception
        RAISE SHORTDUMP lx_web_http_client_error.

    ENDTRY.

  ENDMETHOD.

  METHOD update_so.

    " Update an already created sales order by specifying a new value for the PURCHASE_ORDER_BY_CUSTOMER field
    DATA:
      ls_business_data TYPE z_salesorder_v4=>tys_sales_order_type,
      ls_entity_key    TYPE z_salesorder_v4=>tys_sales_order_type,
      lo_resource      TYPE REF TO /iwbep/if_cp_resource_entity,
      lo_request       TYPE REF TO /iwbep/if_cp_request_update,
      lo_response      TYPE REF TO /iwbep/if_cp_response_update.

    TRY.

        " Set entity key with the sales order ID
        ls_entity_key = VALUE #( sales_order  = iv_sales_order ).

        " Prepare the business data for the update operation
        ls_business_data = VALUE #( purchase_order_by_customer  = 'Updated from BTP system (ODATA v4)' ).

        " Navigate to the resource and create a request for the update operation
        lo_resource = io_client_proxy->create_resource_for_entity_set( 'SALES_ORDER' )->navigate_with_key( ls_entity_key ).
        lo_request = lo_resource->create_request_for_update( /iwbep/if_cp_request_update=>gcs_update_semantic-patch  ).

        " Set ETag
        lo_request->set_if_match( iv_etag ).

        " Set the business data of a sales order by specifying a new value for the PURCHASE_ORDER_BY_CUSTOMER field
        lo_request->set_business_data(
          EXPORTING
            is_business_data            = ls_business_data
            it_provided_property        = VALUE #( ( |PURCHASE_ORDER_BY_CUSTOMER| ) ) ).

        " Execute the request
        lo_response = lo_request->execute( ).

      CATCH /iwbep/cx_cp_remote INTO DATA(lx_remote).
        " Handle remote Exception
        " It contains details about the problems of your http(s) connection

      CATCH /iwbep/cx_gateway INTO DATA(lx_gateway).
        " Handle Exception

      CATCH cx_web_http_client_error INTO DATA(lx_web_http_client_error).
        " Handle Exception
        RAISE SHORTDUMP lx_web_http_client_error.

    ENDTRY.

  ENDMETHOD.
ENDCLASS.

 

5. Format, save, and activate your class.

Test of the Sales Order (A2X) API Call

In the Project Explorer, select your class and choose Run as…> Application Console (F9) in the context menu. You can check the results of the class execution in this console.

1 Comment