Custom FIORI App – ODATA for Create PR using external catalog Ariba (Punch Out Catalog)
This blog focuses only on the technical details of using the external procurement catalog ARIBA in FIORI (ECC) and not on Create PR. For procurement, the user launches the external catalog (punch out), selects the items and return from the catalog using OCI (Open Catalog Interface). There are many blogs explaining the OCI concepts so we will not go deep in this. In simple words, the OCI interface is a simple protocol that launches a supplier catalog using a simple HTTP get or post command, also the return from the catalog is a simple post back.
This blog highlights the technical approach used to
- Call the external catalog (ARIBA) from FIORI – Simple HTTP POST
- Return the catalog items back to FIORI – Capturing the response form data from HTTP Post
- Calling the external catalog (ARIBA) from FIORI
Let’s understand the process flow first. The HTTP POST call structure is maintained in SPRO. For Purchase Requisition, the path is SPRO->Materials Management->Purchasing->Environment Data->Web Services: ID and Description. These parameters are read with their respective values maintained in SPRO (fixed or runtime) and a simple HTML form POST is done. This calls the ARIBA catalog.
Here the most important part is the HOOK_URL, this will contain the path where the catalog must return with the response items.
Technically, in ECC WSI_CALL is the FM that is used to call the external catalog by specifying the web service id and the HOOK_URL. WSI_CALL internally calls WSI_CUSTOMIZING_READ to read the SPRO call structure.
The approach used here in Odata service is to reuse the same FM WSI_CUSTOMIZING_READ and the parameters (as in the above screen shot with values) are returned to UI that builds a HTML POST same as it is done in ECC. This HTML form POST launches external catalog ARIBA. The HTML form built in UI with the inputs from ODATA looks like this:
<form action="ARIBA URL" name="jump"method="POST"> <input type="hidden" name="EmailAddress" value="runtime"> <input type="hidden" name="~returntarget" value="as maintained in SPRO"> <input type="hidden" name="PunchinPassword" value=" as maintained in SPRO "> <input type="hidden" name="PunchinId" value=" as maintained in SPRO "> <input type="hidden" name="SupplierDomain" value=" as maintained in SPRO "> <input type="hidden" name="User.Address.UniqueN" value="as maintained in SPRO "> <input type="hidden" name="realm" value=" as maintained in SPRO "> <input type="hidden" name="FullName" value=" runtime "> <input type="hidden" name="UniqueName" value=" runtime "> <input type="hidden" name="~caller" value=" as maintained in SPRO "> <input type="hidden" name="~target" value="as maintained in SPRO "> <input type="hidden" name="~OkCode" value=" as maintained in SPRO "> <input type="hidden" name="ModifyURL" value=" as maintained in SPRO "> <input type="hidden" name="BYPASS_INB_HANDLER" value=" as maintained in SPRO "> <input type="hidden" name="BYPASS_OUTB_HANDLER" value=" as maintained in SPRO "> <input type="hidden" name="HOOK_URL" value="URL where the catalog must return"> <input type="hidden" name="OCI_VERSION" value=" as maintained in SPRO "> <input type="hidden" name="OPI_VERSION" value=" as maintained in SPRO "> <input type="hidden" name="returntarget" value=" as maintained in SPRO "> </form>
2. Return the catalog items back to FIORI – Capturing the response HTTP POST
After the catalog is launched and the shopping cart is created, after checkout the cart items are returned back using OCI. UI5 does not have the capability to read this. So the approach used is to redirect the catalog to a BSP application (HOOK_URL) that reads the request form fields and return this to FIORI.
In simple HTTP post the BSP application URL is specified. This BSP application is developed on Gateway server.
<input type=”hidden” name=”HOOK_URL” value=”BSP Application URL”>
The approach used is to read the HTTP form data in BSP on Gateway and use the same standard FM’s to map that data by using a custom RFC FM developed on ECC. FM is developed in ECC as all the standard OCI FMs are available on ECC and not on gateway.
Step 1: Read the Response FORM data
In OnInitialization Event of BSP , the form data is read using the below code.
CALL METHOD request->get_form_fields CHANGING fields = gt_myattr. LOOP AT gt_myattr INTO DATA(lwa_attr). CONCATENATE lv_string lwa_attr-name lc_equal lwa_attr-value lc_ampersand INTO lv_string. ENDLOOP.
This internal table gt_myattr contains all the shopping cart items in name value pair. This table is then converted into a string of above format as expected in standard FM.
Step 2: RFC for mapping the ARIBA response to required format and return in JSON object format to Gateway
CALL FUNCTION ’TEST’ DESTINATION lv_rfcdest EXPORTING iv_string = lv_string IMPORTING ex_json = gv_json_c.
The FM follows the standard code approach :
Data : lt_str TYPE TABLE OF swastrtab. DATA :cnht_post_data_line(256) TYPE c. DATA : cnht_post_data_tab TYPE TABLE OF cnht_post_data_line. *Split string in required internal table format CALL FUNCTION 'SWA_STRING_SPLIT' EXPORTING input_string = iv_string max_component_length = 255 TABLES string_components = lt_str EXCEPTIONS max_component_length_invalid = 1 OTHERS = 2. LOOP AT lt_str INTO DATA(ls_str). cnht_post_data_line = ls_str-str. APPEND cnht_post_data_line TO cnht_post_data_tab. ENDLOOP. *Pass this to the FM for mapping DATA : ltr_fields TYPE TABLE OF savwctxt. CALL FUNCTION 'WSI_MAP_REQUEST' EXPORTING it_request = cnht_post_data_tab TABLES et_its_fields = ltr_fields. LOOP AT ltr_fields ASSIGNING FIELD-SYMBOL(<lwa_fields>). TRANSLATE <lwa_fields>-fieldname TO UPPER CASE. ENDLOOP. LOOP AT ltr_fields INTO DATA(ls_fields). CHECK ls_fields-fieldname(17) EQ 'NEW_ITEM-LONGTEXT' OR ls_fields-fieldname EQ 'NEW_ITEM-DESCRIPTION' OR ls_fields-fieldname EQ 'NEW_ITEM-VENDORMAT' OR ls_fields-fieldname EQ 'NEW_ITEM-MANUFACTMAT'. REPLACE ALL OCCURRENCES OF: lc_html_amp IN ls_fields-fieldcont WITH lc_amper IN CHARACTER MODE, lc_html_equ IN ls_fields-fieldcont WITH lc_equal IN CHARACTER MODE. ENDLOOP. * This FM maps the data as per the DDIC structure CALL FUNCTION 'WSI_IMPORT_DATA' EXPORTING iv_structure_name = 'MMPUR_OCI_CAT_RETURN_TYPE' TABLES it_form_fields = ltr_fields et_ws_item_data = lt_items et_longtext = lt_text EXCEPTIONS no_webservice_active = 0 no_ddic_info = 0 import_error = 0 OTHERS = 0. Map these lt_items & lt_text to your required output table structure that needs to be sent to UI for display. For ex : LOOP AT lt_items INTO DATA(lwa_items). CLEAR : lwa_pritems. lwa_pritems-preq_item = lwa_items-line. lwa_pritems-currency = lwa_items-currency. lwa_pritems-quantity = lwa_items-quantity. lwa_pritems-unit = lwa_items-unit. lwa_pritems-preq_price = lwa_items-price. lwa_pritems-short_text = lwa_items-description. LOOP AT lt_text INTO DATA(lwa_text) WHERE line = lwa_items-line. CONCATENATE lwa_pritems-itemtext lwa_text-text_line INTO lwa_pritems- itemtext SEPARATED BY space. ENDLOOP. APPEND lwa_pritems TO lt_pritems. CLEAR lwa_items. ENDLOOP. *Convert the internal table to JSON Object DATA(lo_json_writer) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). CALL TRANSFORMATION id SOURCE = lt_pritems RESULT XML lo_json_writer. ex_json = cl_abap_codepage=>convert_from( lo_json_writer->get_output( ) ).
Step 3: Passing the JSON Object to UI5 application so that it can be used to bind data in the required UI elements ( form or table )
This completes the cycle of calling the external catalog from FIORI, creating shopping cart and returning the items back to FIORI app from the Odata side.
For the UI code, please refer Rabin’s blog:
Thanks for very nice blog.
Please note that we have similar requirement and tried following above steps and steps mentioned to create SAPUi5 app. But it is not working. Blog also does not clearly define SAPUI5 part very well.
Any additional assistance regarding this - ARIBA punchout catalog opening from custom Fiori app - would be appreciated.