Connector for SAP Business Suite - API description - Developer's manual part 4 - Coding examples

This section contains coding examples that should simplify the implementation of custom processing modules. In principal, it is assumed that a new processing module and a corresponding transfer structure - as shown in the Checklist for creating a new processing module - is used.

1. Example: Provide internal tables

Functionality

This simple example demonstrates how any internal table can be made available for an external caller. Evaluating incoming parameters is forgone.

Concept

Screenshots






Coding

METHOD z_if_ia_ixa_intrexx_api~get_list.

* -------------- local data  
	DATA: lt_data TYPE TABLE OF yixapi_demo.  
	DATA: ls_data TYPE yixapi_demo.

* -------------- init  
	cv_processed = 'X'.  
	ev_error     = 'X'.

* -------------- get inbound parameters
* nothing to do

* -------------- initial check routines
* nothing to do

* -------------- process
* 1. fill demo table  
	ls_data-partner = '100000'.  
	ls_data-name = 'Meier'.  
	APPEND ls_data TO lt_data.

	ls_data-partner = '100001'.  
	ls_data-name = 'Müller'.  
	APPEND ls_data TO lt_data.

	ls_data-partner = '100002'.  
	ls_data-name = 'Schulze'.  
	APPEND ls_data TO lt_data.

* -------------- fill outbound parameters
* 1. sort internal table  
	SORT lt_data BY name.

* 2. loop and fill export  
	LOOP AT lt_data INTO ls_data.    
		CALL METHOD me->set_results_from_struc      
			EXPORTING        
				is_data         = ls_data
				it_requested    = it_requested
				iv_data_struc   = 'YIXAPI_DEMO'
				iv_key_value    = ls_data-partner
				iv_record       = sy-tabix
				iv_struc_name   = 'DEFAULT'
				iv_struc_record = 0
			CHANGING
				ct_keys         = et_result_keys
				ct_results      = et_result_values
			EXCEPTIONS
				failed          = 1
			OTHERS          = 2.
		IF sy-subrc EQ 0.
			ADD 1 TO ev_count.
		ENDIF.
	ENDLOOP.

* -------------- finally set no error
	ev_error    = ' '.

ENDMETHOD.

Test




2. Search help function

Functionality

This example demonstrates a simple search help for the external user. Based on an external entry in a search field (potentially with wildcards) a search is performed in the SAP system and the results are augmented with details. The SAP business partner (BOR Object BUS1006) will serve as an example.

Concept

Screenshots








Coding

METHOD z_if_ia_ixa_intrexx_api~get_list.

* -------------- local data
	DATA: lt_data TYPE TABLE OF yixapi_demo_f4.
	DATA: ls_data TYPE yixapi_demo_f4.
	DATA: ls_filter TYPE LINE OF zia_ixa_api_intrexx_filter_t.
	DATA: lv_search TYPE bu_mcname1.
	DATA: lt_result TYPE TABLE OF bus020_search_result.
	DATA: ls_result TYPE bus020_search_result.
	DATA: lv_name TYPE bu_descrip_long.
	DATA: lt_return TYPE TABLE OF bapiret2.

* -------------- init
	cv_processed = 'X'.
	ev_error     = 'X'.

* -------------- get inbound parameters
	READ TABLE it_filter INTO ls_filter
		WITH KEY fieldname = 'SEARCH'.
	IF sy-subrc NE 0.
		ev_error     = ' '.
		EXIT.
	ENDIF.
	lv_search = ls_filter-value_low.

* -------------- initial check routines
	IF lv_search IS INITIAL OR lv_search EQ '*'.
		ev_error     = ' '.
	EXIT.
	ENDIF.

* -------------- process
* 1. Search
	CALL FUNCTION 'BUPA_SEARCH'
		EXPORTING
			iv_mc_name1      = lv_search
		TABLES
			et_search_result = lt_result.

* 2. build data table
	LOOP AT lt_result INTO ls_result.
		CLEAR lv_name.
		CALL FUNCTION 'BUPA_DESCRIPTION_GET'
			EXPORTING
				iv_partner          = ls_result-partner
			IMPORTING
				ev_description_long = lv_name
			TABLES
				et_return           = lt_return.

	IF lv_name NE space.
			CLEAR ls_data.
			ls_data-search  = lv_search.
			ls_data-partner = ls_result-partner.
			ls_data-name    = lv_name.
			APPEND ls_data TO lt_data.
		ENDIF.
	ENDLOOP.

* -------------- fill outbound parameters
* 1. sort internal table
	SORT lt_data BY name.

* 2. loop and fill export
	LOOP AT lt_data INTO ls_data.
		CALL METHOD me->set_results_from_struc
			EXPORTING
				is_data         = ls_data
				it_requested    = it_requested
				iv_data_struc   = 'YIXAPI_DEMO_F4'
				iv_key_value    = ls_data-partner
				iv_record       = sy-tabix
				iv_struc_name   = 'DEFAULT'
				iv_struc_record = 0
			CHANGING
				ct_keys         = et_result_keys
				ct_results      = et_result_values
			EXCEPTIONS
				failed          = 1
				OTHERS          = 2.
		IF sy-subrc EQ 0.
			ADD 1 TO ev_count.
		ENDIF.
	ENDLOOP.

* -------------- finally set no error
	ev_error    = ' '.

ENDMETHOD.

Test






3. Functional calls

Functionality

Functional calls are required if the external caller calls the SAP system with parameters that are then evaluated there and sent back to the caller. Essentially, this corresponds to the behavior of web services or the call of BAPI functions (without returning tables). Whether and where the data is stored is secondary. The example simulates a price request in SAP. Here, a material number and a customer number are transferred to SAP to calculate potential discounts and the final price is then identified.

Concept

Screenshots








Coding

METHOD z_if_ia_ixa_intrexx_api~modify.

* -------------- local data
	DATA: lv_kunnr TYPE kunnr.
	DATA: lv_matnr TYPE matnr.
	DATA: lv_price(20).

* -------------- init
	cv_processed = 'X'.
	ev_error     = 'X'.

* -------------- no saving within sap - external system is leading
	et_fields[] = it_fields[].
	ev_key = iv_key.

* -------------- get inbound parameters
* without convert because of external structure definition
* -- get kunnr
	CALL METHOD me->get_field
		EXPORTING
			it_fields       = it_fields
			iv_record       = '1'
			iv_struc_name   = 'DEFAULT'
			iv_struc_record = '0'
			iv_fieldname    = 'IV_KUNNR'
			iv_convert      = ' '
		CHANGING
			cv_fieldvalue   = lv_kunnr
		EXCEPTIONS
			failed          = 1
			OTHERS          = 2.
	IF sy-subrc <> 0.
		EXIT.
	ENDIF.

* -- get matnr
	CALL METHOD me->get_field
			EXPORTING
				it_fields       = it_fields
				iv_record       = '1'
				iv_struc_name   = 'DEFAULT'
				iv_struc_record = '0'
				iv_fieldname    = 'IV_MATNR'
				iv_convert      = ' '
			CHANGING
				cv_fieldvalue   = lv_matnr
			EXCEPTIONS
				failed          = 1
				OTHERS          = 2.
	IF sy-subrc <> 0.
		EXIT.
	ENDIF.

* -------------- initial check routines
	CHECK NOT lv_kunnr IS INITIAL
		AND NOT lv_matnr IS INITIAL.

* -------------- process
* 1. call function module to get price (here simulated)
* .....
* 2. write price formatted to transfer structure
	lv_price = '1000,89'.

* -------------- fill outbound parameters
* -- modify ev_price
	CALL METHOD me->set_field
		EXPORTING
*    IV_RECORD       = '1'
*    IV_STRUC_NAME   = 'DEFAULT'
*    IV_STRUC_RECORD = '0'
			iv_fieldname    = 'EV_PRICE'
			iv_convert      = ' '
			iv_fieldvalue   = lv_price
		CHANGING
			ct_fields       = et_fields
		EXCEPTIONS
			failed          = 1
			OTHERS          = 2
				.
	IF sy-subrc <> 0.
		EXIT.
	ENDIF.
* -- modify ev_waers
	CALL METHOD me->set_field
		EXPORTING
*    IV_RECORD       = '1'
*    IV_STRUC_NAME   = 'DEFAULT'
*    IV_STRUC_RECORD = '0'
			iv_fieldname    = 'EV_WAERS'
			iv_convert      = ' '
			iv_fieldvalue   = 'EUR'
		CHANGING
			ct_fields       = et_fields
		EXCEPTIONS
			failed          = 1
			OTHERS          = 2
				.
	IF sy-subrc <> 0.
		EXIT.
	ENDIF.

* -------------- finally set no error
	ev_error    = ' '.

ENDMETHOD.

Test














Specific comments

To implement this concept, a data group is created in the Intrexx portal that contains all of the import and export parameters. Before saving the application for the first time, the field names should be adjusted because otherwise, the automatically generated field names need to be mapped within the SAP processing module.



Click on "Edit data field" here.



Switch to the Expert tab and adjust the name of the data field accordingly. Afterwards, an edit page is created that defines the import parameters for entry and the export parameters as write-protected edit fields. A button triggers the Save action and does not jump to another page. In doing so, the export parameters changed during the saving will be shown in the portal later. The application can now already be tested without SAP integration. Apart from the empty export parameters, it should react normally meaning data records are created upon saving. The SAP integration is implemented via a special exit business logic. The populated edit page is sent to SAP before being saved in the portal. The fields can be evaluated and edited there and potentially, errors may occur. Afterwards, the save action will be continued in the portal. To activate this exit business logic, parameters in the data group's expert attributes need to be modified.



To do this, the datahandler is replaced by an alternative class from the SAP Connector. The parameter "bia-instance" must contain the data source of the called SAP system. The parameter shown as "name" is used as the data group name within the finding of the SAP processing module.

4. SAP triggers with external data storage

Functionality

This example demonstrates how a process in SAP can be triggered when a data record is changed. As a part of this, the data from the data record concerned can also be evaluated.

Concept

The concept is the same as that of the functional call. However, SAP should not perform a check but should rather use the transferred information to start a subsequent SAP-internal process. The processing module should not generate errors.

Coding

METHOD z_if_ia_ixa_intrexx_api~modify.

* -------------- local data
	DATA: lv_kunnr TYPE kunnr.

* -------------- init
	cv_processed = 'X'.
	ev_error     = ' '.

* -------------- no saving within sap - external system is leading
	et_fields[] = it_fields[].
	ev_key = iv_key.

* -------------- get inbound parameters
* -- get kunnr (example)
	CALL METHOD me->get_field
		EXPORTING
			it_fields       = it_fields
			iv_record       = '1'
			iv_struc_name   = 'DEFAULT'
			iv_struc_record = '0'
			iv_fieldname    = 'IV_KUNNR'
		CHANGING
			cv_fieldvalue   = lv_kunnr
		EXCEPTIONS
			failed          = 1
			OTHERS          = 2.
	IF sy-subrc <> 0.
		EXIT.
	ENDIF.

* -------------- initial check routines
	CHECK NOT lv_kunnr IS INITIAL.

* -------------- process
* 1. call a trigger function module (e.g. SWE_EVENT_CREATE)

ENDMETHOD.

5. Data storage in SAP

Functionality

This example demonstrates a simple method for storing data in SAP. Concepts such as locks, permissions and number sequences are forgone. The data is stored in a table in the customer namespace. Within the API methods an additional processing of the data can be triggered. By using GUIDs as the table key, you can forgo the need to use a number sequencing object. An extension of a locking concept can be retrofitted either via the SAP standard locking concept (with the potential disadvantages due to statusless internet use) or by implementing the example in Locking concept.

Concept

Screenshots








Coding

METHOD z_if_ia_ixa_intrexx_api~modify.

* -------------- local data
	DATA: ls_data TYPE yixapi_demodata.
	DATA: lv_guid TYPE sysuuid_x.

* -------------- init
	cv_processed = 'X'.
	ev_error     = 'X'.

* -------------- set export = import
	et_fields[] = it_fields.
	ev_key = iv_key.

* -------------- get existing data
	CLEAR lv_guid.
	IF iv_key NE space AND iv_key NE '-1'.
* ------- get existing
		lv_guid = iv_key.
		SELECT SINGLE * FROM yixapi_demodata
			INTO ls_data
			WHERE lid EQ iv_key.
		IF sy-subrc NE 0.
			CLEAR lv_guid.
		ENDIF.
	ENDIF.

* -------- create a new guid if initial
	IF lv_guid IS INITIAL.
		CALL FUNCTION 'GUID_CREATE'
		IMPORTING
			ev_guid_16 = lv_guid.
	ENDIF.

* -------------- get inbound parameters
	CALL METHOD me->get_fields_from_struc
		EXPORTING
			it_fields         = it_fields
			iv_record         = '1'
			iv_struc_name     = 'DEFAULT'
			iv_struc_record   = '0'
			iv_data_strucname = 'YIXAPI_DEMODATA'
			iv_convert        = 'X'
		CHANGING
			cs_data           = ls_data
		EXCEPTIONS
			failed            = 1
			OTHERS            = 2.
	IF sy-subrc <> 0.
		EXIT. "with error
	ENDIF.

* -------------- process
* 1. set key
	ls_data-lid = lv_guid.
* 2. save to database
	SET UPDATE TASK LOCAL.
	MODIFY yixapi_demodata FROM ls_data.
	IF sy-subrc NE 0.
		ROLLBACK WORK.
		EXIT.
	ENDIF.

* -------------- fill outbound parameters
	REFRESH et_fields.
	CALL METHOD me->set_results_from_struc
		EXPORTING 
			is_data         = ls_data
*    IT_REQUESTED    =
			iv_data_struc   = 'YIXAPI_DEMODATA'
*    IV_KEY_VALUE    =
			iv_record       = 1
*    IV_STRUC_NAME   = 'DEFAULT'
*    IV_STRUC_RECORD = 0
		CHANGING
*      ct_keys         =
			ct_results      = et_fields
	EXCEPTIONS
		failed          = 1
		OTHERS          = 2
		.
	IF sy-subrc <> 0.
		ROLLBACK WORK.
		EXIT.
	ENDIF.

* -------------- final commit
	COMMIT WORK.
	IF sy-subrc NE 0.
		ROLLBACK WORK.
		EXIT.
	ELSE.
		ev_key = lv_guid.
	ENDIF.

* -------------- finally set no error
	ev_error    = ' '.

ENDMETHOD.                    "Z_IF_IA_IXA_INTREXX_API~MODIFY

METHOD z_if_ia_ixa_intrexx_api~delete.

* -------- get existing data via API Func get_Detail
	CALL METHOD me->z_if_ia_ixa_intrexx_api~get_detail
		EXPORTING
			iv_key           = iv_key
*      it_requested     =
		IMPORTING
			ev_error         = ev_error
			et_messages      = et_messages
			et_result_values = et_fields
		CHANGING
			cv_processed     = cv_processed
		EXCEPTIONS
			failed           = 1
			OTHERS           = 2.
	IF sy-subrc <> 0.
		RAISE failed.
	ENDIF.

* -------- check processed and error
	IF cv_processed EQ 'X' AND ev_error NE 'X'.
* -- DELETE Record
		SET UPDATE TASK LOCAL.
		DELETE FROM yixapi_demodata
			WHERE lid EQ iv_key.
		IF sy-subrc NE 0.
			ROLLBACK WORK.
			ev_error = 'X'.
			EXIT.
		ENDIF.
		COMMIT WORK.
	ELSE.
* -- Record does not exist
		cv_processed = 'X'.
		ev_error     = 'X'.
	ENDIF.

ENDMETHOD.

Test






SAP triggers with data storage in the SAP system

Functionality

As is the case with SAP triggers with external data storage, triggers are especially well-suited for connecting processes to one another. This can take place synchronously or asynchronously. Usually, the external performance (e.g. in the portal) and preventing the loss of data is especially important during conception. This example builds on the demo Data storage in SAP. Even reusable triggers can be programmed with the method described there. The transfer structure would then of course not contain the data from SAP business partners, but for example: The following coding contains an example of how the preparation from the demo Data storage in SAP can be used and - after successful execution - a trigger function can be started asynchronously via qRFC.

Concept

Screenshots








Coding

Functional module for the processing


FUNCTION y_ixapi_demo_trigger_process.
*"----------------------------------------------------------------------
*"*"Lokale Schnittstelle:
*" IMPORTING
*"    VALUE(IV_GUID) TYPE  ZIA_IXA_FIELDVALUE
*" EXCEPTIONS
*"     NOT_FOUND
*"----------------------------------------------------------------------



* -------- local data
	DATA: ls_data TYPE yixapi_demodata.



* --------- get data
	SELECT SINGLE * FROM yixapi_demodata
		INTO ls_data
		WHERE lid EQ iv_guid.
	IF sy-subrc NE 0.
		RAISE not_found.
	ENDIF.



* --------- prepare data
	ls_data-processed = 'X'.



* --------- save to db
	SET UPDATE TASK LOCAL.
	MODIFY yixapi_demodata FROM ls_data.
	COMMIT WORK.

ENDFUNCTION.

Method MODIFY

METHOD z_if_ia_ixa_intrexx_api~modify.

* --------- local data
	DATA: lv_queue TYPE trfcqnam VALUE 'YIXAPI-TRIGGER'.

* --------- call super
	CALL METHOD super->z_if_ia_ixa_intrexx_api~modify
		EXPORTING
			iv_key       = iv_key
			it_fields    = it_fields
		IMPORTING
			ev_error     = ev_error
			et_messages  = et_messages
			et_fields    = et_fields
			ev_key       = ev_key
		CHANGING
			cv_processed = cv_processed
		EXCEPTIONS
			failed       = 1
			OTHERS       = 2.
	IF sy-subrc <> 0.
		RAISE failed.
	ENDIF.

* ---------- start trigger
	IF ev_error NE 'X'
		AND cv_processed EQ 'X'
		AND NOT ev_key IS INITIAL.
* ------ luw start
		SET UPDATE TASK LOCAL.
* ------ set queue name
		CALL FUNCTION 'TRFC_SET_QUEUE_NAME'
			EXPORTING
				qname                    = lv_queue
*     NOSEND                   = ' '
*     TRFC_IF_SYSFAIL          = ' '
*     CALL_EVENT               = ' '
			EXCEPTIONS
				invalid_queue_name       = 1
				OTHERS                   = 2
				.
		IF sy-subrc <> 0.
			ev_error = 'X'.
		ENDIF.
* ------ call function module asynchron in qRFC
		CALL FUNCTION 'Y_IXAPI_DEMO_TRIGGER_PROCESS'
			IN BACKGROUND TASK AS SEPARATE UNIT
			DESTINATION 'NONE'
			EXPORTING
				iv_guid   = ev_key
			EXCEPTIONS
				not_found = 1
				OTHERS    = 2.
		IF sy-subrc <> 0.
			ev_error = 'X'.
		ENDIF.
* ------- execute
		COMMIT WORK.
	ENDIF.

ENDMETHOD.

Test








Intrexx-specific remarks

The demo relies on the copying functionality using the Process Manager. The data entry takes place in a custom application with data storage in the portal. If the flag is entered when the data is entered, the Process Manager copies the data to the data group from the example Data storage in SAP.

In doing so, the data is transferred to SAP and booked there. Using the modified processing module, the implementation from the demo Data storage in SAP will be called, followed asynchronously by the RFC processing module within the qRFC. The data record is given the processed flag at this point. QRFC processing procedures can be monitored with the transactions SMQ1 and SMQ2. For more information on this topic, please refer to the SAP documentation on QRFC.

6. Modelling SAP Business objects

Functionality

This example describes the access to SAP standard objects (with data storage in the SAP system). As opposed to the example Data storage in SAP, read and write access to the SAP tables is not performed directly. The SAP Standard usually provides access routines in the form of functional modules (potentially even as a BAPI function) to do this. If such BAPI functions are available for the desired object, these should also be used for the external caller. For demonstration purposes, the example "Modify a customer's contact person in the portal" shall be used. The SAP Business object is "BUS1006002" (Transaction SWO1). This models, for example, in the SAP CRM environment or in custom industry solutions, the relationship between an organiuation (customer) and a person (contact person).



For this object, BAPI functions (e.g. CREATE, CHANGE etc.; recognizable by their green icons) are available. In this example, the external caller always transfers the organization's ID (e.g. stored as a user parameter upon login) and can then access the contact person data. The contact persons will additionally be extended with detailed information of the SAP Business object "BUS1006" of the contact person.

Concept

Screenshots














Coding

GET_DETAIL

METHOD z_if_ia_ixa_intrexx_api~get_detail.

* ------ local data
	DATA: lv_org  TYPE bu_partner.
	DATA: lv_per  TYPE bu_partner.
	DATA: ls_data TYPE yixapi_demo_bapi_conr.
	DATA: ls_relation TYPE bapibus1006002_central.
	DATA: ls_central TYPE bapibus1006_central.
	DATA: ls_person TYPE bapibus1006_central_person.
	DATA: lt_return TYPE TABLE OF bapiret2.
	DATA: lv_error.
	DATA: lv_language TYPE spras.

* ------ set default
	ev_error = 'X'.
	cv_processed = 'X'.

* ------ check for new record
	IF iv_key EQ space OR iv_key EQ '-1'.
* ------ optional: set a default data structure and leave without errors
		EXIT.
	ELSE.
* ------ split key
		SPLIT iv_key AT '~' INTO lv_org lv_per.
* ------ check key
		CHECK lv_org NE space AND lv_per NE space.
	ENDIF.

* ------ get data relation
	CALL FUNCTION 'BAPI_BUPR_CONTP_GETDETAIL'
		EXPORTING
			businesspartner           = lv_org
			contactperson             = lv_per
		IMPORTING
*     VALIDFROMDATE             =
*     VALIDUNTILDATE            =
*     DEFAULTRELATIONSHIP       =
			centraldata               = ls_relation
		TABLES
			return                    = lt_return
			.
	LOOP AT lt_return TRANSPORTING NO FIELDS
		WHERE type CA 'EAX'.
		lv_error = 'X'.
		EXIT.
	ENDLOOP.
	CHECK lv_error NE 'X'.

* ------- get data BP
	CALL FUNCTION 'BAPI_BUPA_CENTRAL_GETDETAIL'
		EXPORTING
			businesspartner   = lv_per
			valid_date        = sy-datum
		IMPORTING
			centraldata       = ls_central
			centraldataperson = ls_person
		TABLES
			return            = lt_return.
	LOOP AT lt_return TRANSPORTING NO FIELDS
		WHERE type CA 'EAX'.
		lv_error = 'X'.
		EXIT.
	ENDLOOP.
	CHECK lv_error NE 'X'.

* -------- build transfer record
* 1. BAPI Info
	MOVE-CORRESPONDING ls_relation TO ls_data.
	MOVE-CORRESPONDING ls_central  TO ls_data.
	MOVE-CORRESPONDING ls_person   TO ls_data.

* 2. ID Info
	ls_data-org_id  = lv_org.
	ls_data-per_id  = lv_per.

* 3. Key Info
	CONCATENATE lv_org lv_per
		INTO ls_data-lid
		SEPARATED BY '~'.

* 4. generate additional text fields with type converting
*    get portal language
	CALL METHOD me->map_intrexx_language_to_sap
		EXPORTING
			iv_language = me->ix_control-ix_language
		IMPORTING
			ev_language = lv_language
		EXCEPTIONS
			not_found   = 1
			OTHERS      = 2. 
	IF sy-subrc <> 0. 
		lv_language = sy-langu. 
	ENDIF.
*  get department 
	IF ls_data-department NE space.
		SELECT SINGLE bez20 FROM tb911 INTO ls_data-text_abtnr  
			WHERE spras EQ lv_language   
				AND abtnr EQ ls_data-department. 
	ENDIF.

*  get function
	IF ls_data-function NE space.  
		SELECT SINGLE bez30 FROM tb913 INTO ls_data-text_pafkt    
			WHERE spras EQ lv_language  
				AND pafkt EQ ls_data-function. 
	ENDIF.

* -------- save for other API Methods
	me->current_data = ls_data.

* -------- build export
	CALL METHOD me->set_results_from_struc
		EXPORTING
			is_data         = ls_data
*    IT_REQUESTED    =
			iv_data_struc   = 'YIXAPI_DEMO_BAPI_CONR'
			iv_key_value    = ls_data-lid   
			iv_record       = 1   
			iv_struc_name   = 'DEFAULT' 
			iv_struc_record = 0  
		CHANGING
*    CT_KEYS         =
			ct_results      = et_result_values
		EXCEPTIONS 
			failed          = 1 
			OTHERS          = 2  
			.  
	IF sy-subrc <> 0. 
		EXIT.
	ENDIF.

* ------- finally OK result
	ev_error = ' '.

ENDMETHOD.

GET_LIST

METHOD z_if_ia_ixa_intrexx_api~get_list.

* -------------- local data
	DATA: lt_data TYPE TABLE OF yixapi_demo_bapi_conr.
	DATA: lt_data_int TYPE TABLE OF yixapi_demo_bapi_conr.
	DATA: ls_data TYPE yixapi_demo_bapi_conr.
	DATA: lt_return TYPE TABLE OF bapiret2.
	DATA: ls_filter TYPE LINE OF zia_ixa_api_intrexx_filter_t.
	DATA: lv_org TYPE bu_partner.  
	DATA: lv_key TYPE zia_ixa_fieldvalue.
	DATA: lv_error.
	DATA: lv_processed TYPE xfeld.
	DATA: lv_lin TYPE i.
	DATA: lt_rel TYPE TABLE OF bapibus1006_relations.
	DATA: ls_rel TYPE bapibus1006_relations.
	DATA: ls_orderby TYPE LINE OF zia_ixa_api_intrexx_orderby_t.
	DATA: lv_rows TYPE i.

* -------------- init
	cv_processed = 'X'.
	ev_error     = 'X'.

* -------------- get inbound parameters
	READ TABLE it_filter INTO ls_filter
		WITH KEY fieldname = 'ORG_ID'.
	IF sy-subrc NE 0.
		ev_error     = ' '.
		EXIT.
	ENDIF.
	lv_org = ls_filter-value_low.

* -------------- initial check routines
	IF lv_org IS INITIAL.
		ev_error     = ' '.
		EXIT.
	ENDIF.

* -------------- process
* 1. Search 
	CALL FUNCTION 'BAPI_BUPA_RELATIONSHIPS_GET' 
		EXPORTING  
			businesspartner = lv_org  
		TABLES   
			relationships   = lt_rel  
			return          = lt_return.  
	LOOP AT lt_return TRANSPORTING NO FIELDS  
		WHERE type CA 'EAX'.   
		lv_error = 'X'.  
		EXIT.  
	ENDLOOP. 
	CHECK lv_error NE 'X'.

* 2. check relations 
	DESCRIBE TABLE lt_rel LINES lv_lin. 
	CHECK lv_lin GT 0.

* 3. build data table 
	LOOP AT lt_rel INTO ls_rel   
		WHERE relationshipcategory  = 'BUR001'  
			AND validfromdate         LE sy-datum   
			AND validuntildate        GE sy-datum.
*   build key
		CONCATENATE ls_rel-partner1 
			ls_rel-partner2         
			INTO lv_key        
			SEPARATED BY '~'.
*   clear working var 
	CLEAR me->current_data.

*   build detail information; transfer via working var
	CALL METHOD me->z_if_ia_ixa_intrexx_api~get_detail
		EXPORTING  
			iv_key           = lv_key
*    IT_REQUESTED     =
*  IMPORTING
*    EV_ERROR         =
*    ET_MESSAGES      =
*    ET_RESULT_VALUES =
		CHANGING    
			cv_processed     = lv_processed 
		EXCEPTIONS    
		failed           = 1   
		OTHERS           = 2   
		. 
		IF sy-subrc EQ 0   
			AND lv_processed EQ 'X'  
			AND NOT me->current_data IS INITIAL.
*     append working var to table  
			APPEND me->current_data TO lt_data. 
		ENDIF.
	ENDLOOP.

* -------------- fill outbound parameters
* 1. ev_count 
	DESCRIBE TABLE lt_data LINES ev_count.
* 2. sort internal table
	DESCRIBE TABLE it_orderby LINES lv_lin.
	IF lv_lin EQ 1.   
		READ TABLE it_orderby INTO ls_orderby INDEX 1. 
		IF ls_orderby-ordertype EQ 'A'.  
			SORT lt_data BY (ls_orderby-fieldname) ASCENDING.   
		ELSE.   
			SORT lt_data BY (ls_orderby-fieldname) DESCENDING.  
		ENDIF. 
	ELSE.   
		SORT lt_data BY per_id. 
	ENDIF.

* 3. check offset access  
	IF iv_max_rows GT 0 OR iv_start_row GT 0.
*   move to a working tab   
		lt_data_int[] = lt_data.  
		REFRESH lt_data.

*   loop working tab 
	LOOP AT lt_data_int INTO ls_data.

*     check offset access   
			IF iv_start_row GT 0     
				AND sy-tabix LE iv_start_row.   
				CONTINUE.
			ENDIF.

*     append to exporting tab   
			APPEND ls_data TO lt_data.

*     check max rows    
			IF iv_max_rows GT 0.    
				ADD 1 TO lv_rows.      
				IF lv_rows GE iv_max_rows.  
					EXIT.     
				ENDIF. 
			ENDIF.

		ENDLOOP. 
	ENDIF.

* 4. loop and fill export 
	LOOP AT lt_data INTO ls_data.  
		CALL METHOD me->set_results_from_struc
			EXPORTING        is_data         = ls_data 
				it_requested    = it_requested   
				iv_data_struc   = 'YIXAPI_DEMO_BAPI_CONR'  
				iv_key_value    = ls_data-lid   
				iv_record       = sy-tabix  
				iv_struc_name   = 'DEFAULT'    
				iv_struc_record = 0     
			CHANGING      
				ct_keys         = et_result_keys  
				ct_results      = et_result_values   
			EXCEPTIONS
				failed          = 1   
				OTHERS          = 2.    
		IF sy-subrc EQ 0.
*     ignore 
		ENDIF.
	ENDLOOP.

* -------------- finally set no error
	ev_error    = ' '.

ENDMETHOD.

MODIFY

METHOD z_if_ia_ixa_intrexx_api~modify.

* ------ local data
	DATA: lv_org  TYPE bu_partner. 
	DATA: lv_per  TYPE bu_partner. 
	DATA: ls_data TYPE yixapi_demo_bapi_conr. 
	DATA: ls_datax TYPE yixapi_demo_bapi_conrx.
	DATA: ls_relation TYPE bapibus1006002_central. 
	DATA: ls_relation_x TYPE bapibus1006002_central_x. 
	DATA: ls_central TYPE bapibus1006_central.
	DATA: ls_central_x TYPE bapibus1006_central_x. 
	DATA: ls_person TYPE bapibus1006_central_person. 
	DATA: ls_person_x TYPE bapibus1006_central_person_x. 
	DATA: lt_return TYPE TABLE OF bapiret2. 
	DATA: ls_return TYPE bapiret2.
	DATA: lv_error.

* ------ set default
	ev_error = 'X'.
	cv_processed = 'X'.

* ------ get fields 
	CALL METHOD me->get_fields_from_struc 
		EXPORTING   
			it_fields         = it_fields
*    IV_RECORD         = '1'
*    IV_STRUC_NAME     = 'DEFAULT'
*    IV_STRUC_RECORD   = '0'   
			iv_data_strucname = 'YIXAPI_DEMO_BAPI_CONR'
			iv_convert        = 'X' 
		CHANGING    
			cs_data           = ls_data  
			cs_data_x         = ls_datax
		EXCEPTIONS     
			failed            = 1  
			OTHERS            = 2 
			. 
	IF sy-subrc <> 0.  
		EXIT. 
	ENDIF.

* ------ split key 
	IF iv_key CS '~'.
* ############################################### MODIFY
* existing record 
		SPLIT iv_key AT '~' INTO lv_org lv_per. 
		CHECK lv_org NE space AND lv_per NE space.

* prepare BAPI access   
		MOVE-CORRESPONDING ls_data TO ls_central.   
		MOVE-CORRESPONDING ls_datax TO ls_central_x.

			MOVE-CORRESPONDING ls_data TO ls_person. 
			MOVE-CORRESPONDING ls_datax TO ls_person_x.

			MOVE-CORRESPONDING ls_data TO ls_relation.  
			MOVE-CORRESPONDING ls_datax TO ls_relation_x.

* Change BAPI BP 
		IF NOT ls_central_x IS INITIAL   
			OR NOT ls_person_x IS INITIAL.    
			CALL FUNCTION 'BAPI_BUPA_CENTRAL_CHANGE' 
				EXPORTING        
					businesspartner     = lv_per   
					centraldata         = ls_central  
					centraldataperson   = ls_person      
					centraldata_x       = ls_central_x    
					centraldataperson_x = ls_person_x    
				TABLES    
					return              = lt_return.    
			LOOP AT lt_return TRANSPORTING NO FIELDS  
				WHERE type CA 'EAX'.     
				lv_error = 'X'.    
				EXIT.    
			ENDLOOP.   
			CHECK lv_error NE 'X'. 
		ENDIF.

* Change BAPI Relation   
		IF NOT ls_relation_x IS INITIAL.   
			CALL FUNCTION 'BAPI_BUPR_CONTP_CHANGE'   
				EXPORTING     
					businesspartner             = lv_org  
					contactperson               = lv_per
*     VALIDFROMDATE               =
*     VALIDUNTILDATE              =
*     DEFAULTRELATIONSHIP         =
*     DEFAULTRELATIONSHIP_X       = 
				centraldata                 = ls_relation 
				centraldata_x               = ls_relation_x 
			TABLES   
				return                      = lt_return    
				.    
			LOOP AT lt_return TRANSPORTING NO FIELDS 
				WHERE type CA 'EAX'.    
				lv_error = 'X'.      
				EXIT.   
			ENDLOOP. 
			CHECK lv_error NE 'X'.

			ev_key = iv_key.

		ENDIF.
	ELSE.
	* ############################################### INSERT
	*  check given business partner for org  
			lv_org = ls_data-org_id. 
			CHECK lv_org NE space.

*  prepare bapi data  
		MOVE-CORRESPONDING ls_data TO ls_central.
		MOVE-CORRESPONDING ls_data TO ls_person.  
		MOVE-CORRESPONDING ls_data TO ls_relation.

*  create business partner   
		CALL FUNCTION 'BAPI_BUPA_CREATE_FROM_DATA' 
			EXPORTING
*   BUSINESSPARTNEREXTERN              = 
				partnercategory                    = '1'
*   PARTNERGROUP                       = 
				centraldata                        = ls_central  
				centraldataperson                  = ls_person
*   CENTRALDATAORGANIZATION            =
*   CENTRALDATAGROUP                   =
*   ADDRESSDATA                        =
*   DUPLICATE_MESSAGE_TYPE             =
*   ACCEPT_ERROR                       = ' '  
			IMPORTING
				businesspartner           				= lv_per    
			TABLES     
				return                             = lt_return 
				.  
		LOOP AT lt_return TRANSPORTING NO FIELDS 
			WHERE type CA 'EAX'.     
			lv_error = 'X'.     
			EXIT.
		ENDLOOP.  
		CHECK lv_error NE 'X'.

		CHECK lv_per NE space.

*   create relation  
		CALL FUNCTION 'BAPI_BUPR_CONTP_CREATE'  
			EXPORTING     
				businesspartner              = lv_org      
				contactperson                = lv_per
*   VALIDFROMDATE                = '00010101'
*   VALIDUNTILDATE               = '99991231'
*   DEFAULTRELATIONSHIP          =
*   ADDRESSGUID                  = 
				centraldata                  = ls_relation
*   ADDRESSDATA                  =
*   DUPLICATE_MESSAGE_TYPE       =  
			TABLES
				return  				= lt_return
			.   
		LOOP AT lt_return TRANSPORTING NO FIELDS   
			WHERE type CA 'EAX'.     
			lv_error = 'X'.    
			EXIT. 
		ENDLOOP.  
		CHECK lv_error NE 'X'.

*   build key  
		CONCATENATE lv_org lv_per   
			INTO ev_key           
			SEPARATED BY '~'.

	ENDIF.

* ------------ final BAPI Commit 
	CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'  
		EXPORTING   
			wait   = 'X'  
		IMPORTING  
			return = ls_return.
	IF ls_return-type CA 'EAX'.  
		EXIT. 
	ENDIF.

* ------------ set finally OK 
	ev_error = ' '.

ENDMETHOD.

Test










7. Provide SAP documents externally

Providing SAP documents externally is a common requirement. This relates to, for example, scanned in incoming invoices or customer invoices that can be requested by the customer and provided to him electronically, e.g. as a PDF. A recommendation as to how this can be implemented technically is dependent on how the binary data for the requested document is physically saved in SAP. The following options are examples: At least the binary data, the document type and the physical length need to be available to the external called. This means that the documents need to be extractable as an internal table before they, prepared for an external caller, can leave the SAP system. In most cases, the related documents are those that are not physically stored in the SAP systembut in a content server (also knowledge provider), meaning in a special document management system (e.g. Docuware, ixOS). An SAP application that displays a scanned-in document to the SAP Business Object (e.g. incoming invoice) would only recognize the connections between the SAP Business Object and the binary document. Usually, the external document management system is instructed to display the document. In the more recent SAP ersions, this is organized using an http request. Theoretically, this could be exploited by an external caller by using this DMS server to actually deliver the document.

Provide documents from DMS externally

In the case that the requested documents are available in a document management system, the document could be referred to directly from the DMS via a generated URL. For this, the DMS must be available in the same place as where the document is available. Scenarios are commonly requested where external users should access the company-internal DMS. It should be clear in doing so, that potentially the most important server of a company (contracts and technical documentation is sometimes stored in the DMS) is released in the internet - which could mean a considerable security loophole. External users could therefore have access to documents that are actually a no-go for external access. You should therefore at least plan plan in enough time and costs for organizational activities and security measures (e.g. setting up a firewall). For this scenario, a handler would need to be developed that evaluates the externally requested research properties (e.g. customer number, date, tags), identifies the connection to potential documents and finally generates URLs where the documents are available externally. The connections can usually be found in the SAP system in the TOA* tables.

Replicate documents externally

This scenario assumes that the documents are available as an internal table in the ABAP. This would also mean that they are copyable. A current scenario would be copying the document on the file system of the external caller. Using the path information, the document would then be available externally (e.g. as an HTTP request when the document was replicated in the webspace of a web server). In this scenario, copies of the actual documents are generated. Depending on the size of the documents, network connection and other technical parameters, synchronous scenarios (request / extract document / replicate document) can become practically impossible. The scenario with replicating documents can be implemented very easily from the perspectie of the ABAP, if the documents are available as an internal table. The target paths can usually be mounted to the SAP application server or addressed (e.g. via transaction AL11) via network names (e.g. "\\webspace\outdocs"). Using the command "OPEN DATASER …TRANSFER", data can be written to this external directory, directly from SAP. If the misuse of such externally stored documents should also be prevented, the filenames can be alienated. A suitable method for this is the use of a Global Unique ID (GUID) as these are almost impossible to memorize. GUIDs can be generated with the functional module GUID_CREATE (i.e. as a 32 character string). The next step is to pack (e.g. as a ZIP file) the documents under password protection. On Windows-based SAP system, the well-known program WINZIP can be started from the command line (impulse transactions SM49, SM69; functional modules SAPXPG_START_XPG) to do this. You should consistently ensure that these replications are also deleted later. This can be implemented, for example, via an SAP batch job or via periodic scripts at the external caller (e.g. delete all files at 00:00).

Deliver documents asynchronously

The scenarios stated above demonstrate that synchronous scenarios may well be desirable but are sometimes not achievable from the organizational or technical perspective. Here, you should consider whether it would really cause a lot of problems to the requested process, if documents are available immediately. In many cases, it is enough if the process is changed from "Display document" to "Request document". The requested document is requested and delivered asynchronously. This can take place as a replicate in an external webspace or as an email. Both scenarios are very common. Sending the email can, for example, be triggered from SAP in a background process. The functional module SO_NEW_DOCUMENT_ATT_SEND_API1 is suitable for this.

Provide documents from the archive system via URL

The following example provides documents (SAP order confirmations or similar) externally via a link from the archive system. The generated URL here must also be accessible from externally. You also have the option of hiding the SAP-typical URL with another prefix and to put the externally visible prefix through to SAP via reverse proxying (see Apache documentation). To begin with, the coding identifies the relevant data records (customized table) from the extenally provided user code (e.g. SAP business partner number), and then checks the corresponding requests from the table VBAK. The URL to the document (if available) is then identified via an SAP function. For this function to work it is of course necessary that the archive function for the corresponding Business Objects (here: Order VBAK) is set up in the SAP Standard and documents (e.g. order confirmations) are available in the archive (print and store order confirmation). This method can also be used for other document types (e.g. delivery slips, bills). To do this, the corresponding archive-typical setup needs to have been made in SAP.
METHOD z_if_ia_ixa_intrexx_api~get_list.

* ---------- local data
	DATA: ls_filter LIKE LINE OF it_filter.
	DATA: lv_user TYPE bu_partner.
	DATA: lt_f4 TYPE /tsii/fr_f4_value_t.
	DATA: ls_f4 LIKE LINE OF lt_f4.
	DATA: lr_handler TYPE REF TO /tsii/cl_bl_bp_user.
	DATA: ls_data TYPE /tsii/exix_ixa_tr_dc_vbak.
	DATA: lt_data LIKE TABLE OF ls_data.
	DATA: lv_guid TYPE /tsii/fr_id_internal.
	DATA: lt_par TYPE /tsii/fr_parameter_t.
	DATA: ls_par LIKE LINE OF lt_par.
	DATA: ls_customizing TYPE /tsii/df_cust_scenario.
	DATA: lv_url TYPE string.

* --------- macros
	DEFINE append_par.
		clear ls_par.
		ls_par-param = &1. 
		ls_par-value = &2.
		append ls_par to lt_par.
	END-OF-DEFINITION.

* --------- init
	ev_error = ' '.
	cv_processed = 'X'.

* --------- check inbound parameter – get external user
	READ TABLE it_filter INTO ls_filter
		WITH KEY fieldname = 'USER'
		operand   = 'EQ'.
	IF sy-subrc NE 0.
		EXIT.
	ELSE.
* --------- add leading 0
		lv_user = ls_filter-value_low.
		CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
			EXPORTING
				input  = lv_user
			IMPORTING
				output = lv_user.
	ENDIF.

* ---------- get all orders (from table VBAK depending of another table)
	DATA: lt_iba TYPE TABLE OF /tsii/m_enpriba.
	DATA: lt_vbak TYPE TABLE OF vbak.
	DATA: ls_vbak TYPE vbak.

* ---------- get orders orderes by given user
	SELECT * FROM /tsii/m_enpriba
		INTO TABLE lt_iba
		WHERE basket_user EQ lv_user.
	CHECK NOT lt_iba[] IS INITIAL.

* ---------- get depending vbak record
	SELECT * FROM vbak
		INTO TABLE lt_vbak
		FOR ALL ENTRIES IN lt_iba
		WHERE vbeln = lt_iba-basket_id.
	CHECK NOT lt_vbak[] IS INITIAL.

* ---------- loop VBAK and fill export table with archive URL 
	DATA: lv_objid TYPE saeobjid.
	DATA: lt_url TYPE TABLE OF toauri.
	DATA: ls_url LIKE LINE OF lt_url.
	DATA: lv_lin TYPE i.
	DATA: lv_tabix TYPE sytabix.

	LOOP AT lt_vbak INTO ls_vbak.
		lv_tabix = sy-tabix.

*   prepare export table
		CLEAR ls_data.
		MOVE-CORRESPONDING ls_vbak TO ls_data.
		ls_data-user = lv_user.

*   get archive info
		lv_objid = ls_vbak-vbeln.
		REFRESH lt_url.
		CALL FUNCTION 'ARCHIVOBJECT_GET_URI'
			EXPORTING
				objecttype               = 'VBAK'
				object_id                = lv_objid
				location                 = 'B'
				http_url_only            = 'X'
			TABLES
				uri_table                = lt_url
			EXCEPTIONS
				error_archiv             = 1 
				error_communicationtable = 2
				error_kernel             = 3
				error_http               = 4
				error_dp                 = 5
				OTHERS                   = 6.
	IF sy-subrc EQ 0.
		DESCRIBE TABLE lt_url LINES lv_lin.
		IF lv_lin GE 1.
			READ TABLE lt_url INTO ls_url INDEX lv_lin.
			IF sy-subrc EQ 0. 
				ls_data-url = ls_url-uri.
			ENDIF.
		ENDIF.
	ENDIF.

*   optional replace the sap like URL with a extern available prefix
*   …

*   append record to export
		APPEND ls_data TO lt_data.

		sy-tabix = lv_tabix.
	ENDLOOP.

* ----------- sort
	DELETE lt_data WHERE url EQ space.
	SORT lt_data BY vbeln DESCENDING.

* ----------- loop and fill to final export parameter
	LOOP AT lt_data INTO ls_data.
		CALL METHOD me->set_results_from_struc
			EXPORTING
				is_data         = ls_data
*    it_requested    =
				iv_data_struc   = '/TSII/EXIX_IXA_TR_DC_VBAK'
				iv_key_value    = ls_data-vbeln
				iv_record       = sy-tabix
				iv_struc_name   = 'DEFAULT'
				iv_struc_record = 0
				iv_convert      = 'X'
			CHANGING
				ct_keys         = et_result_keys
				ct_results      = et_result_values
			EXCEPTIONS
				failed          = 1
				OTHERS          = 2
				.
	IF sy-subrc EQ 0.
			ADD 1 TO ev_count.
		ENDIF.
	ENDLOOP.

* ----------- set final
	ev_error     = ' '.

ENDMETHOD.