Hi everyone, I’m trying to show Overtime YTD balance on the payslip at all times in AU Payroll.
Right now, overtime hours (Work Entry Type: OVERTIME) are being included inside Basic Salary through payslip.paid_amount, so OT is calculated but does not appear as a separate line and no OT YTD is shown.
Odoo does not allow “Work Entry Type” as a condition in Salary Rules, so I can’t trigger a rule directly from OVERTIME without causing duplication.
Does anyone know the correct way to display Overtime YTD on the payslip consistently in AU Payroll?
Thanks!
Hello Syed,
Please find below step by step explanation:
Step 1: Create / Verify Overtime Work Entry Type
Path: Payroll → Configuration → Work Entry Types
Ensure you have a dedicated Work Entry Type, e.g.:
Name: Overtime
Code: OVERTIME
This Work Entry Type should already be used by the attendance / planning / timesheet flow that generates OT hours.
At this stage, OT hours exist, but they are still merged into payslip.paid_amount.
Step 2: Create a Custom Input Type for Overtime
Path: Payroll → Configuration → Input Types
Create a new Input Type:
Name: Overtime Hours
Code: OT_HOURS
(Optional) Description: Overtime hours coming from Work Entries
This Input Type will act as the bridge between Work Entries and Salary Rules.
Step 3: Convert Overtime Work Entries into Payslip Inputs
This is the key step.
You need to override / extend payslip input computation so that Overtime Work Entries are extracted separately.
Concept:
Loop through Work Entries on the payslip
Filter entries with Work Entry Type = OVERTIME
Sum their duration (hours)
Push the result into the OT_HOURS input
Typical Python Extension (Example)
This is done in a small custom module:
from odoo import models
class HrPayslip(models.Model):
_inherit = 'hr.payslip'
def _get_inputs(self, contracts, date_from, date_to):
inputs = super()._get_inputs(contracts, date_from, date_to)
for slip in self:
ot_hours = sum(
slip.worked_days_line_ids.filtered(
lambda w: w.work_entry_type_id.code == 'OVERTIME'
).mapped('number_of_hours')
)
if ot_hours:
inputs.append({
'name': 'Overtime Hours',
'code': 'OT_HOURS',
'amount': ot_hours,
'contract_id': slip.contract_id.id,
})
return inputs
Result: OT hours are now explicitly available as an Input, instead of being hidden inside Basic Salary.
Step 4: Create a Dedicated Salary Rule for Overtime
Path: Payroll → Configuration → Salary Rules
Create a new rule under the appropriate structure (e.g. Earnings):
Name: Overtime
Code: OT
Category: Allowance / Overtime (AU-specific category if required)
Condition:
Input
Input Code = OT_HOURS
Salary Rule Computation
Example (hourly OT rate already defined on contract):
result = inputs.OT_HOURS.amount * contract.overtime_rate
Or if OT is a multiplier:
result = inputs.OT_HOURS.amount * contract.wage * 1.5
Step 5: Ensure Overtime Is Excluded from Basic Salary
To avoid duplication:
Make sure Basic Salary rule only uses:
Normal worked hours
NOT payslip.paid_amount if OT is included there
If needed, adjust Basic rule logic to exclude OT Work Entry Types
This guarantees OT is paid once and only once.
Step 6: Enable YTD Tracking for Overtime
In the Overtime Salary Rule:
Ensure:
“Show on Payslip” = ✅
Rule has its own unique code (OT)
Category is consistent across periods
Odoo automatically:
Aggregates rule results by code
Displays Year-to-Date (YTD) totals on the payslip
No extra YTD logic is required once OT is a standalone Salary Rule.
Hope it helps.