HR Overtime: Detect, Approve, Compensate
Overtime auto-detected from attendance, routed through a configurable approval workflow, and compensated as pay or time off in lieu.
Why this module
HR Overtime: Detect, Approve, Compensate
Overtime that finds itself
A generation service reads the attendance day projection and creates one overtime entry for every day with positive overtime minutes, converting minutes to hours. Re-running it never duplicates: a per-day uniqueness constraint and a search guard keep generation idempotent over any date range.
Approval, not honour system
Every entry moves through a workflow whose states and transitions come from data. The employee submits, an HR manager approves, refuses, or marks it compensated. Each transition is group-gated and emitted to the platform audit log, so who advanced what is never in doubt.
Pay or time in lieu, your rule
Choose paid out or time off in lieu per entry, and set the multiplier as a field rather than a buried constant. Compensated hours are computed and stored as hours times multiplier, so a 1.5x rule on two hours reads as three compensated hours on the list view.
Day in the life
From a long shift to a clean payroll-ready record
Friday a technician works ninety extra minutes; the attendance day projection records the overtime minutes. Over the weekend the generation service is run for the week and creates a single auto-sourced overtime entry of 1.5 hours, linked back to that attendance day. Monday the employee opens it, adds a reason, and submits. The HR manager reviews, sets the entry to time off in lieu, approves, and marks it compensated. The entry is now final, its multiplier and compensated hours visible at a glance, and every step from creation to completion sits in the append-only audit trail under the right company.
Edge cases
The cases most modules quietly ignore.
In the shipped code today, each one a place where a cheaper module silently does the wrong thing.
The generation service guards every attendance day with a search-count check and the model carries a unique(attendance_day_id) constraint, so re-running over an overlapping date range creates zero duplicates and returns a count of new entries only.
Compensated and Refused are marked final in the workflow definition. The engine refuses any further transition out of a final state, even one a misconfigured definition might declare, so a completed or refused entry cannot be quietly re-opened.
Submit is restricted to the employee self group; approve, refuse, and mark-compensated are restricted to the HR manager group. A user outside a transition's allowed groups is rejected with a clear error rather than silently advancing the record.
Entries inherit the company-aware mixin: company is required and defaults to the active company, and a write that moves a record into a company the user does not belong to is refused unless an explicit, audited cross-company override is set.
State, employee, date, hours, multiplier, and compensation changes are captured to a sha256 hash-chained audit log. Each row hashes the previous row, so any silent edit downstream breaks verify_chain and is detectable.
A check constraint rejects negative overtime hours at the database level, so neither manual entry nor a bad generation run can persist a negative figure.
Auto-generated hours are computed from attendance overtime minutes divided by sixty and rounded to two decimals, so ninety recorded minutes lands as a clean 1.5 hours.
What is inside
Built to do the job, end to end.
- Composes the platform engines. The overtime model inherits the workflow, audited, and company-aware mixins plus mail thread. It declares no state machine, approval, or audit logic of its own; the shared EH HR Platform engines do the work, which is why behaviour is consistent with the rest of the suite.
- Data-defined workflow. Draft, Submitted, Approved, Compensated, and Refused states and their transitions ship as data records against a workflow definition keyed eh.hr.overtime. Steps and the groups allowed to fire them can be reconfigured without touching Python.
- Attendance generation service. A registered service, eh.hr.overtime.generate, exposes generate_for_range(date_from, date_to, company) which scans attendance days with positive overtime minutes and creates linked entries. It is callable from a scheduler or by hand; this module ships the service, not a preconfigured cron.
- Sequenced references and chatter. Each entry gets an automatic OT/year/number reference from a company-shared sequence, tracks field changes in the chatter via mail thread, and links back to its source attendance day for traceability.
Honest about the edges
What this does not do, so nothing surprises you.
- Requires the EH HR Platform: depends on eh_hr_core, eh_hr_compat, eh_hr_engine_workflow, and eh_hr_attendance_pro. It is not a standalone overtime app.
- Auto-detection reads the eh.hr.attendance.day projection from eh_hr_attendance_pro; without attendance data captured there, only manual entries are possible.
- The generation service must be invoked by a scheduler or manually. This module ships the idempotent service but does not install its own scheduled job.
- Overtime transitions are group-gated single-step approvals (employee submits, HR manager approves). The platform's multi-tier approval chains and self-approval guard are available in the engine but are not wired onto the overtime workflow in this module.
- Compensation is recorded as an attribute (paid or time off in lieu) with a multiplier and computed compensated hours. The module does not itself post to payroll or create leave allocations.
- Targets Odoo 18 Community.
Odoo 18 overtime, overtime management Odoo, attendance overtime detection, overtime approval workflow, time off in lieu Odoo, paid overtime tracking, overtime multiplier, HR overtime module, employee overtime requests, overtime audit trail, Odoo Community HR, attendance to overtime, overtime compensation, multi-company overtime, ERP Heritage HR
Need this fitted to the way you work?
ERP Heritage delivers end to end Odoo work: Odoo Implementation, Customization and Development, Integration, Migration, Consultation, Support and Training. We help teams put this module into production, shape it to their process, and keep it running.
We work with businesses across Australia (Melbourne, Sydney, Brisbane, Perth, Adelaide, Canberra) and the Middle East (Dubai, Abu Dhabi, Riyadh, Jeddah, Doha, Kuwait City, Muscat). Start a conversation at erpheritage.com.au or email info@erpheritage.com.au.
Languages
Available in 19 languages
The interface ships translated out of the box. Switch language in Odoo and the fields, menus, and messages follow.
Please log in to comment on this module