Using the Persistent Classes for BAPIs, Part 2
The part 1 explains, how to create generally persistent classes, basing on BAPIs. We have created a single persistent class on the example of SAP Business Partner. The objects of this persistent class can reading and saving updates of the partner central data.
In this part we have to model the partner central data in four persistent classes: the superclass Partner and its subclasses Person, Organization and Group. The functions of the classes are the same as in the part 1: read and save changes of the partner central data.
Persistent Classes for the Partner Central Data
Functional Class Model
The persistent subclasses CL_PERSON, CL_ORGANIZATION and CL_GROUP inherit primarly the mapping common attributes with their SET/GET methods from the superclass CL_PARTNER.
Persistent Class Model
The agent class of the superclass CL_PARTNER implements reading and saving logic for the partner central data. The agent class knows the subclasses of the superclass and creates the persistent objectes of them.
Public Methods of the Agent Class CA_PARTNER
- GET_PARTNER_REF – Get a Partner Persistent Object by the Partner Category
- GET_DB_CENTRAL_DATA – Get the Central Partner Data through BAPI
- SAVE_DB_CENTRAL_DATA – Save the Central Partner Data through BAPI
Implementation of the Persistent Classes
Mapping Structures (DDIC)
In addition to the main structure YSDN_BP_CENTRAL_DATA (see the part 1), each of the new persistent classes must have its own mapping structures:
- Structure for the superclass Partner
- Structure for the subclass Person
- Structure for the subclass Organization
- Structure for the subclass Group
Create the Persistent Classes
1. Create the persistent superclass for the partner central data
Map the structure YSDN_PARTNER_CENTRAL to the persistent class and define two fields PARTNER and VALID_FROM as business key and read only.
The others fields are to define as changeable value attributes.
2. Create the persistent subclass for the person central data
Map the structure YSDN_PERSON_CENTRAL to the persistent class, all fields of the structure are to define as changeable value attributes.
3. Create the persistent subclass for the organization central data
Map the structure YSDN_ORGANIZ_CENTRAL to the persistent class, all fields of the structure are to define as changeable value attributes.
4. Create the persistent subclass for the group central data
Map the structure YSDN_GROUP_CENTRAL to the persistent class, all fields of the structure are to define as changeable value attributes.
Extensions of the Agent Class (of the Super Class)
There are to define and to implement four new methods in the agent class:
- Method GET_DB_CENTRAL_DATA
Interface
Code
METHOD get_db_central_data.
DATA:
ls_central_data TYPE ysdn_bp_central_data,
lt_bapiret TYPE STANDARD TABLE OF bapiret2.
CALL FUNCTION ‘BAPI_BUPA_CENTRAL_GETDETAIL’
EXPORTING
businesspartner = i_partner
valid_date = i_valid_date
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 ).
ls_central_data-partner = i_partner.
IF ( ls_central_data-person IS NOT INITIAL ).
ls_central_data-category = ‘1’.
ELSEIF ( ls_central_data-organiz IS NOT INITIAL ).
ls_central_data-category = ‘2’.
ELSEIF ( ls_central_data-group IS NOT INITIAL ).
ls_central_data-category = ‘3’.
ELSE.
RETURN.
ENDIF.
MOVE-CORRESPONDING ls_central_data TO e_central_data.
ENDIF.
ENDMETHOD.
- Method SAVE_DB_CENTRAL_DATA
Interface
Code
METHOD save_db_central_data.
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_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 ).
MOVE-CORRESPONDING i_central_data TO ls_central_data_new.
* get the old partner data
yca_central_partner2=>agent->get_db_central_data(
EXPORTING
i_partner = ls_central_data_new-partner
i_valid_date = ls_central_data_new-valid_from
IMPORTING
e_central_data = ls_central_data_old
).
* 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_bairet.
ENDIF.
ENDMETHOD.
- Method GET_PARTNER_REF
Interface
Code
METHOD get_partner_ref.
DATA lv_partner_category TYPE bu_type.
CALL METHOD me->get_partner_category
EXPORTING
i_partner = i_partner
RECEIVING
r_partner_category = lv_partner_category
EXCEPTIONS
partner_not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
RAISE EXCEPTION TYPE cx_os_object_not_found.
ENDIF.
CASE lv_partner_category.
WHEN ‘1’.
r_partner_ref = yca_central_person2=>agent->get_persistent(
i_partner = i_partner
i_valid_from = i_valid_date
).
WHEN ‘2’.
r_partner_ref = yca_central_organiz2=>agent->get_persistent(
i_partner = i_partner
i_valid_from = i_valid_date
).
WHEN ‘3’.
r_partner_ref = yca_central_group2=>agent->get_persistent(
i_partner = i_partner
i_valid_from = i_valid_date
).
ENDCASE.
ENDMETHOD.
- Method GET_PARTNER_CATEGORY
Interface
Code
METHOD get_partner_category.
DATA:
ls_search_result TYPE bapibus1006_bp_addr,
lf_person TYPE bus000flds-char1,
lf_organiz TYPE bus000flds-char1,
lf_group TYPE bus000flds-char1.
CALL FUNCTION ‘BUP_PARTNER_TYPE_GET’
EXPORTING
i_partner = i_partner
IMPORTING
e_xorganisation = lf_organiz
e_xperson = lf_person
e_xgroup = lf_group
EXCEPTIONS
partner_not_found = 1
wrong_type = 2
wrong_parameters = 3
OTHERS = 4.
IF ( sy-subrc = 0 ).
CASE abap_true.
WHEN lf_person.
r_partner_category = ‘1’.
WHEN lf_organiz.
r_partner_category = ‘2’.
WHEN lf_group.
r_partner_category = ‘3’.
ENDCASE.
ENDIF.
IF ( r_partner_category IS INITIAL ).
RAISE partner_not_found.
ENDIF.
ENDMETHOD.
Redefine the Agent Methods the of Subclasses
The two methods are to redefine (in the same way) in each of the agent classes of the subclasses:
1. Method MAP_LOAD_FROM_DATABASE_KEY
METHOD map_load_from_database_key.
DATA:
ls_result LIKE LINE OF result,
ls_err_msg TYPE string.
FIELD-SYMBOLS <lfs_business_key> LIKE LINE OF i_business_key_tab.
LOOP AT i_business_key_tab ASSIGNING <lfs_business_key>.
yca_central_partner2=>agent->get_db_central_data(
EXPORTING
i_partner = <lfs_business_key>-partner
i_valid_date = <lfs_business_key>-valid_from
IMPORTING
e_central_data = ls_result
).
IF ( ls_result IS NOT INITIAL ).
APPEND ls_result TO result.
ELSE.
ls_err_msg = |Partner | && <lfs_business_key>-partner && | not found|.
RAISE EXCEPTION TYPE cx_os_db_select
EXPORTING
table = ‘CENTRAL_DATA’
textid = cx_os_db_select=>by_bkeytab
bkey = ls_err_msg.
ENDIF.
ENDLOOP.
ENDMETHOD.
2. Method MAP_SAVE_TO_DATABASE
METHOD map_save_to_database.
FIELD-SYMBOLS:
<lfs_update> LIKE LINE OF i_updates.
* save the updates
LOOP AT i_updates ASSIGNING <lfs_update>.
yca_central_partner2=>agent->save_db_central_data( <lfs_update> ).
ENDLOOP.
ENDMETHOD.
Test Report
*&———————————————————————*
*& Report YSDN_CENTRAL_PARTNER_TEST2
*&
*&———————————————————————*
*&
*&
*&———————————————————————*
REPORT ysdn_central_partner_test2.
TYPES oscon.
DATA:
lo_partner TYPE REF TO ycl_central_partner2,
lo_person TYPE REF TO ycl_central_person2,
lo_organiz TYPE REF TO ycl_central_organiz2,
lo_group TYPE REF TO ycl_central_group2,
lv_partner TYPE i,
ls_text TYPE string,
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 ” controll the LUWs by the local tranaction object
i_update_mode = oscon_dmode_direct ” perform database update immediately
).
START-OF-SELECTION.
IF ( partner IS NOT INITIAL ).
TRY.
lo_partner ?= yca_central_partner2=>agent->get_partner_ref(
i_partner = partner
i_valid_date = sy-datlo
).
lo_trans_mng = cl_os_system=>get_transaction_manager( ).
lo_trans = lo_trans_mng->create_transaction( ).
CASE lo_partner->get_category( ).
WHEN ‘1’.
lo_person ?= lo_partner.
ls_text = lo_person->get_firstname( ).
WRITE / ls_text.
” start the transaction for partner changes
lo_trans->start( ).
lo_person->set_firstname( lo_person->get_firstname( ) && ‘ test’ ).
” end the transaction, the method END() calls the BAPI for partner change eventually
lo_trans->end( ).
ls_text = lo_person->get_firstname( ).
WRITE / ls_text.
WHEN ‘2’.
lo_organiz ?= lo_partner.
ls_text = lo_organiz->get_name1( ).
WRITE / ls_text.
lo_trans->start( ).
lo_organiz->set_name1( lo_organiz->get_name1( ) && ‘ test’ ).
lo_trans->end( ).
ls_text = lo_organiz->get_name1( ).
WRITE / ls_text.
WHEN ‘3’.
lo_group ?= lo_partner.
ls_text = lo_group->get_namegroup1( ).
WRITE / ls_text.
lo_trans->start( ).
lo_group->set_namegroup1( lo_group->get_namegroup1( ) && ‘ test’ ).
lo_trans->end( ).
ls_text = lo_group->get_namegroup1( ).
WRITE / ls_text.
WHEN OTHERS.
WRITE ‘The partner category is unknown’.
RETURN.
ENDCASE.
CATCH cx_os_object_not_found.
lv_partner = partner.
ls_text = |{ lv_partner ZERO = NO }|.
WRITE: ‘The partner number ‘, ls_text , ‘ is not found’.
RETURN.
ENDTRY.
ENDIF.