Lets checkout the ABAP object oriented approach for reports when you want to get data from different data sources – Database and/or Archive .
Introduction
Almost all clients use archiving to control the primary DB size and to make sure it doesn’t grow too big. If primary DB would be big, it would have its own performance impact. But this not the topic for this article. In this article, I want to give you a pattern which you can follow in your developments where you have more than one data source – Database and Archive.
In this example, we would take PBS as the archive add-on as example. But, in reality you can implement this approach in any multiple data selection.
Report Requirement
This report is very basic report to display data from DB as well as archive. The selection screen has other reporting criteria along with these options:
As name suggest, the data can be selected from DB, archive or both
Procedural Design
In simple procedural design, this report selection would be using the IF conditions to restrict the selection based on the selected option. It is not necessarily an issue, but this design can be modified to be more modular, following more design principles, etc.
I’m providing only the part where there is a data selection and also there is different logic.
* Block 1 of selection screen SELECTION-SCREEN BEGIN OF BLOCK block1 WITH FRAME TITLE text-001. SELECT-OPTIONS : s_vendor FOR v_vendor. SELECTION-SCREEN END OF BLOCK block1. * Display Data Retrieval Options SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE text-049. PARAMETERS: p_rb_all TYPE c RADIOBUTTON GROUP rd2, p_rb_arc TYPE c RADIOBUTTON GROUP rd2 , p_rb_db TYPE c RADIOBUTTON GROUP rd2 DEFAULT 'X'. SELECTION-SCREEN END OF BLOCK b2. START-OF-SELECTION. IF p_rb_db = 'X' OR p_rb_all = 'X'. SELECT ebeln bukrs bsart lifnr waers submi INTO TABLE i_ekko FROM ekko WHERE lifnr IN s_vendor[]. ENDIF. IF p_rb_ar = 'X' OR p_rb_all = 'X'. DATA: tab93 TYPE STANDARD TABLE OF ekko. DATA: ls_tab93 LIKE LINE OF tab93. DATA: ls_ekko LIKE LINE OF i_ekko. CALL FUNCTION '/PBS/SELECT_INTO_TABLE' EXPORTING archiv = 'CMM' OPTION = " tabname = 'EKKO' clr_itab = 'X' schl1_name = 'LIFNR' TABLES i_tabelle = tab93 schl1_in = s_vendor[] EXCEPTIONS eof = 4 OTHERS = 2. LOOP AT tab93 INTO ls_tab93. MOVE ls_tab93-ebeln TO ls_ekko-ebeln . MOVE ls_tab93-bukrs TO ls_ekko-bukrs . MOVE ls_tab93-bsart TO ls_ekko-bsart . MOVE ls_tab93-lifnr TO ls_ekko-lifnr . MOVE ls_tab93-waers TO ls_ekko-waers . MOVE ls_tab93-submi TO ls_ekko-submi . APPEND ls_ekko TO i_ekko . ENDLOOP. DESCRIBE TABLE i_ekko LINES sy-tfill. IF sy-tfill GT 0. sy-subrc = 0. ENDIF. ENDIF. IF p_rb_db = 'X' OR p_rb_all = 'X'. SELECT ekpo~ebeln ekpo~ebelp ekpo~matnr ekpo~bukrs ekpo~werks ekpo~menge ekpo~netwr ekkn~ps_psp_pnr eket~eindt ekpo~mwskz ekpo~loekz INTO TABLE i_ekpo FROM ekpo JOIN ekkn ON ( ekpo~ebeln = ekkn~ebeln AND ekpo~ebelp = ekkn~ebelp ) JOIN eket ON ( ekpo~ebeln = eket~ebeln AND ekpo~ebelp = eket~ebelp ) FOR ALL ENTRIES IN i_ekko WHERE ekpo~ebeln EQ i_ekko-ebeln. ENDIF. IF p_rb_ar = 'X' OR p_rb_all = 'X'. "use same PBS FM to get the data from EKPO, EKKN, EKET ENDIF. "Vendor name selection "fill up final table "display data in ALV
Object Oriented Approach
To avoid the IF conditions and to have separate classes for the different data sources, I use these design. This design is very much dependent on the Decorator Design Pattern. If you are not yet familiar with decorator, I suggest you make yourself familiar with decorator before continue reading here.
The design is based on following idea:
- Create the class for the primary data selection.
- Using this class, inherit classes for each data source.
- At time of instantiating the object, establish the decorator relationship
- Within the methods which are redefined, call the decorator methods.
- Get back the data from decorator objects into the primary data object.
Here you are not fully using the decorator design pattern. But, you can if you have more than couple different data-sources.
Another problem I’m facing is to make sure same data selection doesn’t get reselected over and over
Redesigned Code Lines
Again, this is smaller version of the original program with only relevant parts. You can create the full blown solution using ABAP Object Oriented Approach for Reports – Redesign
* CLASS zcl_cda_db DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING io_next TYPE REF TO zcl_cda_db OPTIONAL. METHODS: get_data. PROTECTED SECTION. TYPES: tt_ekko TYPE STANDARD TABLE OF ty_ekko, tt_ekpo TYPE STANDARD TABLE OF ty_ekpo. METHODS: select_ekko, select_ekpo_ekkn, merge_data, select_vendor_names, fill_final_table. DATA: i_ekko TYPE tt_ekko, i_ekpo TYPE tt_ekpo. DATA: o_decorator TYPE REF TO zcl_cda_db. ENDCLASS. "zcl_cda_db DEFINITION * CLASS zcl_cda_arch DEFINITION INHERITING FROM zcl_cda_db. PUBLIC SECTION. METHODS: constructor IMPORTING io_next TYPE REF TO zcl_cda_db OPTIONAL. PROTECTED SECTION. METHODS: select_ekko REDEFINITION, select_ekpo_ekkn REDEFINITION. ENDCLASS. "zcl_cda_arch DEFINITION **__SELECTION-SCREEN_____________________________________________________* DATA: v_vendor TYPE ekko-lifnr. * Block 1 of selection screen SELECTION-SCREEN BEGIN OF BLOCK block1 WITH FRAME TITLE text-001. SELECT-OPTIONS : s_vendor FOR v_vendor. SELECTION-SCREEN END OF BLOCK block1. * Display Data Retrieval Options SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE text-049. PARAMETERS: p_rb_all TYPE c RADIOBUTTON GROUP rd2, p_rb_arc TYPE c RADIOBUTTON GROUP rd2 , p_rb_db TYPE c RADIOBUTTON GROUP rd2 DEFAULT 'X'. SELECTION-SCREEN END OF BLOCK b2. **__START-OF-SELECTION_________________________________________________* START-OF-SELECTION. DATA: o_data TYPE REF TO zcl_cda_db. DATA: lo_data_a TYPE REF TO zcl_cda_arch. IF p_rb_db = 'X'. CREATE OBJECT o_data. ENDIF. IF p_rb_arc = 'X'. CREATE OBJECT o_data TYPE zcl_cda_arch. ENDIF. IF p_rb_all = 'X'. CREATE OBJECT lo_data_a. CREATE OBJECT o_data EXPORTING io_next = lo_data_a. ENDIF. o_data->get_data( ). * CLASS zcl_cda_db IMPLEMENTATION. * METHOD constructor. o_decorator = io_next. ENDMETHOD. "constructor * METHOD get_data. " data from data source me->select_ekko( ). me->select_ekpo_ekkn( ). " merge data from decorator objects into here me->merge_data( ). "Always from primary data source me->select_vendor_names( ). "fill up the final table me->fill_final_table( ). ENDMETHOD. "get_Data * METHOD select_ekko. SELECT ebeln bukrs bsart lifnr waers submi INTO TABLE me->i_ekko FROM ekko WHERE lifnr IN s_vendor[]. CHECK o_decorator IS BOUND. o_decorator->select_ekko( ). ENDMETHOD. "select_ekko * METHOD select_ekpo_ekkn. SELECT ekpo~ebeln ekpo~ebelp ekpo~matnr ekpo~bukrs ekpo~werks ekpo~menge ekpo~netwr ekkn~ps_psp_pnr eket~eindt ekpo~mwskz ekpo~loekz INTO TABLE me->i_ekpo FROM ekpo JOIN ekkn ON ( ekpo~ebeln = ekkn~ebeln AND ekpo~ebelp = ekkn~ebelp ) JOIN eket ON ( ekpo~ebeln = eket~ebeln AND ekpo~ebelp = eket~ebelp ) FOR ALL ENTRIES IN i_ekko WHERE ekpo~ebeln EQ i_ekko-ebeln. CHECK o_decorator IS BOUND. o_decorator->select_ekpo_ekkn( ). ENDMETHOD. "select_ekpo_ekkn * METHOD merge_data. CHECK o_decorator IS BOUND. APPEND LINES OF: o_decorator->i_ekko TO me->i_ekko, o_decorator->i_ekpo TO me->i_ekpo. ENDMETHOD. "merge_data * METHOD select_vendor_names. "get NAME1 from LFA1 for all entries in I_EKKO ENDMETHOD. * METHOD fill_final_Table. "move data from all tables into final table for display ENDMETHOD. ENDCLASS. "zcl_cda_db IMPLEMENTATION * CLASS zcl_cda_arch IMPLEMENTATION. * METHOD constructor. super->constructor( io_next ). ENDMETHOD. "constructor * METHOD select_ekko. DATA: tab93 TYPE STANDARD TABLE OF ekko. DATA: ls_tab93 LIKE LINE OF tab93. DATA: ls_ekko LIKE LINE OF me->i_ekko. CALL FUNCTION '/PBS/SELECT_INTO_TABLE' EXPORTING archiv = 'CMM' OPTION = " tabname = 'EKKO' clr_itab = 'X' schl1_name = 'LIFNR' TABLES i_tabelle = tab93 schl1_in = s_vendor[] EXCEPTIONS eof = 4 OTHERS = 2. LOOP AT tab93 INTO ls_tab93. MOVE ls_tab93-ebeln TO ls_ekko-ebeln . MOVE ls_tab93-bukrs TO ls_ekko-bukrs . MOVE ls_tab93-bsart TO ls_ekko-bsart . MOVE ls_tab93-lifnr TO ls_ekko-lifnr . MOVE ls_tab93-waers TO ls_ekko-waers . MOVE ls_tab93-submi TO ls_ekko-submi . APPEND ls_ekko TO me->i_ekko . ENDLOOP. DESCRIBE TABLE me->i_ekko LINES sy-tfill. IF sy-tfill GT 0. sy-subrc = 0. ENDIF. ENDMETHOD. "select_ekko METHOD select_ekpo_ekkn. "similarly select the data from PBS "for the tables EKPO, EKET, EKKN ENDMETHOD. "select_ekpo_ekkn ENDCLASS. "zcl_cda_arch IMPLEMENTATION
When RB_ALL is selected and primary DB object is being instantiated
When method SELECT_EKKO is being called
Do let me know your thoughts in the comments.
No comments:
Post a Comment