Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
renish
Explorer

Hi all,

This blog is about BW Hierarchies. Ever since S4 was introduced, managing hierarchies have got also simplified via S4 Fiori App called "Manage Global Hierarchies". These Global hierarchies have been maintained/stored differently in S4, and as a result, extraction in BW have also changed via CDS extractors. We also have older types of hierarchies in addition, which means typically BW system have 3 types of hierarchies from now onwards. In the below blog, I will try to explain extraction, flattening them in BW by their types and other miscellaneous requirements achieved via coding.

    1. Type of hierarchies

 

    1. Flattening of hierarchies

 

    1. Manipulation for legacy cost centers hierarchies

 

    1. Merging hierarchies SKFs and GL accounts



 

Topic 1 : Types of hierarchies

There are 3 types of hierarchies in BW.

Hierarchy Type 1 : Standard hierarchies (ECC and S4). These hierarchies for different objects are captured in different TCODEs.

Hierarchy Type 2 : Set hierarchies – based on T-codes GS01/GS02/GS03 (ECC and S4). Please refer below blog links by Bindu Priya for set in ECC/S4 and its extraction in BW system.

https://blogs.sap.com/2012/05/02/custom-hierarchy-extraction-in-sap-bw-73-part1/

https://blogs.sap.com/2012/08/09/custom-hierarchy-extraction-in-sap-bw-73-part2/

https://blogs.sap.com/2012/08/10/custom-hierarchy-extraction-in-sap-bw-73-part3/

https://launchpad.support.sap.com/#/notes/134975

  

 

Standard and Set Hierarchy in BW TCODE RSH1


In above both Hierarchy case, Hierarchy Node are stored in 0HIER_NODE InfoObject. To load the hierarchies node text, same Standard SAP Hierarchy extractors can be used by selecting the Text Segments. 0HIER_NODE in RSH1 is shown as Folder by system.

 

Hierarchy Node text


Similarly, in Set Hierarchy, TEXT Segment of BW07 extractor will extract texts from maintained TEXT in GS01/GS02/GS03.

 

Hierarchy Type 3.   Global hierarchies (S4) -  Hierarchies for different objects are captured in single Fiori app called Manage Global Hierarchies. Backend tables are HRRP* in S4. Now if you check the difference in RSH1 where Hierarchy Node is now InfoObject specific (i.e. 0GLACCHIENT for 0GL_ACCOUNT). CDS extractor is  given by SAP to load  text for 0GLACCHIENT separately. (For many of FI InfoObjects, SAP has given standard contents. If not provided by SAP then it is very similar code for all other Hierarchy Objects because of central HRRP* tables for all hierarchy, requires to change the WHERE condition(s) in Hierarchy CDS code of extractor). 0GLACCHIENT is shown in RSH1 by system is just like InfoObject.

 

 

Global Hierarchy in BW TCODE RSH1


 

How to extract and load global hierarchies in BW is described in below blog by simon.kranig.

https://blogs.sap.com/2019/12/20/cds-based-data-extraction-part-iii-miscellaneous/

 

 

Topic 2 : Flattening of hierarchies

In below example of hierarchies flattening, it is fixed levels of hierarchies are up to 10. There must be business confirmation on how many levels they are maintaining in source side.

If the InfoObject is having more than one hierarchies, below solution will take care of all such hierarchies. e.g. If the 0GL_ACCOUNT has 3 hierarchy namely BS, PL and SalesCOGSMargin then all these 3 hierarchies will get flattened in CM layer aDSO. There is Identification field 'HIENM' has been added in CM layer aDSO. This identification field help to store multiple hierarchies in same aDSO dynamically so no hard-coding or separate processing required for individual hierarchy flattening. Where as DW layer aDSO will have HIENM, GL Account/Last level and Chart Of accounts as Key fields.

Look for the detailing in the comment of End routine code for Standard hierarchy and Global hierarchy specific tables and fields

2.1 Flattening of Standard / Set hierarchy. Here I am using TEXT DataSource as starting point of TRFN. I have stored the Key and Text of all levels of Hierarchy nodes. so the aDSO will have one column for storing Key and one column for storing text of node.

 

Standard / Set Hierarchy Flattening TRFN

 

 

End routine



 

METHOD GLOBAL_END.



     FIELD-SYMBOLS:

       <RESULT_FIELDS>    TYPE _ty_s_TG_1.



  DATA: MONITOR_REC     TYPE rstmonitor.



* Note the _M class are not considered for DTP execution.

* ABAP Breakpoints must be set in the generated program instead



* ABAP Breakpoints within an ABAP End-Routine must be set

* in the _A class if the transformation runtime is set to SAP HANA!



**** begin of routine - insert your code only below this line       ****





**********************************************************************

** Hierarchy flattening will happen in CM layer which is Staging aDSO inbound queue only

** Hierarchy logic is Columns sequence sensitive

** If you change aDSO type, columns sequence will get changed

** Also, 1. If you load DTP frequently, data will get duplicated in CM layers

**       2. If frequent delete and load happens, data won’t be available for join until load finished

** Because of above reasons, introduced DW layer which will prevent above problems (Standard aDSO with write changelog type)

** Only DW layer will be used in Joining in CalcViews



** Don't change HANA Runtime to ABAP Runtime

** Impact : ABAP Runtime will add REQTSN and DATAPAKID as a column in the internal table

**          Sequence of the Columns shifts by 2 (2 extra columns added in _ty_t_tg_1 at runtime)

**          below code needs to adjust --> lv_rollup_col_num = 6 + lv_count.  Instead of 6, it will be 8 if ABAP runtime



** Tables required in Hierarchy flattening

** 1. rshiedir - for Hierarchy directory

** 2. /bi0/hgl_account - InfoObject specific hierarchy

** 3. rsthiernode - Hierarchy node text (In case of backend /Standard hierarchy)

** OR

** 3. /bi0/tglacchient - InfoObject specific hierarchy node text (In case global hierarchy)



** Misc Documentation

**          https://wiki.scn.sap.com/wiki/display/BI/BW+Hierarchy+Tables

**          https://blogs.sap.com/2019/12/20/cds-based-data-extraction-part-iii-miscellaneous/



**********************************************************************



... "insert your code here

data:   lt_hiernodes type standard table of /bi0/hgl_account, " hierarchy table of InfoObject

         lt_nodetexts type standard table of rsthiernode,

         ls_hiernodes like line of lt_hiernodes,

         ls_nodetexts like line of lt_nodetexts,

         lt_result_pkg type _ty_t_tg_1,

         ls_result_pkg like line of lt_result_pkg,

         lv_hierid type rshieid,

         lv_account type rsiobjnm,

         lv_levels type i,

         lv_count type i,

         lv_rollup_col_num type i,

         lv_rollup_col(10),

         lv_curr_col_name type i,

         lv_curr_col type i,

         lv_prev_col_name type i,

         lv_prev_col type i,

         lv_next_col_name type i,

         lv_next_col type i.







types : begin of ty_rshiedir,

        hieid type rshieid,

        objvers type rsobjvers,

        hienm type rshienm,

        iobjnm type rsiobjnm,

        end of ty_rshiedir.



data : wa_rshiedir type ty_rshiedir,

       it_rshiedir type standard table of ty_rshiedir.



field-symbols: <fs_account> like line of lt_hiernodes,

                <fs_hiernodes> like line of lt_hiernodes,

                <fs_nodetexts> like line of lt_nodetexts,

                <fs_rollup> type any,

                <fs_rollup_name> type any,

                <fs_curr_col> type any,

                <fs_curr_col_name> type any,

                <fs_next_col> type any,

                <fs_next_col_name> type any,

                <fs_prev_col> type any,

                <fs_prev_col_name> type any.







** get the Standard hierarchies of InfoObject and get unique hierarchies

** below Inner join will ensure only Standard Hierarchies are getting processed

** If the Hierarchy Name is found in the tables rshiedir and rsthiernode, it means these are standard/Set hierarchies



select a~hieid a~objvers a~hienm a~iobjnm

from rshiedir as a

inner join rsthiernode as b

on a~hieid = b~hieid

into table it_rshiedir

where a~objvers = 'A' and a~iobjnm = '0GL_ACCOUNT'.



sort it_rshiedir by hieid.

delete adjacent duplicates from it_rshiedir comparing hieid.



* loop for number of hierarchy

loop at it_rshiedir into wa_rshiedir.



 " Get nodes (Hierarchy Node & G/L Accounts) based on Hierarchy ID



      select *

           from /bi0/hgl_account

           into table lt_hiernodes

           where hieid = wa_rshiedir-hieid.





* Get the Node descriptions



           select *

           from rsthiernode

           into table lt_nodetexts

           where hieid = wa_rshiedir-hieid .



        sort lt_nodetexts by nodename.



	loop at result_package assigning <result_fields>.



* GL account is compounded to Chart of Account



 concatenate <result_fields>-chrt_accts <result_fields>-lv09 into lv_account.

      sort lt_hiernodes by nodename.

* If G/L Account is available in the hierarchy

      read table lt_hiernodes

           with key nodename = lv_account

           into ls_hiernodes

           binary search.

      if sy-subrc = 0.

        sort lt_hiernodes by nodeid.

        read table lt_hiernodes

           with key nodeid = ls_hiernodes-parentid

           assigning <fs_hiernodes>

           binary search.



          ls_result_pkg-chrt_accts = <result_fields>-chrt_accts.

          ls_result_pkg-hienm =  wa_rshiedir-hienm.

          ls_result_pkg-lv09 = <result_fields>-lv09.

          ls_result_pkg-lv09_name = <result_fields>-lv09_name.



          ls_result_pkg-lv08 = <fs_hiernodes>-nodename.



          read table lt_nodetexts

          with key nodename = <fs_hiernodes>-nodename

          assigning <fs_nodetexts>

          binary search.

          if sy-subrc eq 0.

          ls_result_pkg-lv08_name = <fs_nodetexts>-txtlg.

          endif.



* Leaf and immediate parent node information is already captured in above logic

* So 2 levels of nodes are handled

* Calculate remaining levels of hierarchy nodes



           lv_levels = ls_hiernodes-tlevel - 2. " calculate remaining levels

           lv_count = 2.



* We need 10 levels

             do 10 times.

                  read table lt_hiernodes

                  with key nodeid = <fs_hiernodes>-parentid

                  assigning <fs_hiernodes>.

                      if sy-subrc <> 0.

                         exit.

                      endif.

* After leaf and Parent nodes, the next level starts at 5 and then 7, 9..

* Get the Cell(Column x Row) of ls_result_pkg and assign the value of Node and Node text

* always verify the column number from where the Rollup1 is starting then adjust the variable value lv_rollup_col_num



                 lv_rollup_col_num = 6 + lv_count.



                 assign component lv_rollup_col_num of structure ls_result_pkg  to  <fs_rollup>.

                   <fs_rollup> = <fs_hiernodes>-nodename.



                 lv_rollup_col_num = lv_rollup_col_num + 1.

                  assign component lv_rollup_col_num of structure ls_result_pkg  to  <fs_rollup_name>.



                  read table lt_nodetexts

                   with key nodename = <fs_hiernodes>-nodename

                   assigning <fs_nodetexts>

                   binary search.

                   <fs_rollup_name> = <fs_nodetexts>-txtlg.

                lv_count = lv_count + 2.



            enddo.



*** added by Renish to shift values in columns if the current column is blank

*** 1st col is REQTSN, 2nd col is RECORDMODE, 3rd col is CHRT_ACCTS.... 24th (last) col is HIENM

*** structure of ls_result_pkg is same as /BIC/AZFIMD_C017

*** above mentioned col sequence is used in below do-while loop





    clear : lv_curr_col, lv_prev_col_name, lv_prev_col .

    lv_curr_col_name = 23 .

    do 9 times.



        lv_curr_col =  lv_curr_col_name - 1 .

        lv_prev_col_name = lv_curr_col_name - 2 .

        lv_prev_col = lv_curr_col_name - 3 .



        assign component lv_curr_col_name of structure ls_result_pkg  to <fs_curr_col_name>.

        assign component lv_curr_col of structure ls_result_pkg  to <fs_curr_col>.





        while <fs_curr_col_name> is initial. " keep moving the values till curr_col or curr_col_name is filled



            assign component lv_prev_col_name of structure ls_result_pkg  to <fs_prev_col_name>.

            assign component lv_prev_col of structure ls_result_pkg  to <fs_prev_col>.



            move <fs_prev_col_name> to <fs_curr_col_name>.

            move <fs_prev_col> to <fs_curr_col>.

            <fs_prev_col_name> = ''.

            <fs_prev_col> = ''.



            lv_prev_col_name = lv_prev_col_name - 2 .

            lv_prev_col = lv_prev_col - 2 .



            if  lv_prev_col_name le 3.

                exit.  " once column reached at CHRT_ACCTS (i.e. column number 3), exit from shifting loop

            endif.



        endwhile.



     lv_curr_col_name = lv_curr_col_name - 2 .



    enddo.





*** Fill up the blank columns with lowest node and node name

    clear : lv_curr_col_name, lv_next_col_name, lv_next_col .

    lv_curr_col = 4 .

    do 9 times.



        lv_curr_col_name =  lv_curr_col + 1 .

        lv_next_col = lv_curr_col + 2 .

        lv_next_col_name = lv_curr_col + 3 .





        assign component lv_curr_col of structure ls_result_pkg  to <fs_curr_col>.

        assign component lv_curr_col_name of structure ls_result_pkg  to <fs_curr_col_name>.



        while <fs_curr_col_name> is initial. " keep copying the value



            assign component lv_next_col_name of structure ls_result_pkg  to <fs_next_col_name>.

            assign component lv_next_col of structure ls_result_pkg  to <fs_next_col>.



                 move <fs_next_col> to <fs_curr_col> .

                 move <fs_next_col_name> to <fs_curr_col_name> .



                lv_next_col = lv_next_col + 2 .

                lv_next_col_name = lv_next_col_name + 2 .





        endwhile.



        lv_curr_col = lv_curr_col + 2 .



    enddo.



*** end of added by Renish to shift values in columns if the current column is blank



      append ls_result_pkg to lt_result_pkg.

      clear: ls_result_pkg, ls_hiernodes.



    endif.

endloop. " loop at result_package assigning <result_fields>.



endloop. " loop at it_rshiedir into wa_rshiedir.



    refresh result_package.







    result_package[] = lt_result_pkg[].

**** end of routine - insert your code only before this line        ****

ENDMETHOD.

 


 

2.2  Flattening of Global hierarchy. Here I am using TEXT DataSource as starting point of TRFN

 

Global Hierarchy Flattening TRFN


 

 

End routine


 

 

METHOD GLOBAL_END.



     FIELD-SYMBOLS:

       <RESULT_FIELDS>    TYPE _ty_s_TG_1.



  DATA: MONITOR_REC     TYPE rstmonitor.



* Note the _M class are not considered for DTP execution.

* ABAP Breakpoints must be set in the generated program instead



* ABAP Breakpoints within an ABAP End-Routine must be set

* in the _A class if the transformation runtime is set to SAP HANA!



**** begin of routine - insert your code only below this line       ****





**********************************************************************

** Hierarchy flattening will happen in CM layer which is Staging aDSO inbound queue only

** Hierarchy logic is Columns sequence sensitive

** If you change aDSO type, columns sequence will get changed

** Also, 1. If you load DTP frequently, data will get duplicated in CM layers

**       2. If frequent delete and load happens, data won’t be available for join until load finished

** Because of above reasons, introduced DM layer which will prevents above problems

(Standard aDSO with write changelog type)

** Only DM layer will be used in Joining in CalcViews



** Don't change HANA Runtime to ABAP Runtime

** Impact: ABAP Runtime will add REQTSN and DATAPAKID as a column in the internal table

**          Sequence of the Columns shifts by 2 (2 extra columns added in _ty_t_tg_1 at runtime)

**          below code needs to adjust --> lv_rollup_col_num = 6 + lv_count.  Instead of 6, it will be 8 if ABAP runtime



** Tables required in Hierarchy flattening

** 1. rshiedir - for Hierarchy directory

** 2. /bi0/hgl_account - InfoObject specific hierarchy

** 3. rsthiernode - Hierarchy node text (In case of backend /Standard hierarchy)

** OR

** 3. /bi0/tglacchient - InfoObject specific hierarchy node text (In case global hierarchy)



** Misc Documentation

**          https://wiki.scn.sap.com/wiki/display/BI/BW+Hierarchy+Tables

**          https://blogs.sap.com/2019/12/20/cds-based-data-extraction-part-iii-miscellaneous/

**********************************************************************



... "insert your code here

data:   lt_hiernodes type standard table of /bi0/hgl_account,  " hierarchy table of InfoObject

         lt_nodetexts type standard table of /bi0/tglacchient, " text table of hierarchy nodes

         ls_hiernodes like line of lt_hiernodes,

         ls_nodetexts like line of lt_nodetexts,

         lt_result_pkg type _ty_t_tg_1,

         ls_result_pkg like line of lt_result_pkg,

         lv_hierid type rshieid,

         lv_account type rsiobjnm,

         lv_levels type i,

         lv_count type i,

         lv_rollup_col_num type i,

         lv_rollup_col(10),

         lv_curr_col_name type i,

         lv_curr_col type i,

         lv_prev_col_name type i,

         lv_prev_col type i,

         lv_next_col_name type i,

         lv_next_col type i,

         v_pattern type c length 1 value '',

         v_hier_id type c length 60,

         v_hier_node type c length 60,

         v_node_name type c length 60.







types : begin of ty_rshiedir,

        hieid type rshieid,

        objvers type rsobjvers,

        hienm type rshienm,

        iobjnm type rsiobjnm,

        end of ty_rshiedir.



data : wa_rshiedir type ty_rshiedir,

       it_rshiedir type standard table of ty_rshiedir.



field-symbols: <fs_account> like line of lt_hiernodes,

                <fs_hiernodes> like line of lt_hiernodes,

                <fs_nodetexts> like line of lt_nodetexts,

                <fs_rollup> type any,

                <fs_rollup_name> type any,

                <fs_curr_col> type any,

                <fs_curr_col_name> type any,

                <fs_next_col> type any,

                <fs_next_col_name> type any,

                <fs_prev_col> type any,

                <fs_prev_col_name> type any.





** get the Global hierarchies of InfoObject and get unique hierarchies

** below Inner join will ensure only Global Hierarchies are getting processed

** If the Hierarchy Name is found in the tables rshiedir and /bi0/tglacchient, it means these are global hierarchies



select a~hieid a~objvers a~hienm a~iobjnm

from rshiedir as a

inner join /bi0/tglacchient as b

on a~hienm = b~glacchieid

into table it_rshiedir

where a~objvers = 'A' and a~iobjnm = '0GL_ACCOUNT'.



sort it_rshiedir by hieid.

delete adjacent duplicates from it_rshiedir comparing hieid.



* loop for number of hierarchy

loop at it_rshiedir into wa_rshiedir.



 " Get nodes (Hierarchy Node & G/L Accounts) based on Hierarchy ID



      select *

           from /bi0/hgl_account          " hierarchy table of InfoObject

           into table lt_hiernodes

           where hieid = wa_rshiedir-hieid.



* Get the Node descriptions

   select *

      from /bi0/tglacchient            " text table of hierarchy nodes

      into table lt_nodetexts

      where glacchieid = wa_rshiedir-hienm .

      sort lt_nodetexts by glacchieid glacchient.



	loop at result_package assigning <result_fields>.



* GL account is compounded to Chart of Account



 concatenate <result_fields>-chrt_accts <result_fields>-lv09 into lv_account.



          ls_result_pkg-chrt_accts = <result_fields>-chrt_accts.

          ls_result_pkg-hienm =  wa_rshiedir-hienm.

          ls_result_pkg-lv09 = <result_fields>-lv09.

          ls_result_pkg-lv09_name = <result_fields>-lv09_name.



* If G/L Account is available in the hierarchy

      sort lt_hiernodes by nodename.

      read table lt_hiernodes

           with key nodename = lv_account

           into ls_hiernodes

           binary search.

      if sy-subrc = 0.

        sort lt_hiernodes by nodeid.

        read table lt_hiernodes

           with key nodeid = ls_hiernodes-parentid

           assigning <fs_hiernodes>

           binary search.



          if sy-subrc eq 0.

            ls_result_pkg-lv08 = <fs_hiernodes>-nodename.

            condense ls_result_pkg-lv08.

            clear : v_hier_id , v_hier_node.

            split ls_result_pkg-lv08 at v_pattern into v_hier_id v_hier_node.

            ls_result_pkg-lv08 = v_hier_node.



          " /bi0/tglacchient has column 'glacchieid' as Hierarchy ID && column 'glacchient' as node

          " e.g. glacchieid = 'FINR'   glacchient = '0F001'

          " whereas /bi0/hgl_account has column 'nodename' as concatenation of hierarchy ID and node

          " e.g. nodename = 'FINR                                      0F009'



          " check above table values for few sample node, it will clear the doubts of condensing and splitting the node into two variables for reading internal table



          read table lt_nodetexts

          with key

           glacchieid = wa_rshiedir-hienm

           glacchient = ls_result_pkg-lv08

          assigning <fs_nodetexts>

          binary search.



          if sy-subrc eq 0.

          ls_result_pkg-lv08_name = <fs_nodetexts>-txtlg.

          endif.

         endif.



* Leaf and immediate parent node information is already captured in above logic

* So 2 levels of nodes are handled

* Calculate remaining levels of hierarchy nodes



           lv_levels = ls_hiernodes-tlevel - 2. " calculate remaining levels

           lv_count = 2.



* As per agreement with business, there will be max 10 levels

             sort lt_hiernodes by nodeid.

             do 10 times.

                  read table lt_hiernodes

                  with key nodeid = <fs_hiernodes>-parentid

                  assigning <fs_hiernodes>.

                      if sy-subrc <> 0.

                         exit.

                      endif.

* After leaf and Parent nodes, the next level starts at 5 and then 7, 9..

* Get the Cell(Column x Row) of ls_result_pkg and assign the value of Node and Node text

* always verify the column number from where the Rollup1 is starting then adjust the variable value lv_rollup_col_num



                 lv_rollup_col_num = 6 + lv_count.



                 assign component lv_rollup_col_num of structure ls_result_pkg  to  <fs_rollup>.

                  condense <fs_hiernodes>-nodename.

                  v_node_name = <fs_hiernodes>-nodename.

                  clear : v_hier_id , v_hier_node.

                  split v_node_name at v_pattern into v_hier_id v_hier_node.

                  <fs_rollup> = v_hier_node.



                 lv_rollup_col_num = lv_rollup_col_num + 1.

                 assign component lv_rollup_col_num of structure ls_result_pkg  to  <fs_rollup_name>.





          read table lt_nodetexts

          with key

           glacchieid = wa_rshiedir-hienm

           glacchient = <fs_rollup>

          assigning <fs_nodetexts>

          binary search.



          if sy-subrc eq 0.

          <fs_rollup_name> = <fs_nodetexts>-txtlg.

          endif.





                lv_count = lv_count + 2.



            enddo.



*** added by Renish to shift values in columns if the current column is blank

*** 1st col is REQTSN, 2nd col is RECORDMODE, 3rd col is CHRT_ACCTS.... 24th (last) col is HIENM

*** structure of ls_result_pkg is same as /BIC/AZFIMD_C017

*** above mentioned col sequence is used in below do-while loop





    clear : lv_curr_col, lv_prev_col_name, lv_prev_col .

    lv_curr_col_name = 23 .

    do 9 times.



        lv_curr_col =  lv_curr_col_name - 1 .

        lv_prev_col_name = lv_curr_col_name - 2 .

        lv_prev_col = lv_curr_col_name - 3 .



        assign component lv_curr_col_name of structure ls_result_pkg  to <fs_curr_col_name>.

        assign component lv_curr_col of structure ls_result_pkg  to <fs_curr_col>.





        while <fs_curr_col_name> is initial. " keep moving the values till curr_col or curr_col_name is filled



            assign component lv_prev_col_name of structure ls_result_pkg  to <fs_prev_col_name>.

            assign component lv_prev_col of structure ls_result_pkg  to <fs_prev_col>.



            move <fs_prev_col_name> to <fs_curr_col_name>.

            move <fs_prev_col> to <fs_curr_col>.

            <fs_prev_col_name> = ''.

            <fs_prev_col> = ''.



            lv_prev_col_name = lv_prev_col_name - 2 .

            lv_prev_col = lv_prev_col - 2 .



            if  lv_prev_col_name le 3.

                exit.  " once column reached at CHRT_ACCTS (i.e. column number 3), exit from shifting loop

            endif.



        endwhile.



     lv_curr_col_name = lv_curr_col_name - 2 .



    enddo.





*** Fill up the blank columns with lowest node and node name

    clear : lv_curr_col_name, lv_next_col_name, lv_next_col .

    lv_curr_col = 4 .

    do 9 times.



        lv_curr_col_name =  lv_curr_col + 1 .

        lv_next_col = lv_curr_col + 2 .

        lv_next_col_name = lv_curr_col + 3 .





        assign component lv_curr_col of structure ls_result_pkg  to <fs_curr_col>.

        assign component lv_curr_col_name of structure ls_result_pkg  to <fs_curr_col_name>.



        while <fs_curr_col_name> is initial. " keep copying the value



            assign component lv_next_col_name of structure ls_result_pkg  to <fs_next_col_name>.

            assign component lv_next_col of structure ls_result_pkg  to <fs_next_col>.



                 move <fs_next_col> to <fs_curr_col> .

                 move <fs_next_col_name> to <fs_curr_col_name> .



                lv_next_col = lv_next_col + 2 .

                lv_next_col_name = lv_next_col_name + 2 .





        endwhile.



        lv_curr_col = lv_curr_col + 2 .



    enddo.



*** end of added by Renish to shift values in columns if the current column is blank



      append ls_result_pkg to lt_result_pkg.

      clear: ls_result_pkg, ls_hiernodes.



    endif.

endloop. " loop at result_package assigning <result_fields>.



endloop. " loop at it_rshiedir into wa_rshiedir.



    refresh result_package.







    result_package[] = lt_result_pkg[].

**** end of routine - insert your code only before this line        ****

ENDMETHOD.

 


 

Below is how I am ensuring the data loads of GL Accounts are including hierarchy flattening is working via process chain.

 

 

 

Process chain sequencing


 

 

 

Topic 3 : Manipulation for legacy cost centers hierarchies

As part of the project requirement, it was decided by business to accommodate legacy Cost Centers and it’s transactions in BW side directly. To bring these legacy costcenters from S4 side, there must be masterdata created for those many costcenters. It was huge manual task for S4 team to create and maintain those legacy costcenters. Instead S4 team have only created the nodes in Global Hierarchy without creating actual costcenters. now it was BW team’s responsibility to manipulate those nodes and treat those nodes as costcenters.

Highlighted Legacy costcenters are maintained as Folder in S4 side.

 

Cost Center Hierarchy in S4

 

 

Cost Center Hierarchy in S4 - Legacy cost centers maintained as Folder


 

 

End Routine in Transformation written for handling Legacy Cost Centers


 

 

 

METHOD GLOBAL_END.



     FIELD-SYMBOLS:

       <RESULT_FIELDS_1>    TYPE _ty_s_TG_1,

       <RESULT_FIELDS_2>    TYPE _ty_s_TG_2,

       <RESULT_FIELDS_3>    TYPE _ty_s_TG_3,

       <RESULT_FIELDS_4>    TYPE _ty_s_TG_4,

       <RESULT_FIELDS_5>    TYPE _ty_s_TG_5,

       <RESULT_FIELDS_6>    TYPE _ty_s_TG_6.



  DATA: MONITOR_REC     TYPE rstmonitor.



* Note the _M class are not considered for DTP execution.

* ABAP Breakpoints must be set in the generated program instead



* ABAP Breakpoints within an ABAP End-Routine must be set

* in the _A class if the transformation runtime is set to SAP HANA!



**** begin of routine - insert your code only below this line       ****





... "insert your code here



** Legacy CostCenters are not created in S4 system.

** So in S4 system, they cannot be part of Leaf Node in Hierarchy.

** Instead creating legacy CostCenters in S4, Folders are created with EXACT Legacy CostCenter names at hierarchy level 6 in cost center hierarchy.

** below logic will convert Folders into Leaf Nodes (Folders are getting converted to actual EXACT CostCenters)



** Segment 3 holds actual Hierarchy Structure

** Segment 3 is stores in internal table result_package_3 for TRFN



** If the Folder name i.e. costchient is Legacy CostCenters

** assign them to Costcenter

** also change type from Folder to CostCenter

** Folder identification FIELDNM = HIERARCHYNODE

** Leaf Node / CostCenter identification FIELDNM = COSTCENTER



** Include all the Legacy CostCenters which are maintained as Folder in XXXCCHIERXXX hierarchy.



loop at result_package_3 assigning <RESULT_FIELDS_3>.



if  <result_fields_3>-costchieid = 'H101/1000/XXXCCHIERXXX'.



       if <result_fields_3>-costchient eq '0204010001'

         or <result_fields_3>-costchient eq '0204010002'

         or <result_fields_3>-costchient eq '0204010003'

         or <result_fields_3>-costchient eq '0204010004'

         or <result_fields_3>-costchient eq '0204010005'

         or <result_fields_3>-costchient eq '0204010006'.

       " or <result_fields_3>-costchient is number ?





         <result_fields_3>-costcenter = <result_fields_3>-costchient.  " assign folder name to costcenter

         <result_fields_3>-h_iobjnm = '0COSTCENTER'.  " change Folder type to CostCenter

       endif.  " end for legacy CostCenters check



    endif.  "end for <result_fields_3>-costchieid = '1000/H101/1000/ XXXCCHIERXXX' check

endloop.



**** end of routine - insert your code only before this line        ****

ENDMETHOD.

 


Above end routine manipulation of hierarchy node for legacy cost centers, they are shown in BW side as actual costcenters. Attributes and Texts of these legacy cost centers can be loaded by FILE based extractrors for historical data reporting.

 

Legacy Cost Center result in RSH1


 

Topic 4 : Merging Hierarchies in BW

Sometimes, there are requirement like combining the two different objects hierarchy in One object (e.g. Standard FSV object like 0GLACCEXT. Though SAP has given standard extractor for it, but what in case of no standard extractor by SAP).

In Oracle, there is similar object named as “OMR Account” which is combination of GL Costing accounts and SKF for headcount costing. This OMR Account is not compounded to any field(s). Therefore Chart Of accounts is not mapped while loading data from Costing accounts to OMR Accounts.

Loading sequence would be:

    1. GL account Hierarchy

 

    1. SKF Hierarchy



 

Business has to create the GL Hierarchy having Node which is same as SKF hierarchy. Here in my case it is “TSKF”. This "TSKF" node will not have any nodes inside. It is blank placeholder.

 

GL PnL Account Hierarchy


SKF Hierarchy is “TSKF” which will get merge with GL hierarchy

 

 

SKF Hierarchy for Headcounts


 

TRFN with GL account hierarchy, load as is in BW side. Only DTP should be restricted with Hierarchy ID. Here in my case, it is H109/<CHART_OF_ACCOUNT>/TTOM

 

Transformation mapping - GL Costing Accounts


 

While in TRFN with SKF, make the OMR Hierarchy ID as constant which is in my case H109/<CHART_OF_ACCOUNT> /TTOM

 

 

Transformation mapping - SKF headcounts


 

DTP settings while updating SKF hierarchy. Update Mode must be “Update Subtree”.

And change Hierarchy Name to as GL Hierarchy which is H109/<CHART_OF_ACCOUNT> /TTOM.

Also, Hierarchy ID restriction/filter for SKF in extraction tab is H104/<CONTROLLIN_AREA>/TSKF

 

DTP for SKF - setting while merging hierarchies


 

1 Comment
Labels in this area