Back to Blog

July 28, 2026

How a Rounding Edge Case in Odoo Quietly Miscounted Overtime for Split-Shift Workers

Odoo fixed a bug in its HR Attendance module where employees working multiple shifts per day had their overtime incorrectly calculated against the company tolerance threshold, resulting in phantom overtime entries that should have been absorbed by the tolerance window.

Diagram showing how Odoo HR Attendance calculated overtime incorrectly for split-shift workers before the fix versus the corrected behavior after flattening overtime values

There’s a category of ERP bug that never shows up in testing because the test scenario is always a single, clean eight-hour shift. The employee clocks in at 9, clocks out at 5, and the overtime math works perfectly. But the moment you introduce split shifts — a morning block, a gap, and an afternoon block — the arithmetic starts doing things nobody intended.

That’s exactly what happened inside Odoo’s HR Attendance module. For companies that set a “Tolerance Time in Favor of Company” (say, 15 minutes), the system was supposed to absorb small overtime overages. Work 8 hours and 12 minutes? That 12 minutes falls under the tolerance threshold, so no extra time gets recorded. Simple enough in theory. But when an employee split their day across two attendance records, the tolerance logic broke down in a way that silently inflated overtime.

The Scenario That Broke It

Here’s the setup that triggered the bug. An employee works two shifts in a single day: 8:00 AM to 3:00 PM (7 hours), then 4:00 PM to 6:12 PM (2 hours and 12 minutes). Total time worked: 9 hours and 12 minutes. With an 8-hour expected day, that’s 1 hour and 12 minutes of total overtime — but the way it was distributed across the two shifts caused the problem.

The first shift ran short of the 8-hour target, so the system calculated a negativeovertime value for that block. The second shift’s post-work time then compensated for the deficit, bringing the total to a net 12 minutes of overtime. Under a 15-minute tolerance, that 12 minutes should vanish entirely. No overtime logged. The employee worked a normal day with a slightly long afternoon.

But Odoo wasn’t aggregating the values before applying the tolerance check. Instead, it evaluated the post-work time from each shift independently against the tolerance threshold. The second shift’s raw post-work contribution — taken in isolation — exceeded 15 minutes, so the system flagged it as overtime. The negative value from the first shift and the positive value from the second were never “flattened” into a single number before hitting the tolerance comparison.

Why This Was Hard to Catch

The reason this bug persisted is that it only manifests under a specific combination of conditions. You need a company tolerance configured. You need an employee with multiple attendance records in a single day. And you need the total overtime to be small enough that it shouldfall under the tolerance — but large enough in one of the individual shifts to trip the threshold when evaluated alone.

For companies where employees clock in once and clock out once, this bug never fires. For companies without tolerance configured, it doesn’t matter. It only hits the intersection of split-shift scheduling and tolerance-based overtime policies, which is common enough in hospitality, healthcare, and retail but rare enough in test suites that it went undetected.

What makes it particularly insidious is that the resulting overtime numbers looked plausible. An extra 12 minutes here and there doesn’t trigger alarms the way a 3-hour discrepancy would. Payroll teams processing hundreds of employees per cycle are unlikely to notice that Maria’s Tuesday overtime should have been zero instead of 12 minutes, especially when other days have legitimate overtime entries.

The Fix: Flatten Before You Compare

The correction itself is elegant in its simplicity. Before the tolerance threshold comparison runs, the system now “flattens” the overtime duration and post-work time values across all attendance records for the day. Instead of checking whether each shift’s individual contribution exceeds the tolerance, it sums them first and checks the aggregate.

In the example above, the negative overtime from the short first shift and the positive post-work from the long second shift combine to produce a net 12 minutes. That 12-minute aggregate is then compared against the 15-minute tolerance. It’s under the threshold, so no overtime is recorded. The employee’s record accurately reflects a standard workday.

This is the same approach that had already been applied to the “Tolerance Time in Favor of Employee” calculation (the mirror setting that absorbs small under-time), where a similar bug had been caught and fixed earlier. The company-side tolerance just took longer to surface because the conditions that trigger it are slightly less common in typical testing scenarios.

Who Should Care About This

If your organization uses Odoo’s HR Attendance module with the company tolerance setting enabled, and any of your employees work split shifts, this fix directly affects your payroll accuracy. The impact per employee per day is small — a few minutes of phantom overtime — but it compounds across pay periods and headcount. A 200-person hospitality operation with 30% of staff on split shifts could easily accumulate several hours of incorrect overtime per month.

The fix is available now and rolls out as part of the standard update cycle. There’s nothing to configure — the flattening logic applies automatically when multiple attendance records exist for the same employee on the same day. If you’ve been running with this bug, you may want to audit recent payroll periods for affected employees to identify any overcounted overtime.

Ready to experience Odoo AI?

Join hundreds of teams using DearERP to customize Odoo in minutes, not weeks. Plans start at $29/month.