Using the Persistent Classes for BAPIs, Part 1
This part explains the usage of persistent classes to the SAP (standard) BAPIs. To simplify matters, a single class will be created for the Business Partner Central Data, this class is used to read and change the existing business partners in a SAP System.
The next part Using the Persistent Classes for BAPIs, Part 2 explains how to create inheriting persistent classes based on the Business Partner Central Data.
Overview
ABAP Object Service
The ABAP Object Services provide global services for working with persistent objects within ABAP applications. The Object Services include:
- Persistence Service, used to manage persistent objects in the data repository
- Transaction Service, is based on the classical SAP transaction concept (SAP LUWs) and used to update the data repository
- Query Service, used for searching of persistent objects (like SQL statements).
The Class Builder provides the complete support for creating and maintaining of persistent classes.
The Class Builder generates for each persistent class SET and GET methods for all defined attributes. In addition, the Class Builder generates two further classes (Base and Agent), which are the class-specific part of the Persistence Service. The agent class manages the persistent objects at runtime. The medhods of the agent class can be mostly redefined. Besides of them, the agent class can be extended with new attributes, methodes etc.
More details to the Object Services under ABAP – Object Services
Standard BAPIs
The standard BAPIs (Business Application Programming Interface) allow an access to the defined SAP Business Objects. The SAP Business Objects with their BAPIs perpresent an object-oriented view of the business functions in a SAP System.
More details to the BAPIs under BAPI User Handbook
SAP Business Partner (BP)
The Business Object “Business Partner” can be used for the central management of business partners in a company for different business applications.
BAPIs for the Business Partner
BAPIs are remote-enabled function modules. The function group BUPA_3 contains all essential function modules for the management of the Business Partner:
The function module BAPI_BUPA_CENTRAL_GETDETAIL
This function module is used to read the central attributes (partner master data) of a business partner depending on the business partner category (organization, person or group of organizations or persons).
Importing parameter: partner number and valid date
Exporting parameter: common central data, partner category specific central data (organization, person or group)
The function module BAPI_BUPA_CENTRAL_CHANGE
This function module is used to change the central attributes of a business partner.
Create a persistent class for BP Central Data
Mapping Structure (DDIC)
.
A persistent class must have one or more references to the DDIC structures. These structures can be database tables, views or structures. The components of these structures can be then defined as attributes of the persistent class. For each attribute the Class Builder generates the access methods GET and SET.
- Mapping as database table or view: The Class Builder generates additionally to the GET/SET the SQL statements for the database access
- Mapping as structures: The database access methods must be implemented from developers themself
Since we have to use the database model of the Business Partner and its BADIs we must map a structure to the persistent class. The structure includes all central data structures defined in the function module as parameters.
In addition, the two fields are to define: the partner number and partner category.
The new structure for the persistent class
Create the Persistent Class
Create a persistent class in the Class Builder (The persistent class name must begin with <Y/Z>CL!):
After saving the persistent class we have three new classes in the Class Builder:
- YCL_CENTRAL_PARTNER – the persistent class
- YCB_CENTRAL_PARTNER – the base class for the agent class
- YCA_CENTRAL_PARTNER – the agent (actor) class for the YCL_CENTRAL_PARTNER
Mapping the Structure to the Persistent Plass YCL_CENTRAL_PARTNER
Pick the class YCL_CENTRAL_PARTNER in the Class Builder and click the button “Persistentce”:
Enter the structure name for the persistent class:
Define the two fields PARTNER and VALID_FROM of the structure as Business Key:
The remaining fields are to define as Value Attribute:
After saving the mapping structure and activating the persistent class and their agent (actor) class the Class Builder generates the SET/GET methods for all defined attributes.
The Class Builder adapts also the base and agent classes to the mapped structure type.
Redefine the Agent Class Methods
We have to redefine two agent class methods for reading and writing the cetral data from / to the BAPIs.
- Method MAP_LOAD_FROM_DATABASE_KEY loads persistent data by the business key from the data repository (through BAPI)
Code
METHOD map_load_from_database_key.
DATA:
ls_central_data TYPE ysdn_bp_central_data,
ls_result LIKE LINE OF result,
lt_bapiret TYPE STANDARD TABLE OF bapiret2.
FIELD-SYMBOLS <lfs_business_key> LIKE LINE OF i_business_key_tab.
LOOP AT i_business_key_tab ASSIGNING <lfs_business_key>.
CALL FUNCTION ‘BAPI_BUPA_CENTRAL_GETDETAIL’
EXPORTING
businesspartner = <lfs_business_key>-partner
valid_date = <lfs_business_key>-valid_from
IMPORTING
centraldata = ls_central_data-central
centraldataperson = ls_central_data-person
centraldataorganization = ls_central_data-organiz
centraldatagroup = ls_central_data-group
centraldatavalidity = ls_central_data-validity
TABLES
return = lt_bapiret.
IF ( lt_bapiret IS INITIAL ).
MOVE-CORRESPONDING ls_central_data TO ls_result.
ls_result-partner = <lfs_business_key>-partner.
IF ( ls_central_data-person IS NOT INITIAL ).
ls_result-category = ‘1’.
ELSEIF ( ls_central_data-organiz IS NOT INITIAL ).
ls_result-category = ‘2’.
ELSEIF ( ls_central_data-group IS NOT INITIAL ).
ls_result-category = ‘3’.
ELSE.
CONTINUE.
ENDIF.
APPEND ls_result TO result.
ENDIF.
ENDLOOP.
ENDMETHOD.
- Method MAP_SAVE_TO_DATABASE saves changes of persistent objects in the data repository (through BAPI)
Code
METHOD map_save_to_database.
TYPES BEGIN OF lty_partner_changes.
INCLUDE TYPE bapibus1006_central_x AS central.
INCLUDE TYPE bapibus1006_central_person_x AS person.
INCLUDE TYPE bapibus1006_central_organ_x AS organiz.
INCLUDE TYPE bapibus1006_central_group_x AS group.
TYPES END OF lty_partner_changes.
DATA:
lo_structdescr TYPE REF TO cl_abap_structdescr,
ls_central_data_old TYPE ysdn_bp_central_data,
ls_central_data_new TYPE ysdn_bp_central_data,
ls_partner_changes TYPE lty_partner_changes,
lt_bapiret TYPE STANDARD TABLE OF bapiret2.
FIELD-SYMBOLS:
<lfs_update> LIKE LINE OF i_updates,
<lfs_new> TYPE data,
<lfs_old> TYPE data,
<lfs_change> TYPE data,
<lfs_component> TYPE abap_compdescr.
lo_structdescr ?= cl_abap_structdescr=>describe_by_data( ls_partner_changes ).
LOOP AT i_updates ASSIGNING <lfs_update>.
CLEAR ls_partner_changes.
* move the new partner data
MOVE-CORRESPONDING <lfs_update> TO ls_central_data_new.
* get the partner old data
CALL FUNCTION ‘BAPI_BUPA_CENTRAL_GETDETAIL’
EXPORTING
businesspartner = ls_central_data_new-partner
valid_date = ls_central_data_new-valid_from
IMPORTING
centraldata = ls_central_data_old-central
centraldataperson = ls_central_data_old-person
centraldataorganization = ls_central_data_old-organiz
centraldatagroup = ls_central_data_old-group
centraldatavalidity = ls_central_data_old-validity
TABLES
return = lt_bapiret.
IF ( lt_bapiret IS INITIAL ).
* determine partner changes
LOOP AT lo_structdescr->components ASSIGNING <lfs_component>.
ASSIGN COMPONENT <lfs_component>-name OF STRUCTURE ls_central_data_new TO <lfs_new>.
IF sy-subrc <> 0.
CONTINUE.
ENDIF.
ASSIGN COMPONENT <lfs_component>-name OF STRUCTURE ls_central_data_old TO <lfs_old>.
IF sy-subrc <> 0.
CONTINUE.
ENDIF.
ASSIGN COMPONENT <lfs_component>-name OF STRUCTURE ls_partner_changes TO <lfs_change>.
IF sy-subrc <> 0.
CONTINUE.
ENDIF.
IF <lfs_new> NE <lfs_old>.
<lfs_change> = abap_true.
ENDIF.
ENDLOOP.
* save the partner changes
IF ( ls_partner_changes IS NOT INITIAL ).
CALL FUNCTION ‘BAPI_BUPA_CENTRAL_CHANGE’
EXPORTING
businesspartner = ls_central_data_new-partner
centraldata = ls_central_data_new-central
centraldataperson = ls_central_data_new-person
centraldataorganization = ls_central_data_new-organiz
centraldatagroup = ls_central_data_new-group
centraldata_x = ls_partner_changes-central
centraldataperson_x = ls_partner_changes-person
centraldataorganization_x = ls_partner_changes-organiz
centraldatagroup_x = ls_partner_changes-group
valid_date = ls_central_data_new-valid_from
TABLES
return = lt_bapiret.
ENDIF.
ENDIF.
ENDLOOP.
ENDMETHOD.
Test Report
*&———————————————————————*
*& Report YSDN_CENTRAL_PARTNER_TEST
*&
*&———————————————————————*
*&
*&
*&———————————————————————*
REPORT ysdn_central_partner_test.
TYPES oscon.
DATA:
lo_partner TYPE REF TO ycl_central_partner,
lo_trans_mng TYPE REF TO if_os_transaction_manager,
lo_trans TYPE REF TO if_os_transaction.
PARAMETERS partner TYPE bu_partner.
LOAD-OF-PROGRAM.
* set the transaction mode
cl_os_system=>init_and_set_modes(
i_external_commit = oscon_false
i_update_mode = oscon_dmode_direct
).
START-OF-SELECTION.
IF ( partner IS NOT INITIAL ).
lo_trans_mng = cl_os_system=>get_transaction_manager( ).
lo_trans = lo_trans_mng->create_transaction( ).
lo_trans->start( ).
TRY.
lo_partner = yca_central_partner=>agent->get_persistent(
i_partner = partner
i_valid_from = sy-datlo
).
CASE lo_partner->get_category( ).
WHEN ‘1’.
lo_partner->set_firstname( lo_partner->get_firstname( ) && ‘ test’ ).
WHEN ‘2’.
lo_partner->set_name1( lo_partner->get_name1( ) && ‘ test’ ).
WHEN ‘3’.
lo_partner->set_namegroup1( lo_partner->get_namegroup1( ) && ‘ test’ ).
WHEN OTHERS.
WRITE: ‘The partner category is unknown’.
ENDCASE.
CATCH cx_os_object_not_found.
WRITE: ‘The partner number ‘, partner, ‘ is not found’.
RETURN.
ENDTRY.
lo_trans->end( ).
ENDIF.
Hi Andreas,
nice idea and a nice blog about it.
It always annoys me that there is no OO access to such basic objects as BPs e.g. in SAP IS-U and everyone just does SELECT * FROM BUT000. I think I'll put this to action.
Looking forward for part 2 of the series.
Christian