Financial Management Blogs by Members
Dive into a treasure trove of SAP financial management wisdom shared by a vibrant community of bloggers. Submit a blog post of your own to share knowledge.
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member

Hello Folks,

I hope you are doing good.

A couple of days ago I came across a situation that is, a little bit, unusual. I was dealing with work statuses and locking on certain data regions.

In short, the scenario that I'm working on demands that a certain ENTITY owner locks several [VERSION,TIME] (VERSION is a CATEGORY dimension) combinations in one shot. Instead of letting him do this manually, I thought of using Script Logic.

I already knew that Script Logic would not contain a straightforward way to do this (I mean the NW SL has a reduced feature set from its MS counterpart, and the MS version couldn't do this directly so...), so I thought to myself: Why don't I use BAdI?

After a little digging inside the BW object explorer, I found the ABAP classes that manage the Work Statuses and I found a little example built-in with a sample program to test those classes right inside BW. What a jolly coincidence, thank you SAP!

I started copying and pasting the bits and pieces, modifying and shrinking the source to form just just what I needed.

I came up with the following code (Excuse my lousy coding, I met ABAP a week ago. Good thing it's object oriented!)

method IF_UJ_CUSTOM_LOGIC~EXECUTE.

******** Data and Type declarations

    TYPES: BEGIN OF t_dims,

            dimension   TYPE uj_dim_name,   " Dimension Name

            parameter   TYPE char20,        " Parameter Name

            modif_id    TYPE char04,        " Modification Group

            text_id     TYPE char20,        " Text(Label) Field

           END OF t_dims.

    DATA: user type UJ0_S_USER,

          user_id        TYPE uj0_s_user-user_id,

          gr_work_status_mgr type ref to CL_UJW_WORK_STATUS_MGR,

          lt_dim_mem TYPE ujw_t_dim_mem,

          ls_dim_mem LIKE LINE OF lt_dim_mem,

          gt_dims TYPE TABLE OF t_dims,

          gs_dims LIKE LINE OF gt_dims,

          gs_user TYPE uj0_s_user,

          appset_id      TYPE uja_appset_info-appset_id,

          incl_child     TYPE abap_bool,

          status         TYPE uj_status,

          gr_exception       TYPE REF TO cx_uj_static_check, "cx_ujw_work_status_error,

          ls_param TYPE ujk_s_script_logic_hashentry,

          l_log TYPE string,

          l_entity(32) TYPE c,

          l_time(32) TYPE c,

          l_status(32) TYPE c,

          l_version(32) TYPE c,

          application_id TYPE uja_appl-application_id.

    FIELD-SYMBOLS: <lv_member> TYPE ANY.

******** Since this is an implementation of the BADI_UJ_CUSTOM_LOGIC interface, I used the following parameters to get the Appset and the application IDs.

    appset_id = I_APPSET_ID.

    application_id = I_APPL_ID.

******** I hardcoded my user id just for testing purposes.

******** You can use an ABAP method that can get you the currently logged-on user. In fact this is what you should do!

    user_id = 'RIZKJ'.

    gs_user-USER_ID = user_id.

******** I do not want to include the children of the entity!

    incl_child = abap_false.

******** I started reading the parameters that will be passed from Script Logic:

    CLEAR ls_param.

    READ TABLE it_param WITH KEY hashkey = 'VERSION' INTO ls_param.

    IF sy-subrc NE 0.

    l_log = 'You have not specified the parameter ''VERSION'' which is required.'.

    cl_ujk_logger=>log( i_object = l_log ).

    RAISE EXCEPTION TYPE cx_uj_custom_logic.

    EXIT.

    ENDIF.

    l_version = ls_param-hashvalue.

    cl_ujk_logger=>log( i_object = l_version ).

    CLEAR ls_param.

    READ TABLE it_param WITH KEY hashkey = 'ENTITY' INTO ls_param.

    IF sy-subrc NE 0.

    l_log = 'You have not specified the parameter ''ENTITY'' which is required.'.

    cl_ujk_logger=>log( i_object = l_log ).

    RAISE EXCEPTION TYPE cx_uj_custom_logic.

    EXIT.

    ENDIF.

    l_entity = ls_param-hashvalue.

    cl_ujk_logger=>log( i_object = l_entity ).

    CLEAR ls_param.

    READ TABLE it_param WITH KEY hashkey = 'TIME' INTO ls_param.

    IF sy-subrc NE 0.

    l_log = 'You have not specified the parameter ''TIME'' which is required.'.

    cl_ujk_logger=>log( i_object = l_log ).

    RAISE EXCEPTION TYPE cx_uj_custom_logic.

    EXIT.

    ENDIF.

    l_time = ls_param-hashvalue.

    cl_ujk_logger=>log( i_object = l_time ).

    CLEAR ls_param.

    READ TABLE it_param WITH KEY hashkey = 'STATUS' INTO ls_param.

    IF sy-subrc NE 0.

    l_log = 'You have not specified the parameter ''STATUS'' which is required.'.

    cl_ujk_logger=>log( i_object = l_log ).

    RAISE EXCEPTION TYPE cx_uj_custom_logic.

    EXIT.

    ENDIF.

    l_status = ls_param-hashvalue.

    cl_ujk_logger=>log( i_object = l_status ).

********Here, we are reading the parameter that will contain the status. The status is a numerical code that is found in a table starting with "UJW_". Just search for it and you will find it!

    status = l_status.

******** Here, we are filling the dimension table that will contain the dimensions intersection that will be affected by the work status change.

      CLEAR ls_dim_mem.

      ls_dim_mem-dimension = 'MINING_ENTITY'.

      ASSIGN l_entity TO <lv_member>.

      ls_dim_mem-member = <lv_member>.

      APPEND ls_dim_mem TO lt_dim_mem.

      CLEAR ls_dim_mem.

      ls_dim_mem-dimension = 'TIME'.

      ASSIGN l_time TO <lv_member>.

      ls_dim_mem-member = <lv_member>.

      APPEND ls_dim_mem TO lt_dim_mem.

      CLEAR ls_dim_mem.

      ls_dim_mem-dimension = 'VERSION'.

      ASSIGN l_version TO <lv_member>.

      ls_dim_mem-member = <lv_member>.

      APPEND ls_dim_mem TO lt_dim_mem.

******** And this is where the magic happens! We instantiate the gr_work_status_mgr object with a factory object builder (nice use of design patterns!)

    gr_work_status_mgr = cl_ujw_work_status_mgr=>factory(

                               is_user   = gs_user

                               i_appset  = appset_id ).

******** And we call the method that will change the work status!

    TRY.

      gr_work_status_mgr->update_work_status_locks(

            EXPORTING

              i_applid        = application_id

              it_dim_mem      = lt_dim_mem

              i_incl_children = incl_child

              i_status        = status         ).

      MESSAGE  text-023 TYPE 'S'.

      CATCH cx_uj_static_check INTO gr_exception.

******** I caught the exception and did absolutely nothing with it! You should not! Log it or something...

    ENDTRY.

ENDMETHOD.

You have to excuse my fascination, I'm still relatively new to ABAP and I was surprised that it had incorporated some of the features of more modern programming languages. I was expecting something hideous like COBOL! (With all my excuses to all the COBOL advocates)

There are some comments that need to be put in place:

  • First: you can observe that this method is an implementation of the BADI_UJ_CUSTOM_LOGIC Business Add-In. This is necessary so you can call the method from Script Logic.
  • Second: In order to make the code available to Script Logic, you have to create a filter for the BAdI implementation. Let's suppose that you named the filter Z_LOCK_WS.

Now to call the code from Script Logic, you have to create a new Logic Script! Name it whatever you like and put inside the following piece of script:

*START_BADI Z_LOCK_WS

QUERY = OFF

WRITE = OFF

ENTITY = E100

TIME = 2012.01

VERSION = ACTUAL

*END_BADI

You can call this method multiple times for more than one intersection. You can even use a FOR loop and some data manager variables to call this for multiple intersections at once. In example:

*FOR %CURRENT_MONTH% = $MY_MONTHS$

*START_BADI Z_LOCK_WS

QUERY = OFF

WRITE = OFF

ENTITY = E100

TIME = %CURRENT_MONTH%

VERSION = FORECAST1

*END_BADI

*NEXT

This took me quite a bit to figure out and I hope it will be useful for some. All comments are welcome!

Have a great time,

Joseph.

10 Comments