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:
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.