Die Datenerfassung der Antragsdaten erfolgt im Infotyp: 0700 (Elektronischer Datenaustausch) Subtypen:
DXA1 (A1: Antrag Entsendebescheinigung)
DXAV (A1: Antrag Ausnahmevereinbarung)
Reports zur Erstellung der Meldungen und der Meldedateien:
Personal → Personalabrechnung → Europa → Deutschland → Folgeaktivitäten → Periodenunabhängig → Abrechnungszusatz → A1-Meldeverfahren → Ausgangsmeldungen
Reports zur Verarbeitung der Eingangsmeldungen:
Personal → Personalabrechnung → Europa → Deutschland → Folgeaktivitäten → Periodenunabhängig → Abrechnungszusatz → A1-Meldeverfahren → Eingangsmeldungen
Behördenkommunikation (B2A): Transaktion PB2A
Personal → Personalabrechnung → Europa → Deutschland → Folgeaktivitäten → Periodenunabhängig → Behördenkommunikation (B2A) → B2A-Manager
Hilfreiche Entwicklungsobjekte
Paket: P01S
Reports:
Klassen:
Für mich hilfreich waren folgenden Klassen:
CL_HRPAYDE_A1_NOTIF (Klasse für A1-Meldungen)
CL_HRPAYDE_A1_NOTIF_DISPLAYER (ALV-Ausgabe für A1-Meldungen)
CL_HRPAYDE_A1_ALV_EVNT_HANDLER (Ereignisbehandler für A1-spezifische Ereignisse)
PDFs der A1-Meldungen von Datenbank lesen
*&---------------------------------------------------------------------*
*& Tabellen A1-Meldeverfahren:
*& P01A1_STAT - A1-Verfahren: Verwaltungstabelle
*& P01A1_RAWDATA - A1-Verfahren: Rohdaten einer Meldung
*&---------------------------------------------------------------------*
GET peras.
SELECT * INTO TABLE @DATA(lt_p01a1_stat) FROM p01a1_stat
WHERE pernr = @pernr-pernr
AND mdtyp = '2'
AND status = '23'
AND mzbeg <= @pn-endda
AND mzbeg >= @pn-begda.
LOOP AT lt_p01a1_stat INTO DATA(ls_p01a1_stat).
SELECT SINGLE * INTO @DATA(ls_p01a1_rawdata) FROM p01a1_rawdata
WHERE guid = @ls_p01a1_stat-guid
AND lfdnr = ( SELECT MAX( lfdnr ) FROM p01a1_rawdata WHERE guid = @ls_p01a1_stat-guid ). "höchste lfdnr nehmen
DATA(pdf_xstring) = ls_p01a1_rawdata-rawdata.
ENDLOOP.
When searching for a way to select quotas without doing a manual select, I found the following class is the Fiori odata packages.
DATA pernr TYPE pernr_d VALUE 1.
DATA(time_accounts) = cl_hcmfab_att_abs_bl_apis=>get_instance( )->read_time_accounts( iv_pernr = pernr
iv_begda = sy-datum
iv_endda = sy-datum ). "iv_endda is never used!
cl_demo_output=>display( time_accounts ).
But although there is an obligatory iv_endda parameter, it is never used inside of method read_time_accounts. Instead, there is some logic which checks for a T77S0 Parameter, and it will use either highdate or begda as endda value.
IMO, it would have made sense to mark iv_endda as optional, so it would be downward compatible and the parameter could be omitted on newer releases. Now it is a bit misleading.
However, if you look inside the method read_time_accounts you’ll find another class that is used to read the quotas. The names of the result fields are slightly different, but at least the endda is used in this case.
By using line_exists you can check if a line exists or not exists, but it is not possible to use other comparison operators. A workaround can be REDUCE in that case.
In the following snippet, we want to check if there is a flight that costs more than $1000,
SELECT * FROM sflight INTO TABLE @DATA(flights).
* Check if flight with price > 1000 exist
IF REDUCE abap_bool( INIT price_gt_1000 = abap_false
FOR line IN flights WHERE ( price > 1000 )
NEXT price_gt_1000 = abap_true ) EQ abap_true.
" flight with price > 1000 exists
ENDIF.
Easy way to loop over multiple tables of the same type, without having to create an additional table to join the data before the loop.
SELECT FROM spfli FIELDS * WHERE carrid EQ 'AA' INTO TABLE @DATA(lt_spfli_1).
SELECT FROM spfli FIELDS * WHERE carrid EQ 'AZ' INTO TABLE @DATA(lt_spfli_2).
LOOP AT VALUE spfli_tab( ( LINES OF lt_spfli_1 )
( LINES OF lt_spfli_2 )
( carrid = 'AV' ) ) ASSIGNING FIELD-SYMBOL(<spfli>).
WRITE <spfli>-carrid.
ENDLOOP.
Got this snippet from George Drakos talk from the ABAPConf 2024. Check his Github.
Since my workflow was already in this state, I had to find another way, and found it with transaction code SWWL. Simply find the unique Identification of the top level workitem via t-code SWIA and then use it in SWWL. When running the report, you will first get a list, then simply select the result items you want to delete and hit the trash icon, or restart the selection and check the flag for Delete immediately.
I had to calculate the difference between two times, even if the end time goes beyond the 0 o’clock day limit, e.g. 20:00 to 02:00 should be 6h. I found the following two function modules doing the job:
* Option 1
CALL FUNCTION 'CATS_COMPUTE_HOURS'
EXPORTING
pernr = pernr
date = date
* NO_BREAK_DEDUCTION = ' '
row = row
TABLES
return = return
CHANGING
catshours = catshours
beguz = beguz
enduz = enduz
vtken = vtken.
* Option 2 (I think it's only available on S/4 HANA)
CALL FUNCTION 'CATS_DETERMINE_HOURS'
CHANGING
catshours = catshours
beguz = beguz
enduz = enduz.
Customizing SPRO → Personnel Management → Employee Self-Service (Web Dynpro ABAP) → Service-Specific Settings → Working Time → My Overtime Requests.
Adjusting the Fiori UI
If you want to hide fields in the Fiori frontend, or you want to adjust some labels, you can simply do this via Customizing: My Overtime Requests → Layout of the Web Application → Define Field Selection
Multi-Level Approval for Time Data Requests (HRPT_B_TMD_MULTI_APPROVERS)
The BAdI is called when opening the My Overtime Request App and a second time when clicking on the New Button to create a new OVT request. It’s not triggered when sending the request, what I initially expected. To reuse the code from the sample class,
* "Determine approver level
* DATA(cust_key_request_fields) = VALUE cl_hrpt_ovt_const=>ovt_cust_key_request_fields( pernr = iv_pernr
* ktart = iv_subtype
* date = is_request_period-start_date ).
* TRY.
* DATA(approval_settings) = cl_hrpt_ovt_cust_factory=>get_customizing_reader( )->get_approval_settings( REF #( cust_key_request_fields ) ).
* CATCH cx_hrpt_tmd.
* RETURN.
* ENDTRY.
* IF approval_settings-use_multiple_approver = abap_false.
* RETURN.
* ENDIF.
....
* "If no last approvers exist, use line manager, HR BP and HR Admin by default
* CALL FUNCTION 'BAPI_GET_LINE_MANAGER'
* EXPORTING
* im_objid = iv_pernr
* IMPORTING
* es_approver = line_manager
* ev_has_manager = approver_exists.
* IF approver_exists = abap_true.
* last_seqnr = last_seqnr + 1.
* line_manager-seqnr = last_seqnr.
* APPEND line_manager TO rt_approver_tab.
* IF lines( rt_approver_tab ) >= approval_settings-approver_level.
* RETURN.
* ENDIF.
* ENDIF.
you have to set the amount of approval steps in the customizing.
Also, a Filter must be set for the BAdI:
When you run into a permission issue when opening an overtime request in MyInbox, take a look in the HCMFAB_COMMON BAdI. Perhaps the GET_CONFIGURATION method must be implemented
method if_ex_hcmfab_common~get_configuration.
ev_hide_employee_picture = abap_false.
ev_hide_employee_number = abap_false.
ev_hide_ce_button = abap_false.
ev_enable_onbehalf = abap_false.
ev_show_empl_number_wo_zeros = abap_false.
* On_behalf is switched off by default for compatibility reasons
* To activate it for all users who are mangers the following code could be used:
case iv_application_id.
when gc_application_id-myovertimequota.
ev_enable_onbehalf = boolc( go_employee_api->is_manager( iv_application_id = iv_application_id
iv_pernr = iv_employee_number ) = abap_true ).
endcase.
* In case that on behalf is active, transfer all data to the frontend. This is faster for small number of employees.
* The backend search would only transfer the visible employees to the frontend, at the cost of multiple smaller requests.
ev_use_onbehalf_backend_search = abap_false.
endmethod.
Custom Workflow
If you want to replace the default Workflow WS02400057 (PT_OVTREQ) with a custom one, you must adjust the customizing (as described here for the standard WF), and you’ll need to create a new BAdI Implementation for /IWWRK/ES_WF_WI_BEFORE_UPD_IB analog HCMFAB_MYOTQ_APPROVAL_INBOX to get the Approve and Rejects Buttons working by providing the Workflow-ID and decision Step-ID.
Extensibility
Although it should be possible to extend both Fiori Apps via Adaptation Projects, I was unable to do so. Either it’s a problem with the new adaption editor, which got new released while writing the blog, or it is a problem with the apps itself. Whatever I tried, I was always running in issues.
Therefore, I did it the “classic” way and created an Extension Project and used the provided Extension Points. For the Approval App, I was unable to preview the application directly in BAS, perhaps because it is only an Inbox integration and does not run standalone. I therefore always had to deploy, to test my changes.