The standard Workflow inbox delivered by SAP Master Data Governance is very generic, since it does not contain any business data (like Material attributes). Luckily we can change this.
The MDG Inbox uses the Suite Inbox (CA-EPT-IBO) or Lean Workflow Inbox as a basis. This is basically a WebDynpro application that uses a POWL List to display Workitems. While the application offers Workflow-specific features not found in the standard POWL application (e.g. substitution settings for Workflow), it is driven by a specialization of the POWL feeder.
We implement a new Query by deriving a new ABAP Class from the SAP MDG Standard one. First the SAP Standard fetches the assigned Workitems and standard fields (like priority, CR status, …), then we add the business data (here: Material).
1. DDIC Structure & Table Type
In SE11, create new DDIC structure and table types describing your result structure. The structure must contain the base fields of the MDG inbox in structure USMD_S_CREQUEST_POWL. Use a named INCLUDE so that you have easier access to the Material fields in your ABAP coding later on. I include the Material structure /MDGMM/_S_MM_PP_MATERIAL generated by MDG-M, i.e. all fields of the Type1 entity MATERIAL will be available for the end user.
2. ABAP Class for Query
Create a new ABAP class derived from CL_USMD_CREQUEST_POWL, the standard Inbox feeder. Overwrite the following methods:
- SET_MV_RESULTS: Set me->mv_results to the name of your result table type
- SET_MV_RESULTSTRUCTURE: Set me->mv_resultstructure to the name of your result structure
- CONSTRUCTOR: Copy the code from the super Constructor into this method
(for ABAP internal reasons, the Constructor does not execute the code in your overwritten methods as you might expect. It’s in the documentation, so you cannot complain, and I for once am not half as good in explaining such things as Mr. ABAP himself)
3. Register the new POWL application
Using transaction POWL_COCKPIT, you create a new POWL application, query type (this references our ABAP class), query, and finally register your query to the application. See the POWL documentation for details.
4. Create WebDynpro configurations
Now we need WebDynpro application and component configurations that start the Suite Inbox application IBO_WDA_INBOX with our new POWL list:
- Copy the application configuration USMD_CREQUEST_POWL into customer namespace & edit it
- Copy & edit the component configuration of IBO_WDC_INBOX. Change the parameter applid to the name of your newly created POWL application
- (Optional) Copy & edit the component configuration of POWL_UI_COMP. This allows you to modify the look&feel of the POWL result table.
- Assign the newly created component configurations in the application configuration created above
- (Optional) From transaction POWL_QUERY, define a standard ALV layout for the result table, e.g. which columns are being displayed initially.
5. ABAP code for reading Material data
At last, some real coding (You didn’t think you could just customize this together, did you?! 😉 ). In this code, we first let the MDG standard fetch the Workitem information, then we add the Material data using theMaster Data Governance Application Programming Interface.
The code uses some tricks for enhancing the performance that are applicable to MDG programming as a whole:
- Use concrete DDIC types whenever possible
- Reduce the MDG API calls to the bare minimum, i.e. it is better to do more work in your own code than to call the API. For instance, in the code below, instead of invoking the MDG API from within the LOOP (n calls), I prepare a list of Material numbers and invoke the API only once.
First display is pretty slow (>1.5s), as the MDG API initialization (CL_USMD_GOV_API=>GET_INSTANCE())alone adds 0.5s to the start-up time. 😯
METHOD if_powl_feeder~get_objects. "Let Standard fetch & fill basic fields CALL METHOD super->if_powl_feeder~get_objects EXPORTING i_username = i_username i_applid = i_applid i_type = i_type i_selcrit_values = i_selcrit_values i_langu = i_langu i_visible_fields = i_visible_fields IMPORTING e_results = e_results e_messages = e_messages e_workflow_result_count = e_workflow_result_count. IF e_results IS INITIAL. RETURN. ENDIF. "Cast result into real type FIELD-SYMBOLS: <workitems> TYPE y0mm_mat_ui_t_ibo_creq_mat. ASSIGN e_results TO <workitems>. "Create mapping table workItem --> CR DATA(lt_wi_crequest) = cl_usmd_wf_crequest_mapper=>get_crequest_by_wi( it_wi = VALUE #( FOR <wi> IN <workitems> ( <wi>-wi_id ) ) ). "Get MDG GOV API DATA: lo_mdg_api TYPE REF TO if_usmd_gov_api. TRY . lo_mdg_api = cl_usmd_gov_api=>get_instance( iv_model_name = cl_mdg_bs_mat_c=>gc_usmd_model ). CATCH cx_usmd_gov_api. RETURN. "Some error, so we show only vanilla worklist ENDTRY. "Get list of (first) Material in each CR DATA: lt_material_keys TYPE SORTED TABLE OF /mdgmm/_s_mm_kf_material WITH UNIQUE KEY material. TYPES: BEGIN OF ty_wi2material, wi_id TYPE y0mm_mat_ui_s_ibo_creq_mat-wi_id, material TYPE /mdgmm/_s_mm_kf_material-material, END OF ty_wi2material. DATA: lt_wi2material TYPE HASHED TABLE OF ty_wi2material WITH UNIQUE KEY wi_id. LOOP AT <workitems> ASSIGNING FIELD-SYMBOL(<workitem>). "Get CR for that Workitem READ TABLE lt_wi_crequest ASSIGNING FIELD-SYMBOL(<wi2crequest>) WITH TABLE KEY wi_id = <workitem>-wi_id. IF sy-subrc <> 0. CONTINUE. ENDIF. TRY . "Get object list of that CR lo_mdg_api->get_object_list( EXPORTING iv_crequest_id = <wi2crequest>-usmd_crequest IMPORTING et_object_list_db_style = DATA(lt_object_list) " Change Request, Entity, Table Type ). "Is Material entity in CR? READ TABLE lt_object_list ASSIGNING FIELD-SYMBOL(<ent_material>) WITH KEY usmd_crequest = <wi2crequest>-usmd_crequest usmd_entity = cl_mdg_bs_mat_c=>gc_entity_name_mat. IF sy-subrc <> 0. CONTINUE. ENDIF. "Get Material key into key table (conversion!) INSERT VALUE #( material = <ent_material>-usmd_value ) INTO TABLE lt_material_keys ASSIGNING FIELD-SYMBOL(<material>). "Store association workItem -> material INSERT VALUE #( wi_id = <workitem>-wi_id material = <material>-material ) INTO TABLE lt_wi2material. CATCH cx_usmd_gov_api. "Ignore errors, just let add-on data fields empty in output CONTINUE. ENDTRY. ENDLOOP. IF lt_material_keys IS INITIAL. RETURN. "No CRs in list, nothing to add ENDIF. "Read all Materials from MDG API (Only 1 call for performance reasons!) DATA: lt_materials TYPE HASHED TABLE OF /mdgmm/_s_mm_pp_material WITH UNIQUE KEY material. lo_mdg_api->retrieve_entity( EXPORTING iv_crequest_id = VALUE #( ) "Initial CR, means read all iv_entity_name = cl_mdg_bs_mat_c=>gc_entity_name_mat "Material it_key = lt_material_keys "Material in current CR IMPORTING et_data = lt_materials " Entity Keys and Attributes ). IF lt_materials IS INITIAL. RETURN. "No Materials, nothing to add ENDIF. "Add Material information to Change Requst Work Item List LOOP AT <workitems> ASSIGNING <workitem>. "Get material_id by workitem_id READ TABLE lt_wi2material WITH TABLE KEY wi_id = <workitem>-wi_id ASSIGNING FIELD-SYMBOL(<wi2material>). IF sy-subrc <> 0. CONTINUE. ENDIF. "Get Material data into WorkItem list READ TABLE lt_materials WITH TABLE KEY material = <wi2material>-material INTO <workitem>-yy_material. ENDLOOP. ENDMETHOD.
6. Test it
You can invoke your new MDG-M Inbox by starting the Suite Inbox with the newly created configuration. The URL should look something like this:
7. Inbox customizing
You might have realized that the Suite Inbox is showing all Workitems from all workflows and that the MDG specific buttons (e.g. “Process request”) are not working. This is due to missing customizing settings, that SAP delivers for the MDG Inbox. The customizing is specific to the POWL applicationID, which is of course different for our own Inbox.
You can copy over the settings made by SAP (in system tables) into customizing tables. There are some Customizing transactions for this in SPRO, but I entered it directly. SM30 for the customizing table, SE16 for the system tables, as well as Copy&Paste are your friends in this task.
|IBO_C_WF_TA_P_SC||IBO_C_WF_TA_P_TY||Tasks to show in Inbox. Leave empty to see all tasks of all workflows in system.|
|IBO_C_WF_ACC||IBO_C_WF_ACS||Action types for the Inbox actions: Describes how a navigation event triggered by one of the Inbox buttons is evaluated by the Inbox, e.g. via OBN or a function module handler.|
|IBO_C_WF_TAC||IBO_C_WF_TAS||Overwrite the standard action to execute on a task.|
|IBO_C_WF_TTAC||IBO_C_WF_TTAS||Which Inbox actions (buttons) are available for a task in the inbox.|
This work is heavily based on the blog MDG: “Empower the POWER List” by Florian Raab, which also contains some very nice screen cams (movies, not just pictures!) to guide you through the POWL setup process.