I have often wondered about the ingredients for the recipe of “Success”. Without an iota of doubt, Success requires hard work, diligence, perseverance, right skill set, knowledge, expertise, right attitude, inspiration, perspiration and so on. It also requires another important ingredient called “Lady Luck”.
Whenever we are trying to work on something new or going into an unknown territory, we need that “Eureka” moment and I had one such moment a couple of days back with regards to overtime requirement for one of my clients.
Our client requirement was to give overtime at two different rates – R1 and R2. There were both regular and shift employees and overtime was applicable to both of them.
Below were the conditions for overtime:
- R1 – If the employee worked overtime on working days outside planned working hours between 6 am – 9 pm.
- R2 – If the employee worked overtime on OFF days or Public Holidays or on working days outside planned working hours between 9 pm – 6 am.
There was an additional requirement that if the employee worked more than 20 hours of R1 overtime in a month, then the hours beyond 20 hours should be treated as R1 extra overtime and the rate of R1 extra will be more than R1.
In similar way, if the employee worked more than 15 hours of R2 overtime, then the hours beyond 15 hours should be treated as R2 extra overtime and the rate of R2 extra will be more than R2.
Below were the rates of overtime:
- R1 – 150% of daily hourly rate
- R1 Extra – 200% of daily hourly rate
- R2 – 175% of daily hourly rate
- R2 Extra – 250% of daily hourly rate
Also, the client wanted a report to display the overtime hours at the above rates on a daily basis. In other words, client also wanted to know from which date onwards, the rates R1 and R2 changed to R1 Extra and R2 Extra respectively.
If there was only one overtime wage type (R1) to be generated in time evaluation and once the total no. of overtime hours in the month crossed 20 hours, then the 2nd wage type (R1 Extra) had to be generated, then the solution would have been simpler and easier to achieve in time evaluation. Here, we are assuming that the rates R2 and R2 extra were not in the requirements.
In such a case, this could have been done by building a solution of cumulating the total no. of overtime hours in a month and till 20 hours, we allow wage type with R1 rate to be generated using processing type M and after 20 hours, we change the processing type to N in time pair for overtime hours and generate wage type with R1 Extra rate.
The process of assigning processing type N to overtime hours beyond 20 hours in a month would need to be done using a custom PCR before the block of selecting time wage types (shown in the screenshot below from time schema).
We would need to assign a wage type for processing type M and assign another wage type for processing type N along with the relevant overtime rules in Table V_T510S.
Also, we would need to add “GWT N ZML” in the schema for selecting time wage types.
However, we need wage types with two different rates (R1 and R2) initially and once they cross the cumulative threshold values within a month, R1 Extra and R2 Extra rates kick in. Also, the generation of wage types with R1 and R2 rates are dependent on the timings for which we need the overtime hours in Table TIP to get processed through time wage type selection rule table V_T510S.
Hence, we would need to generate wage types with R1 and R2 rates first and when they cross the threshold values within the month, the generation of wage types with R1 Extra and R2 Extra rates should commence. This means that the logic will have to be built after the block of selecting time wage types.
I also thought of another approach. We generate all the time wage types using R1 and R2 rates only for the month in Table V_T510S. These wage types will get stored in Table ZL. Standard function ZLIT in time section of payroll schema will read these wage types from Table ZL and move them to Table IT for payroll processing.
In payroll, we will write a custom PCR to check the total no. of overtime hours in R1 and R2 wage types and if the total no. of overtime hours cross the threshold values, we split them into R1, R1 Extra, R2 and R2 Extra wage types with the overtime hours.
This splitting of wage types from R1 and R2 into R1, R1 Extra, R2 and R2 Extra will happen before processing in PCR X015 in payroll schema, where the rate gets multiplied with no. of hours to give the final amount. The rates for all the four wage types will be maintained in Table V_T510J.
However, there is an inherent flaw in my solution approach which doesn’t meet one of the requirements of the customer. It wants a report to display the overtime hours with rates R1, R2, R1 Extra and R2 Extra on a daily basis. In this approach, overtime hours will get generated only with rates R1 and R2 on a daily basis in time evaluation. The cumulative values of these overtime hours are later split into R1, R1 Extra, R2 and R2 Extra based on threshold values in payroll calculation. Hence, the report can display overtime hours only with R1 and R2 rates on a daily basis which doesn’t suffice customer’s requirement.
This leaves us with only one choice – allow generation of overtime wage types with R1 and R2 rates on a daily basis in Table V_T510S and when the cumulative threshold for R1 and R2 rates crosses, replace wage types of R1 and R2 rates with wage types of R1 Extra and R2 Extra rates respectively.
When overtime wage types get generated based on rules defined in Table V_T510S, they get stored in internal table ZML. Function POVT processes PCR TC40 to move the overtime wage types from Table ZML to Table DZL. Finally, function CUMBT moves overtime wage types from Table DZL to Table ZL.
The process of replacing wage types of R1 and R2 rates with wage types of R1 Extra and R2 Extra rates respectively would need to be done before wage types are moved into Table ZL in time evaluation.
I researched through time functions and operations to find a way to split the overtime hours and move them into a new wage type. Finally, I was able to find a function PZL and an operation OUTZL which helped me build this solution.
PZL function provides a personnel calculation rule (Par 1) with wage types for processing based on the identifier (Par 3) and deletes these wage types from DZL or ZL table. If we want the wage types to remain in DZL or ZL table after processing, we will have to use operation ADDZL to transfer the wage types back to DZL or ZL Table.
A time wage type can have three possible identifiers:
- S – Planned Work
- M – Overtime
- A – Absence
In our scenario, the wage types will have identifier M.
OUTZL operation will help us to query the wage type for processing.
Let us now design and build the solution. For solution design purpose, we will be focusing only on splitting Wage Type with R1 rate into R1 and R1 Extra after 20 hours overtime threshold is reached. The same logic can be used to build it for wage type with R2 rate.
We will use the below model wage types for our solution design:
- R1 – M806
- R1 Extra – M807
Time Type ZAD4
We will also create a monthly time type ZAD4 for cumulating overtime hours. Below is the screenshot for the same.
We will create a constant ZOVBR for the threshold check of 20 hours. Below is a screenshot for the same. If the client decides to change this threshold limit tomorrow, we just have to update this constant from the date of change.
We will also create a PCR ZAD5 for splitting overtime hours of wage type M806 once it touches the monthly threshold value of 20 hours. Below is the screenshot for the same.
This PCR appears to be slightly complex and hence, let me try my best to explain its functionality.
Function PZL processes PCR ZAD5 for wage types with identifier as M in Table DZL. PCR ZAD5 reads the wage types using operation OUTZL WGT. For any wage type other than M806, it gets processed under ****. Basically, it doesn’t process the wage type and also removes it from Table DZL. If we wish to move that WT to Table DZL, then we should use operation ADDZL.
If the wage type is M806, it reads the cumulative monthly overtime hours from time type ZAD4 using HRS=MZAD4. Then it compares the hours (ZAD4) with the value in constant ZOVBR using HRS?CZOVBR.
If the value of ZAD4 is equal to or greater than the value in ZOVBR, it means that the threshold value is already reached and the PCR gets processed under * and the overtime hours of the current day (WT M806) should be transferred to WT M807. The overtime hours of WT M806 for current day are read from Table DZL by using HRS=ENUM and then they are added to time type ZAD4 (total overtime hours of a month) using ADDDBZAD4Z and wage type M807 using ADDZLMM807. As mentioned before, function PZL finally deletes the WT M806 which was present before during input.
If the value of ZAD4 is less than the value in ZOVBR, it means that the threshold value is not yet reached and the PCR gets processed under <. The cumulative monthly overtime hours are read using HRS=MZAD4 and the overtime hours of current day (WT M806) are added to the monthly overtime hours using HRS+ENUM. The value is again compared with the threshold value in constant ZOVBR using HRS?ZOVBR.
If the value is less than or equal to ZOVBR, the PCR gets processed under *. The overtime hours of the current day (WT M806) are read using HRS=ENUM and then they are added to time type ZAD4 (total overtime hours of a month) using ADDDBZAD4Z and wage type M806 using ADDZLMM806. Function PZL finally deletes the WT M806 which was present before during input.
If the value is greater than ZOVBR, the PCR gets processed under > and finally goes to PCY ZAD5A and PCY ZAD5B.
Under A, it reads the value of ZOVBR using HRS=CZOVBR and subtracts the value of cumulative monthly overtime hours using HRS-MZAD4. The difference is compared using HRS?0 and if it is greater than 0, it gets processed under >. Under >, the hours are added to WT M806.
Under B, it reads the value of cumulative monthly overtime hours using HRS=MZAD4 and adds the overtime hours for the current day (WT M806) using HRS+ENUM and subtracts the threshold hours limit in ZOVBR using HRS-CZOVBR and adds the difference to WT M807. Finally, the overtime hours for the current day (WT M806) are again read using HRS=ENUM and then added to cumulative monthly overtime hours using ADDDBZAD4Z. Function PZL finally deletes the WT M806 which was present before during input.
The function PZL and PCR ZAD5 are finally placed in the time schema as shown below:
The solution design and build is finally complete and hence, let us now test it.
We have created the overtime hours in IT2002 for the employee using attendance type 0801 for the entire month.
The time evaluation is run for the month of Sep’13. Let me show you the processing for date 21-Sep-13 where 3 overtime hours of WT M806 get split into 2 overtime hours of WT M806 and 1 overtime hour of WT M807.
Processing and Output Table
Let us now view Table ZL.
Let us execute report RPTBAL00 as shown in the screenshot below:
Here, I come to the end of this knowledge artifact.
It’s been a long document and hence, thanks for your patience to go through it. I got to learn a new functionality in time because of this requirement and I hope this has been beneficial for you too.
You can also refer to other knowledge artifacts created by me at the below link: