Overtime

Overtime management in ERPNext v15

Install Overtime

bench get-app https://github.com/aliraxa29/overtime

Tags

  • erpnext
  • frappe
  • overtime
  • overtime-calculation
  • overtime-tracking
  • version-15

Add the Frappe Gems badge to your README

Maintain Overtime? Paste this into your README:

[![Listed on Frappe Gems](https://frappegems.com/api/method/frappe_gems.seo.badge?app=aliraxa29%2Fovertime)](https://frappegems.com/gems/apps/aliraxa29/overtime)

About Overtime

# Overtime Management for HRMS v15 [![CI](https://github.com/aliraxa29/overtime/actions/workflows/ci.yml/badge.svg)](https://github.com/aliraxa29/overtime/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/) [![Frappe v15](https://img.shields.io/badge/Frappe-v15-blue.svg)](https://frappeframework.com/) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md) A Frappe/HRMS v15 app that **automatically calculates overtime hours** from Employee Checkin records. Supports overnight shifts, Ramadan schedules with religion-based rules, configurable rounding, rate multipliers, and an approval workflow. --- ## Table of Contents - [Features](#features) - [Installation](#installation) - [Configuration](#configuration) - [Overtime Settings](#overtime-settings) - [Overtime Shift Rules](#overtime-shift-rules) - [Custom Fields](#custom-fields) - [How It Works](#how-it-works) - [Calculation Flow](#calculation-flow) - [Overnight Shift Handling](#overnight-shift-handling) - [Ramadan Mode](#ramadan-mode) - [Shift Rule Matching (Scoring)](#shift-rule-matching-scoring) - [Shift Schedule Reference](#shift-schedule-reference) - [DocTypes](#doctypes) - [Extending / Customization](#extending--customization) - [Troubleshooting](#troubleshooting) - [License](#license) --- ## Features | Feature | Description | |---|---| | **Auto-calculation** | Overtime calculated on Attendance submit via `doc_events` hook | | **Overnight shifts** | Full support for shifts crossing midnight (e.g. 23:30 → 07:30) | | **Ramadan mode** | Date-range activation with religion-based shift schedules | | **Shift rule scoring** | Weighted matching: period → religion category → shift type → department | | **Food/Suhoor breaks** | Configurable break deductions per shift rule | | **Grace period** | Late arrival / early departure tolerance (per shift rule) | | **Rounding** | Round Up, Round Down, or Round to Nearest (configurable interval) | | **Rate multipliers** | Separate rates for normal days vs holidays | | **Min/Max caps** | Minimum minutes threshold, maximum hours per day | | **Approval workflow** | Optional manager approval before overtime is finalized | | **Bulk operations** | Recalculate / bulk-submit overtime via API | | **Daily scheduler** | Fallback daily job to catch missed attendance events | | **Attendance sync** | Overtime hours and entry link written back to Attendance record | --- ## Installation ### Prerequisites - Frappe v15 - HRMS v15 (installed and configured with Shift Types and Employee Checkin) - Python 3.10+ ### Install ```bash cd $PATH_TO_YOUR_BENCH # Get the app bench get-app $URL_OF_THIS_REPO --branch develop # Install on your site bench --site your-site.local install-app overtime # Run migrations bench --site your-site.local migrate ``` The `after_install` hook automatically: 1. Creates custom fields on Employee and Attendance 2. Creates default Overtime Settings 3. Creates 7 default Overtime Shift Rules --- ## Configuration ### Overtime Settings Navigate to **Overtime Settings** (single DocType) to configure global behavior. | Field | Type | Description | |---|---|---| | `enabled` | Check | Master switch — disables all overtime processing when off | | `overtime_based_on` | Select | `Shift Hours` (scheduled vs actual) or `Fixed Hours` (fixed daily threshold) | | `minimum_overtime_minutes` | Int | Minimum minutes before overtime counts (e.g. 15 = ignore <15min) | | `max_overtime_hours_per_day` | Float | Daily cap (e.g. 4.0) | | `overtime_rounding` | Select | `No Rounding`, `Round Up`, `Round Down`, `Round to Nearest` | | `rounding_interval_minutes` | Int | Interval for rounding (e.g. 15 = round to 15-min blocks) | | `default_overtime_rate_multiplier` | Float | Normal-day rate (e.g. 1.5x) | | `holiday_overtime_rate_multiplier` | Float | Holiday rate (e.g. 2.0x) | | `require_approval` | Check | If enabled, entries are created as Draft for manager approval | | `auto_create_overtime_entry` | Check | Auto-create Overtime Entry on Attendance submit | | `ramadan_mode_enabled` | Check | Enable Ramadan period shift rules | | `ramadan_start_date` | Date | Ramadan period start | | `ramadan_end_date` | Date | Ramadan period end | ### Overtime Shift Rules Navigate to **Overtime Shift Rule** list to manage shift definitions. Each rule defines: | Field | Description | |---|---| | `shift_name` | Display name (e.g. "Morning", "Night") | | `applicable_period` | `Standard` or `Ramadan` | | `employee_category` | `All`, `Muslim`, or `Non-Muslim` | | `check_in_time` / `check_out_time` | Scheduled shift start/end times | | `is_overnight_shift` | Check if shift crosses midnight | | `allow_late_early_exception` | Enable grace period | | `late_early_grace_minutes` | Grace minutes for late arrival / early departure | | `has_food_break` | Deduct a food/suhoor break from working hours | | `food_break_duration_minutes` | Break length in minutes | | `food_break_type` | `Regular Break` or `Suhoor Break` | | `food_break_included_in_shift` | If checked, break is deducted from scheduled hours | | `shift_type` | Optional — link to HRMS Shift Type for matching | | `department` | Optional — restrict rule to a department | | `overtime_eligible` | Allow overtime calculation for this rule | ### Custom Fields Created automatically by `after_install`: | DocType | Field | Type | Description | |---|---|---|---| | Employee | `religion_category` | Select | Muslim / Non-Muslim | | Attendance | `overtime_hours` | Float | Auto-filled overtime hours | | Attendance | `overtime_entry` | Link | Link to Overtime Entry | --- ## How It Works ### Calculation Flow 1. **Trigger**: `Attendance.on_submit` fires `hooks_handler.on_attendance_submit()` 2. **Settings check**: Load Overtime Settings; skip if disabled or auto-create is off 3. **Rule matching**: `get_applicable_shift_rule()` finds the best-scoring rule for this attendance 4. **Checkin retrieval**: Get Employee Checkin records linked to this Attendance (with fallback search) 5. **Duration calc**: Compute actual working hours from first-IN to last-OUT checkin timestamps 6. **Scheduled hours**: Calculate from shift rule's check_in/check_out times (handles overnight) 7. **Net overtime**: `actual_hours - scheduled_hours - food_break + grace_adjustment` 8. **Rounding**: Apply configured rounding method 9. **Caps**: Enforce `minimum_overtime_minutes` and `max_overtime_hours_per_day` 10. **Rate**: Apply `default_overtime_rate_multiplier` or `holiday_overtime_rate_multiplier` 11. **Create entry**: Insert Overtime Entry with all calculated fields ### Overnight Shift Handling **HRMS behavior** (critical to understand): When a Shift Type has `start_time > end_time` (e.g. 23:30 → 07:30), HRMS treats it as an overnight shift: - The `get_shift_timings()` function in HRMS detects `start_time > end_time` and enters the overnight branch - A checkin at **23:30 on Jan 15** gets `shift_start = Jan 15 23:30` and `shift_end = Jan 16 07:30` - A checkout at **07:30 on Jan 16** gets the **same** `shift_start = Jan 15 23:30` and `shift_end = Jan 16 07:30` - HRMS groups checkins by `(employee, shift_start)` and creates ONE Attendance record - The Attendance date is **Jan 15** (the `shift_start.date()`) **Our app handles this by:** - Using `is_overnight_shift` flag on shift rules to correctly calculate scheduled hours across midnight - The `_get_checkin_logs()` function searches by `shift_start` date for fallback matching - Duration is always calculated from full datetime timestamps (not time-only), so midnight crossing is automatic **Known HRMS edge case**: If `last_sync_of_checkin` on the Shift Type is set to a value less than the shift duration, overnight OUT checkins may be skipped. Ensure `last_sync_of_checkin` ≥ shift duration. ### Ramadan Mode When `ramadan_mode_enabled = 1` and today falls within `[ramadan_start_date, ramadan_end_date]`: 1. Shift rules with `applicable_period = "Ramadan"` get +100 priority in scoring 2. Muslim employees match rules with `employee_category = "Muslim"` 3. Non-Muslim employees match rules with `employee_category = "Non-Muslim"` 4. Rules with `employee_category = "All"` serve as fallback Outside the Ramadan date range, only `Standard` period rules are considered. ### Shift Rule Matching (Scoring) When multiple shift rules exist, the system picks the best match using a weighted score: | Criterion | Points | Description | |---|---|---| | **Period match** | +100 | Ramadan rule during Ramadan period | | **Category match** | +50 | Exact religion category match (Muslim/Non-Muslim) | | **Shift type match** | +30 | Rule's `shift_type` matches Attendance's shift | | **Department match** | +25 | Rule's `department` matches Employee's department | | **Fallback** | +10 | Rules with `employee_category = "All"` | The highest-scoring enabled rule wins. Ties are broken by the DB ordering. --- ## Shift Schedule Reference ### Standard Period (All Employees) | Shift | Check-in | Check-out | Overnight | Scheduled | Food Break | Grace | |---|---|---|---|---|---|---| | Morning | 07:30 | 15:30 | No | 8h (7.5h net) | 30min | 15min | | Evening | 15:30 | 23:30 | No | 8h (7.5h net) | 30min | 15min | | Night | 23:30 | 07:30 | **Yes** | 8h (7.5h net) | 30min | 15min | ### Ramadan Period — Muslim Employees | Shift | Check-in | Check-out | Overnight | Scheduled | Food Break | Grace | |---|---|---|---|---|---|---| | Factory Morning | 07:00 | 13:00 | No | 6h | None (fasting) | None | | Admin Morning | 09:00 | 15:00 | No | 6h | None (fasting) | None | | Factory Night | 00:00 | 19:30 | No | 19.5h (18.5h net) | 60min Suhoor | None | ### Ramadan Period — Non-Muslim Employees | Shift | Check-in | Check-out | Overnight | Scheduled | Food Break | Grace | |---|---|---|---|---|---|---| | Factory Evening | 16:00 | 00:00 | **Yes** | 8h (7.5h net) | 30min | None | --- ## DocTypes ### Overtime Settings (Single) Global configuration for overtime processing. One record per site. ### Overtime Shift Rule Defines shift schedules with check-in/out times, breaks, grace periods, and category/period qualifiers. Named as `{shift_name}-{employee_category}-{applicable_period}`. ### Overtime Entry (Submittable) Individual overtime records linked to Employee + Attendance. Named as `OT-{employee}-.####`. **Fields**: employee, attendance, attendance_date, shift, overtime_hours, rate_multiplier, payable_overtime_hours, status (Draft/Approved/Rejected), and complete shift/checkin details. --- ## Extending / Customization ### Adding New Shift Rules 1. Go to **Overtime Shift Rule** → New 2. Fill in shift name, times, period, category 3. Set `overtime_eligible = 1` 4. Save — the rule will be matched automatically by the scoring engine ### Custom Rate Logic Override `_get_rate_multiplier()` in `utils.py` if you need per-employee or per-department rates. ### Custom Hooks The app hooks into `Attendance.on_submit` and `Attendance.on_cancel`. If you need to add custom logic, extend `hooks_handler.py` or add your own `doc_events` in a separate app. ### Adding Department-Specific Rules Set the `department` field on a shift rule to restrict it. Department match adds +25 to the scoring, giving it priority over generic rules. --- ## Troubleshooting | Problem | Solution | |---|---| | No overtime calculated | Check **Overtime Settings** → `enabled` and `auto_create_overtime_entry` are checked | | Wrong shift rule applied | Check scoring: verify `applicable_period`, `employee_category`, `shift_type`, `department` on rules | | Overnight shift gives 0 hours | Ensure `is_overnight_shift` is checked on the rule; verify HRMS Shift Type has `start_time > end_time` | | Checkins not found | Ensure Employee Checkins have `attendance` linked, or `shift_start` set for fall

Related Other apps for Frappe & ERPNext

  • Erpnext — Free and Open Source Enterprise Resource Planning (ERP)
  • Helpdesk — Modern, Streamlined, Free and Open Source Customer Service Software
  • Print Designer — Visual print designer for Frappe / ERPNext
  • Ctr — CTR模型代码和学习笔记总结
  • Whitelabel — Whitelabel ERPNext
  • Fossunited — fossunited.org
  • Helm — Helm Chart Repository for Frappe/ERPNext
  • Frappe Attachments S3 — A frappe app to upload file attachments in doctypes to s3.