SAP HCM PROCESS & FORMS in Mobile Architecture SAP UI5 (FIORI) ATTACHEMENT PART IV
I am a Senior SAP technical consultant and associated with one of the SAP partner company and experiencing SAP products for past 7 years with 4 end to end implementation life cycle and more than 10 support projects of SAP Customer from diversified industries. The current company implements and supports SAP solution to the SAP customers. During one of the implementation project that requires HCM Process & Forms that was implemented on SAP webdynpro previously on ESS/MSS Portal and now need to be transformed into SAP FIORI.
For this purpose, I made some R&D about the topic that could help me in this, I found a topic on a blogs https://blogs.sap.com/2016/07/20/hcm-processes-and-forms-mobilize-your-processes-with-ui5-and-sap-gateway-part-i-basic-thoughts/ that give me some help in my requirement fulfilment.
In continuation of the blog, where the concept of SAP HCM process and forms utilisation in UI5 applications at ECC platform concept has been given; I personally felt one part missing during the implementation. And could not able to find such topic else where.
As I implemented that part of ABAP at backend, I would like to share it as it might be the requirement of any other client or consultant too. First I would suggest to go through the above link and follow this if you have such requirement.
First of all you must aware of the concepts of processes, scenarios and steps. The process contains scenarios and the scenario contains steps and the step contains attachments.
Now these attachment possibly have three kind of operations on interface.
- Attachment during Creation of process
- Attachment on created process
- Display attachments.
Let’s discuss them one by one.
- Attachment during Creation of process
A. Fetching Attachment Types:
At initialization of process event when the screen opens; it needs attachment types with its description that are associated with that particular process in order to put it in the drop down box.
The following is the query to do so:
DATA: lt_attach_types TYPE TABLE OF t5asrfscnstgatm, ls_attach_types TYPE t5asrfscnstgatm. DATA: I_PROCESS TYPE QISRDFIELDVALUE. SELECT * FROM t5asrfscnstgatm INTO TABLE lt_attach_types WHERE form_scenario = i_process AND form_scen_stage = 'DEFAULT'.
**WHERE: “i_process” is your process name and stage will be “DEFAULT” at this point of initialization.
Now loop the table in order to get description:
LOOP AT lt_attach_types INTO ls_attach_types. MOVE: ls_attach_types-attachment_type TO ls_attach_det-attachment_type, ls_attach_types-demand_level TO ls_attach_det-demand_level. SELECT SINGLE description FROM t5asrattachmentt INTO ls_attach_det-description WHERE attachment_type = ls_attach_det-attachment_type AND langu = sy-langu. IF ls_attach_det-demand_level = abap_false. ls_attach_det-demand_level = 'O'. ENDIF. APPEND ls_attach_det TO e_attach_det. ENDLOOP.
“Where setting up demand level to “O” for Obligatory because it is showing NULL for obligatory and as we have to forward this to frontend to FIORI it requires some symbol that identify it as obligatory type of attachment.
B. Storing Attachments during create process:
For storing attachment, we need attachment content input as a table in changing parameter of a RFC /FM in order to maintain list of attachments that are attached to a process. For this we need to declare it as follows:
CT_ATTACHMENTS TYPE HRASR00ATTACHMENT_DTL
(Define in changing parameter of RFC)
Once the CT_ATTACHMENTS has attachments then we need to loop it into work area but first we have to change type of work area component “ATTACHMENT_CONTENT” from type “ASR_ATTACHMENT_CONTENT” to “CACL_STRING” because we need to convert it from base64 to bindata for this I customize the structure of HRASR00ATTACHMENT_DTL to zhrasr00attachment_dtl. So I have declare these as:
DATA: lt_att TYPE TABLE OF hrasr00attachment_dtl, ls_att TYPE hrasr00attachment_dtl, ls_attachments TYPE zhrasr00attachment_dtl.
“Where LT_ATT is the additional table that carry attachments after conversion.
Now, we need to loop table as follows:
LOOP AT ct_attachments INTO ls_attachments. MOVE-CORRESPONDING: ls_attachments TO ls_att. CALL FUNCTION 'SSFC_BASE64_DECODE' EXPORTING b64data = ls_attachments-attachment_content IMPORTING bindata = ls_att-attachment_content EXCEPTIONS ssf_krn_error = 1 ssf_krn_noop = 2 ssf_krn_nomemory = 3 ssf_krn_opinv = 4 ssf_krn_input_data_error = 5 ssf_krn_invalid_par = 6 ssf_krn_invalid_parlen = 7 OTHERS = 8. IF sy-subrc <> 0. ELSE. APPEND ls_att TO lt_att. CLEAR: ls_att. ENDIF. ENDLOOP.
Now, we need to loop additional table that holds after conversion contents. In this loop we will introduce a function module “HR_ASR_STORE_ATTACHMENT”. It stores attachment data for temporary basis until the current session ended. If it is ended without save/send call this data will be removed else send with the form.
One more thing that is need to remember for this FM is that the exporting parameter “step_object_guid” will be just declared not filled with any value as we have to attach files at initial step that will be created afterwards at save/send call and the system will auto generate its step guid so we need not to pass step guid.
DATA: lv_case_guid TYPE scmg_case_guid. "Attachement Storage LOOP AT lt_att INTO ls_att. IF ls_att-attachment_type IS NOT INITIAL OR ls_att-attachment_filename IS NOT INITIAL OR ls_att-attachment_content IS NOT INITIAL. CALL FUNCTION 'HR_ASR_STORE_ATTACHMENT' EXPORTING step_object_guid = lv_case_guid attachment_type = ls_att-attachment_type filename = ls_att-attachment_filename attachment_content = ls_att-attachment_content IMPORTING return = ls_att_return attachment_index = lv_attachment_index. APPEND ls_att_return TO lt_att_return. CLEAR ls_att_return. ENDIF. ENDLOOP.
After this when you call function module “ISR_PROCESS_EVENT”. The code that store all the attachment will be committed and saved.
- Attachment on created process
When it comes to attach the attachment at particular step so the procedure becomes bit tricky. Once you have created and send a process, for instance, for approval it will go one step further making initial step status “DEFAULT” and creating next step with status “Ready”. So we have some previously stored files as well as we have to add new with maintaining index of attachment.
In my case, the process is forwarded for approval and now approver wants add some file that he feel missing during the approval process. Let me show you the code by explaining how we could achieve it.
First of all we need to find the current step guid that is on “Ready” stage. Considering that you have scenario guid already followed by a process guid and a reference number. Also the process has been initialized.
SELECT SINGLE case_guid no_of_attachment scenario_stage FROM t5asrsteps INTO (lv_step_object_guid, lv_asr_no_of_attachments, lv_scenario_stage) WHERE parent_scenario = lv_sguid AND status = 'READY'.
Now we have a step guid. Next we have to find either the user is allowed edit or create a new attachment or not. For this we do the following:
CLEAR e_attch_create_allowed. SELECT SINGLE modify_allowed FROM t5asrfscnstgatm INTO e_attch_create_allowed WHERE form_scenario EQ lv_form_scenario AND form_scen_stage EQ lv_scenario_stage.
After this we have to loop the table I_ATTACHMENT. It is the table that holds the content of newly inserted files. Also we require another table with same type i-e zhrasr00attachment_dtl that have content field type altered because now we have to convert base64 to bindata again.
DATA: lt_attachment_m TYPE TABLE OF zhrasr00attachment_dtl, ls_attachment_m TYPE zhrasr00attachment_dtl.
Now have a look at this code:
IF lv_step_object_guid IS NOT INITIAL AND e_attch_create_allowed = abap_true. LOOP AT i_attachment INTO ls_attachment_m. MOVE-CORRESPONDING: ls_attachment_m TO ls_attachment. CALL FUNCTION 'SSFC_BASE64_DECODE' EXPORTING b64data = ls_attachment_m-attachment_content IMPORTING bindata = ls_attachment-attachment_content EXCEPTIONS ssf_krn_error = 1 ssf_krn_noop = 2 ssf_krn_nomemory = 3 ssf_krn_opinv = 4 ssf_krn_input_data_error = 5 ssf_krn_invalid_par = 6 ssf_krn_invalid_parlen = 7 OTHERS = 8. IF sy-subrc <> 0. ELSE. APPEND ls_attachment TO lt_attachment. CLEAR: ls_attachment. ENDIF. ENDLOOP.
Now you need to get a list of attachments on the particular step. This will expose all previously attached list of attachments to memory.
form_scenario = lv_form_scenario. CALL FUNCTION 'HR_ASR_GET_ATTACHMENT_LIST' EXPORTING step_object_guid = lv_step_object_guid form_scenario = form_scenario form_scenario_version = form_scenario_version form_scenario_stage = form_scenario_stage get_attachment_content = 'X' mode = mode IMPORTING * RETURN = attachment_list = attachment_list.
Now, again loop the LT_ATTCHMENT table, that has converted contents now, to different work area and push into attachement store function module. This time we have to give step guid as step has already been created in the system and we are attaching those attachment on particular step so it could not be NULL.
"Attachement Storage LOOP AT lt_attachment INTO ls_attachment. IF ls_attachment-attachment_type IS NOT INITIAL OR ls_attachment-attachment_filename IS NOT INITIAL OR ls_attachment-attachment_content IS NOT INITIAL. CALL FUNCTION 'HR_ASR_STORE_ATTACHMENT' EXPORTING step_object_guid = lv_step_object_guid attachment_type = ls_attachment-attachment_type filename = ls_attachment-attachment_filename attachment_content = ls_attachment-attachment_content IMPORTING return = ls_att_return attachment_index = lv_attachment_index. APPEND ls_att_return TO lt_att_return. CLEAR ls_att_return. ENDIF. ENDLOOP.
Now list attachment again from memory so it will expose a new list in which the old and new files altogether.
CALL FUNCTION 'HR_ASR_GET_ATTACHMENT_LIST' EXPORTING step_object_guid = lv_step_object_guid form_scenario = form_scenario form_scenario_version = form_scenario_version form_scenario_stage = form_scenario_stage get_attachment_content = 'X' mode = mode IMPORTING * RETURN = attachment_list = attachment_list.
Now we have to push into the step properties from work item into external data in order to record changes.
CALL FUNCTION 'HR_ASR_GET_STEP_PROPERTIES' EXPORTING workitem_id = i_workitem_id TABLES step_properties = step_properties message_lines = message_lines error_agent_messages = error_agent_messages. LOOP AT lt_external_data INTO external_data_wa. READ TABLE step_properties INTO step_properties_wa WITH KEY name = external_data_wa-fieldname. IF sy-subrc = 0. IF external_data_wa-fieldname = 'PROCESS_OBJECT_GUID'. external_data_wa-fieldvalue = lv_pro_guid. MODIFY lt_external_data FROM external_data_wa. ELSE. external_data_wa-fieldvalue = step_properties_wa-value. MODIFY lt_external_data FROM external_data_wa. ENDIF. ELSEIF external_data_wa-fieldname = 'PROCESS_REFERENCE_NUMBER'. external_data_wa-fieldvalue = lv_ref_number. MODIFY lt_external_data FROM external_data_wa. ELSEIF external_data_wa-fieldname = 'WORKITEM_ID'. external_data_wa-fieldvalue = i_workitem_id. MODIFY lt_external_data FROM external_data_wa. ENDIF. ENDLOOP.
Now we will initializing the process event in the change mode to record the changes.
ls_data-fieldindex = 1. ls_data-fieldname = 'ISR_SCENARIO_PARAMS'. CONCATENATE 'VERSION=' form_scenario_version INTO ls_data-fieldvalue. APPEND ls_data TO lt_data. lv_mode = 'CHANGE'. CALL FUNCTION 'ISR_PROCESS_EVENT' EXPORTING scenario = lv_scenario mode = lv_mode flag_inout_conversion = space IMPORTING return = lv_return TABLES external_data = lt_external_data additional_data = lt_additional_data data = lt_data message_list = lt_message_list.
Fire the check event on the same point of time.
CALL FUNCTION 'ISR_PROCESS_EVENT' EXPORTING scenario = lv_scenario mode = lv_mode event = 'CHECK' flag_inout_conversion = space IMPORTING return = lv_return TABLES data = lt_data additional_data = lt_additional_data external_data = lt_external_data message_list = lt_message_list. error_found = ' '. LOOP AT lt_message_list INTO isrmessage. IF isrmessage-type = 'E' OR isrmessage-type = 'A'. error_found = abap_true. ENDIF. ENDLOOP.
Change the status in external data table.
IF error_found = ''. external_data_wa-fieldindex = 1. external_data_wa-fieldname = 'PROCESSING_STATUS'. external_data_wa-fieldvalue = 'PROCESSED'. READ TABLE lt_external_data WITH KEY fieldindex = 1 fieldname = 'PROCESSING_STATUS' TRANSPORTING NO FIELDS. IF sy-subrc EQ 0. MODIFY lt_external_data INDEX sy-tabix FROM external_data_wa TRANSPORTING fieldvalue. ELSE. APPEND external_data_wa TO lt_external_data. ENDIF.
Now finally fire the save event.
CALL FUNCTION 'ISR_PROCESS_EVENT' EXPORTING scenario = lv_scenario mode = lv_mode event = 'SAVE' flag_inout_conversion = space IMPORTING return = lv_return TABLES data = lt_data additional_data = lt_additional_data external_data = lt_external_data message_list = lt_message_list. ENDIF. ENDIF. ENDIF.
- Display attachments.
Find the step guid and no. of attachments.
SELECT SINGLE case_guid no_of_attachment FROM t5asrsteps INTO (lv_step_object_guid, lv_asr_no_of_attachments) WHERE parent_scenario = lv_sguid AND scenario_stage = 'DEFAULT'.
Get attachment attribute.
SELECT SINGLE modify_allowed display_allowed FROM t5asrfscnstgatm INTO (e_attch_create_allowed, e_attch_display_allowed) WHERE form_scenario EQ lv_form_scenario AND form_scen_stage EQ lv_step. MOVE: e_attch_create_allowed TO ls_attachment_attr-modify_allowed, e_attch_display_allowed TO ls_attachment_attr-display_allowed. APPEND ls_attachment_attr TO lt_attachment_attr. CLEAR: ls_attachment_attr.
Create instance and get attachment.
IF lv_step_object_guid IS NOT INITIAL AND e_attch_display_allowed = abap_true. cl_hrasr00_proc_obj_handler=>get_instance( EXPORTING step_guid = lv_step_object_guid " Step GUID message_handler = lo_message_list " HR-PD Infotypes: Messages no_auth_check = abap_true " Data Element for Domain BOOLE: TRUE (="X") and FALSE (=" ") activity = 'R' " Activities - 'S', 'R' , 'W', 'X', 'D' IMPORTING instance = lo_ins " Process Object Handler is_ok = lv_is_ok ). IF lv_is_ok = abap_true. lo_ins->get_attachments( EXPORTING message_handler = lo_message_list " HR-PD Infotypes: Messages no_auth_check = abap_true " Data Element for Domain BOOLE: TRUE (="X") and FALSE (=" ") activity = 'R' " Activities - 'R' IMPORTING attachments = lt_attachment "att " Table of Attributes and Contents of Attachment ).
Convert the content of file from bindata to base64.
LOOP AT lt_attachment INTO ls_attachment. MOVE-CORRESPONDING: ls_attachment TO ls_attachment_m. CALL FUNCTION 'SSFC_BASE64_ENCODE' EXPORTING bindata = ls_attachment-attachment_content IMPORTING b64data = ls_attachment_m-attachment_content EXCEPTIONS ssf_krn_error = 1 ssf_krn_noop = 2 ssf_krn_nomemory = 3 ssf_krn_opinv = 4 ssf_krn_input_data_error = 5 ssf_krn_invalid_par = 6 ssf_krn_invalid_parlen = 7 OTHERS = 8. IF sy-subrc <> 0. * Implement suitable error handling here ENDIF. APPEND ls_attachment_m TO lt_attachment_m. CLEAR ls_attachment_m. ENDLOOP. ENDIF. ENDIF.
Now LT_ATTACHMEN T_M has your attachments to display.
In conclusion, I cover the three operations that is needed for attachment of a process at any step i-e create, change and display. You might relate and change the ABAP code according to your requirement but at least it gives you a central idea for doing things.
For more information, you can comment and question to this post so I will as much as I can.