Hello Colleagues,
During MDG Supplier implementation, I received a unique requirement from one of my client.
When requester submits a Change Request with some Bank or HR related sensitive attachments. Then the Bank related approvers should not view the HR attachments. Similarly, the HR related approvers should not view the Bank attachments.
Well, this is quite logical and interesting requirement from Client. Below is implementation process I followed to achieve this unique requirement.
Let’s divide this requirement in to 4 steps.
If we want to enhance CR attachments to add new attribute, we have to extend Genil component “CR”.
So, I planned to add custom attribute “Attach Type” in the Popup which will differentiate the type of attachment.
GeniL Model for CR
So, we need to append Genil Structure for Attachment BSS_CRIL_ATTACHMENT_ATTRIBUTES to have a custom attribute.
Append attribute to BSS_CRIL_ATTACHMENT_ATTRIBUTES
First let’s create a customizing to USMD_CR_ATT_FILE WD component and attach custom feeder class to add this custom attribute. This is a form UIBB, and its feeder class is CL_USMD_CR_ATT_FILE_BOL_FEEDER. Since this feeder class is final, we cannot provide this class as super class to our custom feeder class.
CL_USMD_CR_ATT_FILE_BOL_FEEDER
CL_USMD_CR_ATT_FILE_BOL_FEEDER — Implemented Methods
How to solve this technical block?
What I have done is, created a custom feeder class ZCL_***_CR_ATT_FILE_FEEDER and assign the super class as CL_GUIBB_BOL_FORM which is a super class for CL_USMD_CR_ATT_FILE_BOL_FEEDER.
Custom Feeder class for Attachment Popup
And Reimplemented all the methods as shown below.
Custom Feeder Class with Standard Reimplemented Methods
GET_DATA & GET_DEFINITION methods are redefined to have the custom field (attachment type value, visibility and other options only applicable to MDG-Supplier)
Reimplemented PROCESS_EVENT to through an error message when this field is not field from MDG-Supplier
Code Snippet for this custom feeder class.
IF_FPM_GUIBB_FORM~GET_DATA
METHOD if_fpm_guibb_form~get_data.
DATA : ls_attachment_data TYPE bss_cril_attachment_attributes,
lv_crequest_type TYPE usmd_crequest_type.
FIELD-SYMBOLS: <lv_filename> TYPE any,
<lv_timestamp> TYPE any,
<lv_createdby> TYPE any.
IF me->mv_first_time = abap_false.
ASSIGN COMPONENT 'FILENAME' OF STRUCTURE cs_data TO <lv_filename>.
IF sy-subrc = 0.
mv_filename = <lv_filename>.
ENDIF.
ENDIF.
CALL METHOD super->if_fpm_guibb_form~get_data
EXPORTING
io_event = io_event
it_selected_fields = it_selected_fields
iv_raised_by_own_ui = iv_raised_by_own_ui
iv_edit_mode = iv_edit_mode
IMPORTING
et_messages = et_messages
ev_data_changed = ev_data_changed
ev_field_usage_changed = ev_field_usage_changed
ev_action_usage_changed = ev_action_usage_changed
CHANGING
cs_data = cs_data
ct_field_usage = ct_field_usage
ct_action_usage = ct_action_usage.
IF me->mv_first_time = abap_false.
ASSIGN COMPONENT 'FILENAME' OF STRUCTURE cs_data TO <lv_filename>.
IF sy-subrc = 0.
<lv_filename> = mv_filename.
ENDIF.
ENDIF.
IF me->mv_first_time = abap_true.
me->mv_first_time = abap_false.
CLEAR mv_filename.
" Get parameter
CALL METHOD io_event->mo_event_data->get_value
EXPORTING
iv_key = me->cv_att_mode
IMPORTING
ev_value = me->mv_file_edit_mode.
IF me->mv_file_edit_mode = cv_file_mode_edit.
" Store the initial data of the popup in order to undo changes (if happened)
" when the popup processing will be cancelled
CLEAR me->ms_attachment_file_data.
MOVE-CORRESPONDING cs_data TO me->ms_attachment_file_data.
"me->ms_attachment_file_data = cs_data.
ENDIF.
IF
me->is_mode_read_only( ) = abap_true AND
me->mo_entity IS BOUND AND
NOT ( io_event->mv_event_id = if_fpm_constants=>gc_event-local_edit AND iv_raised_by_own_ui = abap_true ).
me->raise_local_event_by_id( if_fpm_constants=>gc_event-local_edit ).
ENDIF.
ENDIF.
* Below code makes sure that the logic will execute only for MDG-Supplier
IF zcl_oug_vm_util=>get_instance( )->check_app( ) EQ zcl_oug_vm_util=>gc_mdgs.
DATA : ls_field_usage TYPE fpmgb_s_fieldusage,
lt_field_usage TYPE fpmgb_t_fieldusage,
ls_field_usage_value TYPE wdr_context_attr_value,
lt_field_usage_value TYPE wdr_context_attr_value_list.
READ TABLE ct_field_usage ASSIGNING FIELD-SYMBOL(<fs_field_usage>) WITH KEY name = gc_attachment_type.
IF sy-subrc IS INITIAL.
*Add Fixed Values.
ls_field_usage_value-value = gc_bank.
ls_field_usage_value-text = gc_bank.
APPEND ls_field_usage_value TO lt_field_usage_value.
ls_field_usage_value-value = gc_hr.
ls_field_usage_value-text = gc_hr.
APPEND ls_field_usage_value TO lt_field_usage_value.
ls_field_usage_value-value = gc_non_sen.
ls_field_usage_value-text = gc_non_sen.
APPEND ls_field_usage_value TO lt_field_usage_value.
ls_field_usage-fixed_values = lt_field_usage_value.
APPEND ls_field_usage TO lt_field_usage.
<fs_field_usage>-fixed_values = lt_field_usage_value.
<fs_field_usage>-fixed_values_changed = abap_true.
<fs_field_usage>-mandatory = abap_true.
<fs_field_usage>-visibility = '02'.
ENDIF.
ev_field_usage_changed = 'X'.
ELSE.
READ TABLE ct_field_usage ASSIGNING FIELD-SYMBOL(<fs_field_usage1>) WITH KEY name = gc_attachment_type.
<fs_field_usage1>-visibility = '01'.
ev_field_usage_changed = 'X'.
ENDIF.
ENDMETHOD.
IF_FPM_GUIBB_FORM~GET_DEFINITION
METHOD if_fpm_guibb_form~get_definition.
FIELD-SYMBOLS: <ls_field_description> TYPE fpmgb_s_formfield_descr.
CALL METHOD super->if_fpm_guibb_form~get_definition
IMPORTING
es_message = es_message
eo_field_catalog = eo_field_catalog
et_field_description = et_field_description
et_action_definition = et_action_definition
et_special_groups = et_special_groups
ev_additional_error_info = ev_additional_error_info
et_dnd_definition = et_dnd_definition.
READ TABLE et_field_description WITH TABLE KEY name = 'CONTENT' ASSIGNING <ls_field_description>.
IF sy-subrc = 0.
<ls_field_description>-file_name_ref = 'FILENAME'.
<ls_field_description>-mime_type_ref = 'FILE_TYPE'.
ENDIF.
" Enter empty field for dropdown list box for "Attachment Type"
READ TABLE et_field_description ASSIGNING FIELD-SYMBOL(<field_description>) WITH KEY name = gc_attachment_type.
IF sy-subrc = 0 AND <field_description> IS ASSIGNED.
<field_description>-is_nullable = abap_true.
ENDIF.
ENDMETHOD.
IF_FPM_GUIBB_FORM~PROCESS_EVENT
METHOD if_fpm_guibb_form~process_event.
DATA:
lv_dialog_action_id TYPE string,
ls_message LIKE LINE OF et_messages,
lv_message TYPE string, "#EC NEEDED
lv_success TYPE abap_bool,
ls_attachment_data TYPE bss_cril_attachment_attributes.
IF mo_entity IS NOT BOUND OR mo_entity->alive( ) EQ abap_false.
DATA : lr_access1 TYPE REF TO if_bol_bo_property_access,
lr_entity1 TYPE REF TO cl_crm_bol_entity.
lr_access1 = get_property_access( iv_index = 1 ).
TRY.
me->mo_entity ?= lr_access1.
CATCH cx_sy_move_cast_error.
RETURN.
ENDTRY.
ENDIF.
CASE io_event->mv_event_id.
WHEN if_fpm_constants=>gc_event-close_dialog.
io_event->mo_event_data->get_value( EXPORTING iv_key = if_fpm_constants=>gc_dialog_box-dialog_buton_key
IMPORTING ev_value = lv_dialog_action_id ).
CASE lv_dialog_action_id.
WHEN if_fpm_constants=>gc_dialog_action_id-ok.
" Do the necessary popup checks
CHECK me->mo_entity IS BOUND.
CALL METHOD me->mo_entity->if_bol_bo_property_access~get_properties
IMPORTING
es_attributes = ls_attachment_data.
" 1.) Check Mandatory fields
" a.) Link
IF ls_attachment_data-content IS INITIAL.
CLEAR ls_message.
ls_message-msgid = 'USMD2'.
ls_message-msgno = '116'.
ls_message-severity = 'E'.
ls_message-ref_name = 'CONTENT'.
MESSAGE e116(usmd2) INTO lv_message.
APPEND ls_message TO et_messages.
ev_result = if_fpm_constants=>gc_event_result-failed.
ENDIF.
* b.) Title
IF ls_attachment_data-title IS INITIAL.
CLEAR ls_message.
ls_message-msgid = 'USMD2'.
ls_message-msgno = '106'.
ls_message-severity = 'E'.
ls_message-ref_name = 'TITLE'.
ls_message-parameter_1 = TEXT-001.
MESSAGE e106(usmd2) INTO lv_message WITH ls_message-parameter_1.
APPEND ls_message TO et_messages.
ev_result = if_fpm_constants=>gc_event_result-failed.
ENDIF.
* c.) Attach Type for MDG-S
IF zcl_oug_vm_util=>get_instance( )->check_app( ) EQ zcl_oug_vm_util=>gc_mdgs.
IF ls_attachment_data-attach_type IS INITIAL.
CLEAR ls_message.
ls_message-msgid = ''. " Your Custom Message Class
ls_message-msgno = ''. " Message ID from custom message class
ls_message-severity = 'E'.
ls_message-ref_name = 'ATTACH_TYPE'.
ls_message-parameter_1 = TEXT-002.
MESSAGE e106(usmd2) INTO lv_message WITH ls_message-parameter_1.
APPEND ls_message TO et_messages.
ev_result = if_fpm_constants=>gc_event_result-failed.
ENDIF.
ENDIF.
IF ev_result = if_fpm_constants=>gc_event_result-failed.
IF mv_filename IS NOT INITIAL.
CLEAR ls_message.
ls_message-msgid = 'USMDCRUI'.
ls_message-msgno = '002'.
ls_message-severity = 'S'.
ls_message-ref_name = 'CONTENT'.
ls_message-parameter_1 = mv_filename.
MESSAGE s002(usmdcrui) INTO lv_message WITH ls_message-parameter_1.
APPEND ls_message TO et_messages.
ENDIF.
RETURN.
ELSE.
" Processing was fine (no errors)
ev_result = if_fpm_constants=>gc_event_result-ok.
" Initialize variables
me->mv_first_time = abap_true.
CLEAR me->ms_attachment_file_data.
ENDIF.
WHEN if_fpm_constants=>gc_dialog_action_id-cancel OR
if_fpm_constants=>gc_dialog_action_id-close.
IF me->mv_file_edit_mode = cv_file_mode_create.
" If editing has been cancelled in create mode delete the newly created entity again
CALL METHOD me->delete_entity
EXPORTING
io_entity = me->mo_entity
RECEIVING
rv_success = lv_success.
ELSEIF me->mv_file_edit_mode = cv_file_mode_edit.
" If editing has been cancelled in edit mode undo the current changes
CHECK me->mo_entity IS BOUND.
CALL METHOD me->mo_entity->if_bol_bo_property_access~set_properties
EXPORTING
is_attributes = me->ms_attachment_file_data.
CLEAR me->ms_attachment_file_data.
ENDIF.
me->mv_first_time = abap_true.
ENDCASE.
WHEN if_fpm_constants=>gc_event-refresh.
IF mv_filename IS NOT INITIAL.
CLEAR ls_message.
ls_message-msgid = 'USMDCRUI'.
ls_message-msgno = '002'.
ls_message-severity = 'S'.
ls_message-ref_name = 'CONTENT'.
ls_message-parameter_1 = mv_filename.
MESSAGE s002(usmdcrui) INTO lv_message WITH ls_message-parameter_1.
APPEND ls_message TO et_messages.
ENDIF.
WHEN OTHERS.
RETURN.
ENDCASE.
ENDMETHOD.
So far, we have completed the design for Add File Popup screen. Let’s test the functionality in MDG!
Add File Popup with Custom Attribute
Dropdown values
3. Create customizing to LIST UIBB for Attachments:
Now let’s start our next phase of development which is to enhance the Attachments list UIBB to hold/save the “Attach Type” provide from the Add File Popup screen.
So let’s create a customizing to USMD_CR_ATTACHMENTS WD component and attach custom feeder class to add the same custom attribute which we created in GeniL. This is a list UIBB and its feeder class is CL_USMD_CR_GUIBB_ATTACHMENTS. Since this feeder class is not final, we can provide this class as super class to our custom feeder class.
CL_USMD_CR_GUIBB_ATTACHMENTS
Custom Feeder Class for Attachments List UIBB
In this custom feeder class, I have redefined GET_DATA and PROCESS_EVENT methods. Also, created additional methods for Hiding/Disable and checking authorization of the user.
The three custom methods have been called in IF_FPM_GUIBB_LIST~GET_DATA method to check user authorization (at approver level) and to hide/disable the attachments.
Code Snippet for IF_FPM_GUIBB_LIST~GET_DATA
METHOD if_fpm_guibb_list~get_data.
CALL METHOD super->if_fpm_guibb_list~get_data
EXPORTING
iv_eventid = iv_eventid
it_selected_fields = it_selected_fields
iv_raised_by_own_ui = iv_raised_by_own_ui
iv_visible_rows = iv_visible_rows
iv_edit_mode = iv_edit_mode
io_extended_ctrl = io_extended_ctrl
IMPORTING
et_messages = et_messages
ev_data_changed = ev_data_changed
ev_field_usage_changed = ev_field_usage_changed
ev_action_usage_changed = ev_action_usage_changed
ev_selected_lines_changed = ev_selected_lines_changed
ev_dnd_attr_changed = ev_dnd_attr_changed
eo_itab_change_log = eo_itab_change_log
CHANGING
ct_data = ct_data
ct_field_usage = ct_field_usage
ct_action_usage = ct_action_usage
ct_selected_lines = ct_selected_lines
cv_lead_index = cv_lead_index
cv_first_visible_row = cv_first_visible_row
cs_additional_info = cs_additional_info
ct_dnd_attributes = ct_dnd_attributes.
DATA lv_index TYPE i.
CASE iv_eventid->mv_event_id.
WHEN 'CR_ATT_DELETE'.
CALL METHOD iv_eventid->mo_event_data->get_value
EXPORTING
iv_key = 'FPM_GUIBB_LIST_ON_LEAD_SELECTI'
IMPORTING
ev_value = lv_index
er_value = DATA(er_value).
ENDCASE.
* Hide Attachment Type attribute for other Masters. Its applicable only for MSG-S
IF zcl_oug_vm_util=>get_instance( )->check_app( ) NE zcl_oug_vm_util=>gc_mdgs.
READ TABLE ct_field_usage ASSIGNING FIELD-SYMBOL(<fs_field_usage>) WITH KEY name = 'ATTACH_TYPE'.
IF sy-subrc EQ 0.
<fs_field_usage>-visibility = '01'.
ev_field_usage_changed = 'X'.
ENDIF.
ENDIF.
* Hide HR and Bank Attachments based on user Role/Auth object.
IF zcl_oug_vm_util=>get_instance( )->check_app( ) EQ zcl_oug_vm_util=>gc_mdgs.
DATA : lv_crequest_id TYPE usmd_crequest,
lr_data TYPE REF TO data,
lv_leadindex TYPE i,
lt_attachment_data TYPE TABLE OF bss_cril_attachment_attributes,
ls_attachment_data TYPE bss_cril_attachment_attributes,
ls_message TYPE fpmgb_s_t100_message.
FIELD-SYMBOLS <lt_data> TYPE ANY TABLE.
GET REFERENCE OF ct_data INTO lr_data.
ASSIGN lr_data->* TO <lt_data>.
* Get Instance of Conv API.
IF go_mdg_conv IS NOT BOUND.
TRY.
go_mdg_conv = cl_usmd_conv_som_gov_api=>get_instance(
iv_model_name = zcl_oug_vm_util=>gc_model
iv_classname = 'CL_USMD_CONV_SOM_GOV_API' ).
CATCH cx_usmd_conv_som_gov_api. " General Processing Error CONV_API
CATCH cx_usmd_app_context_cons_error. " Exception: Consistency Error in Design of Appl. Context
CATCH cx_usmd_gov_api. " General Processing Error GOV_API
ENDTRY.
ENDIF.
* Get Change Request Attributes to restrict the call after requester step.
IF go_mdg_conv IS BOUND.
go_mdg_conv->get_crequest_attributes( RECEIVING rs_crequest = DATA(rs_crequest) ).
ENDIF.
IF rs_crequest-usmd_creq_status NE '02'. " CR not with Requester
* Check user authorization to view attachments
CALL METHOD me->check_authorization
EXPORTING
im_user = sy-uname " ABAP System Field: Name of Current User
IMPORTING
ev_auth_flag_hr = DATA(lv_auth_flag_hr) " Auth Check Flag for HR Attachments
ev_auth_flag_bank = DATA(lv_auth_flag_bank). " Auth Check Flag for Bank Attachments
IF lv_auth_flag_hr EQ abap_true.
CALL METHOD me->hide_hr_attachments EXPORTING ct_data = lr_data IMPORTING es_message = ls_message.
IF ls_message IS NOT INITIAL.
APPEND ls_message TO et_messages.
ENDIF.
ENDIF.
IF lv_auth_flag_bank EQ abap_true.
CALL METHOD me->hide_bank_attachments EXPORTING ct_data = lr_data IMPORTING es_message = ls_message.
IF ls_message IS NOT INITIAL.
APPEND ls_message TO et_messages.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDMETHOD.
Code Snippet for Custom Method CHECK_AUTHORIZATION
I have created two authorization objects & special roles to differentiate the users. And assigned these roles to users based on requirement. I was checking whether the current CR processor is authorized are not in below method and returning the flag back to GET_DATA method if he is not authorized to view.
METHOD check_authorization.
CLEAR : ev_auth_flag_hr,
ev_auth_flag_bank.
CALL FUNCTION 'AUTHORITY_CHECK'
EXPORTING
user = im_user
object = '' " Custom Auth.Object created for HR
field1 = 'ACTVT'
value1 = '01'
field2 = 'ACTVT'
value2 = '02'
field3 = 'ACTVT'
value3 = '03'
EXCEPTIONS
user_dont_exist = 1
user_is_authorized = 2
user_not_authorized = 3
user_is_locked = 4
OTHERS = 5.
IF sy-subrc = 3.
* User not authorized to view HR attachments
ev_auth_flag_hr = 'X'.
ENDIF.
CALL FUNCTION 'AUTHORITY_CHECK'
EXPORTING
user = im_user
object = '' " Custom Auth.Object created for Bank
field1 = 'ACTVT'
value1 = '01'
field2 = 'ACTVT'
value2 = '02'
field3 = 'ACTVT'
value3 = '03'
EXCEPTIONS
user_dont_exist = 1
user_is_authorized = 2
user_not_authorized = 3
user_is_locked = 4
OTHERS = 5.
IF sy-subrc = 3.
* User not authorized to view Bank attachments
ev_auth_flag_bank = 'X'.
ENDIF.
ENDMETHOD.
Code Snippet for Custom Method HIDE_HR_ATTACHMENTS
In this method, I am receiving the CT_DATA and hiding/disable the data based on custom attribute value. Also, I am sending a warning message. So that the current processor will get an information that there is some sensitive data in that particular CR, but he is not authorized to view.
METHOD hide_hr_attachments.
DATA: lr_data TYPE REF TO data.
FIELD-SYMBOLS: <lt_data> TYPE ANY TABLE,
<ls_line> TYPE any,
<ld_field> TYPE any.
lr_data = ct_data.
ASSIGN lr_data->* TO <lt_data>.
LOOP AT <lt_data> ASSIGNING <ls_line>.
ASSIGN COMPONENT 'CREATED_BY' OF STRUCTURE <ls_line> TO FIELD-SYMBOL(<ls_user>).
ASSIGN COMPONENT 'ATTACH_TYPE' OF STRUCTURE <ls_line> TO <ld_field>.
IF <ld_field> EQ gc_hr.
ASSIGN COMPONENT 'FPM_BOL_GUIBB_REF_0000000020' OF STRUCTURE <ls_line> TO FIELD-SYMBOL(<ls_hr>).
IF <ls_hr> IS ASSIGNED.
<ls_hr> = abap_false.
ENDIF.
ASSIGN COMPONENT 'FPM_BOL_GUIBB_REF_0000000024' OF STRUCTURE <ls_line> TO FIELD-SYMBOL(<ls_langu>).
IF <ls_langu> IS ASSIGNED.
<ls_langu> = abap_false.
ENDIF.
es_message-msgid = ''. " Custom Message Class
es_message-msgno = ''. " Custom Message ID
es_message-parameter_1 = gc_hr.
es_message-severity = 'W'.
ENDIF.
ENDLOOP.
ENDMETHOD.
Code Snippet for Custom Method HIDE_BANK_ATTACHMENTS
METHOD hide_bank_attachments.
DATA: lr_data TYPE REF TO data.
FIELD-SYMBOLS: <lt_data> TYPE ANY TABLE,
<ls_line> TYPE any,
<ld_field> TYPE any.
lr_data = ct_data.
ASSIGN lr_data->* TO <lt_data>.
LOOP AT <lt_data> ASSIGNING <ls_line>.
ASSIGN COMPONENT 'CREATED_BY' OF STRUCTURE <ls_line> TO FIELD-SYMBOL(<ls_user>).
ASSIGN COMPONENT 'ATTACH_TYPE' OF STRUCTURE <ls_line> TO <ld_field>.
IF <ld_field> EQ gc_bank.
ASSIGN COMPONENT 'FPM_BOL_GUIBB_REF_0000000020' OF STRUCTURE <ls_line> TO FIELD-SYMBOL(<ls_bank>).
IF <ls_bank> IS ASSIGNED.
<ls_bank> = abap_false.
ENDIF.
ASSIGN COMPONENT 'FPM_BOL_GUIBB_REF_0000000024' OF STRUCTURE <ls_line> TO FIELD-SYMBOL(<ls_langu>).
IF <ls_langu> IS ASSIGNED.
<ls_langu> = abap_false.
ENDIF.
es_message-msgid = 'ZOUG_MSGS'.
es_message-msgno = '69'.
es_message-parameter_1 = gc_bank.
es_message-severity = 'W'.
ENDIF.
ENDLOOP.
ENDMETHOD.
So before proceeding, let’s test the development at the Requester step.
We can see the new custom attribute which was added to GeniL and Feeder class is appearing in the attachments List UIBB.
Let’s add some attachments and check whether the data getting passed from Popup to List UIBB of attachments.
Ok Data is getting passed and visible in the List UIBB of attachments. So far development is Woking fine as expected.
Now the next task is, once the CR is submitted this custom attribute value also needs to be saved. So that we can retrieve the same for the further CR steps.
For this I have created a custom table Z* as shown below. In this table I have taken Change Request and Timestamp as a key to store the custom attribute value.
The reason behind to create this custom table was to avoid modification/append to SAP standard tables USMD1211 & USMD1212 for attachments.
But here the next technical challenge was, how can I save and read this custom attribute value back to CR during processing.
For this I have created a post exit to the Handler Class for CR Attachment CL_USMD_CR_GIL_ATTACHMENT
But why post exit, why not GeniL enhancement?
Because the standard class CL_USMD_CR_GIL_ATTACHMENT is final, we cannot provide this class as super class to our custom handler class. So created post exit for these methods to overcome this technical block.
In this post exit I have just updated my Z table for attachments and read Z table while displaying. Again, it will be applicable only to MDG Supplier Master.
Code Snippet for Post-Exit CHANGE_OBJECT
METHOD change_object.
IF zcl_oug_vm_util=>get_instance( )->check_app( ) EQ zcl_oug_vm_util=>gc_mdgs.
IF rv_success EQ abap_true.
DATA: ls_att_key TYPE bss_cril_attachment_key,
ls_att_attributes TYPE bss_cril_attachment_attributes,
ls_att_chg_attr TYPE bss_cril_attachment_attributes,
lt_attachment TYPE usmd_ts_attachment,
ls_attachment TYPE usmd_s_attachment,
ls_changed_attribute LIKE LINE OF it_changed_attributes,
ls_attach TYPE zou0065.
FIELD-SYMBOLS:
<lv_changed_attribute> TYPE any,
<lv_attribute> TYPE any.
" Get the key of the changed attachment
ls_att_key = is_key.
" Get the changed attribute structure
CALL METHOD iv_cont_obj->get_attributes
IMPORTING
es_attributes = ls_att_chg_attr.
" Update custom table Z* to display back to UI.
LOOP AT it_changed_attributes INTO ls_changed_attribute.
ASSIGN COMPONENT ls_changed_attribute OF STRUCTURE ls_att_chg_attr TO <lv_changed_attribute>.
CHECK sy-subrc = 0.
IF ls_changed_attribute EQ 'ATTACH_TYPE'.
ls_attach-mandt = sy-mandt.
ls_attach-crequest = ls_att_key-cr_id.
ls_attach-timestamp = ls_att_key-timestamp.
ls_attach-attach_type = ls_att_chg_attr-attach_type.
MODIFY z* FROM ls_attach.
CLEAR ls_attach.
ENDIF.
ENDLOOP.
ENDIF.
ENDIF.
ENDMETHOD.
Code Snippet for Post-Exit GET_ATTRIBUTES
METHOD GET_ATTRIBUTES
IF zcl_oug_vm_util=>get_instance( )->check_app( ) EQ zcl_oug_vm_util=>gc_mdgs.
DATA ls_key TYPE bss_cril_note_key.
DATA lt_attachments TYPE usmd_ts_attachment.
DATA ls_attachments LIKE LINE OF lt_attachments.
DATA ls_genil_attachment_attr TYPE bss_cril_attachment_attributes.
ls_key = is_key.
" Get Instance for API
DATA(go_mdg_conv) = cl_usmd_conv_som_gov_api=>get_instance( iv_model_name = zcl_oug_vm_util=>gc_model ).
" Get attachement attributes
IF go_mdg_conv IS BOUND.
TRY.
CALL METHOD go_mdg_conv->if_usmd_conv_som_gov_cr~get_attachment_list
EXPORTING
if_with_content = space
RECEIVING
rt_attachment = lt_attachments.
CATCH cx_usmd_gov_api_core_error .
RETURN.
ENDTRY.
ENDIF.
READ TABLE lt_attachments INTO ls_attachments WITH KEY usmd_acreated_at = ls_key-timestamp.
IF sy-subrc = 0.
ls_genil_attachment_attr-created_by = ls_attachments-usmd_acreated_by.
ls_genil_attachment_attr-content = ls_attachments-usmd_content.
ls_genil_attachment_attr-explanation = ls_attachments-usmd_explanation.
ls_genil_attachment_attr-file_size = ls_attachments-usmd_file_size.
ls_genil_attachment_attr-file_type = ls_attachments-usmd_file_type.
ls_genil_attachment_attr-language = ls_attachments-usmd_language.
ls_genil_attachment_attr-link = ls_attachments-usmd_link.
ls_genil_attachment_attr-title = ls_attachments-usmd_title.
ls_genil_attachment_attr-timestamp = ls_attachments-usmd_acreated_at.
SELECT crequest,
attach_type
FROM z* INTO @DATA(ls_attach_type)
WHERE crequest = @go_mdg_conv->mv_crequest_id
AND timestamp = @ls_genil_attachment_attr-timestamp.
ENDSELECT.
IF sy-subrc EQ 0.
ls_genil_attachment_attr-attach_type = ls_attach_type-attach_type.
ENDIF.
ELSE.
"??????
ENDIF.
iv_cont_obj->set_attributes( ls_genil_attachment_attr ).
ENDIF.
ENDMETHOD.
Let’s open the change request, which is having both HR and Bank related attachments.
I logged in with user who don’t have authorization to view HR related attachments.
We can see the warning message related to HR related attachments and this particular user cannot perform any action (which means download/view) on HR attachments.
Now I logged in with user who don’t have authorization to view Bank related attachments.
As I mentioned in the beginning of this post, this development should be applicate only to MDG-Supplier.
So, in my coding I always restricted this custom logic using utility class which will check whether the Change Request has been initiated from MDG Supplier.
Here is the Code Snippet for the same.
DATA : GV_APP TYPE CHAR1,
lv_value TYPE string,
lv_key TYPE string.
*Using Application Parameter
DATA(lr_fpm) = cl_fpm=>get_instance( ).
IF lr_fpm IS NOT INITIAL.
CALL METHOD lr_fpm->mo_app_parameter->get_value
EXPORTING
iv_key = 'OTC'
IMPORTING
ev_value = lv_value.
IF lv_value IS NOT INITIAL.
IF lv_value EQ '266'. "266- MDG-S BO Type
me->gv_app = 'S'.
ELSEIF lv_value EQ '159' "159- MDG-C BO Type
me->gv_app = 'C'.
ENDIF.
ENDIF.
ENDIF.
Thank you for reading my blog.
In this blog post I tried to cover all the development tasks. So, I hope this might be helpful for some one’s similar scenario.
Please drop your comments, valuable suggestions and if any help is required. I would be happy to assist. 😊
Thank you.
Best Regards
Mani