Skip to content
People · Attendance management module

An attendance management system that turns punches into payable hours

Your fingerprint terminals record thousands of punches a month. Payroll needs something much simpler, which is who worked, how long and who was late. An attendance management system sits between the two, and it's where most of the arguments happen. Describe your shifts and grace rules, and erpfly writes the Odoo addon or ERPNext app.

ERPNext v16

Works with ERPNext v15 and v16, and Odoo 17, 18 and 19.

Features

What your attendance management module can do

Device punches in, without CSV exports

A scheduled sync pulls logs from your biometric or RFID terminals and writes them against the right employee using the device user ID.

Shifts that cross midnight

Night shift punches get paired by shift window, not calendar date, so a 22:00 to 06:00 shift is one attendance and not two broken ones.

Late marks with your grace rule

Grace periods, late thresholds and early exits calculated per shift, with the minutes stored on the record so payroll doesn't recalculate them.

Missing punch handling

A check-in with no check-out raises a task for the supervisor next morning instead of silently becoming a 16-hour day.

Kiosk and mobile check-in

For sites without terminals, a kiosk screen or phone check-in with optional location, using the same rules as the devices.

The output

What actually gets generated

Real files in a real repository. Here’s the typical output when someone asks for attendance management.

ERPNext / Frappe app

  • Shift Type setup with auto attendance and grace periods
  • Device sync job writing Employee Checkin records
  • Custom late minutes field on Attendance as a fixture
  • Missing checkout ToDo job in scheduler_events
  • Monthly late and overtime Script Report

Odoo addon

  • hr.attendance inheritance with computed late minutes
  • Shift start and grace fields via _inherit on hr.employee
  • ir.cron job pulling punches from biometric devices
  • Device user mapping model with access rules
  • Inherited hr.attendance list and pivot views
shift_attendance/models/hr_attendance.py
import pytz

from odoo import api, fields, models


class HrEmployee(models.Model):
    _inherit = "hr.employee"

    shift_start = fields.Float(default=6.0, help="Hour of day, e.g. 6.5 for 06:30")
    grace_minutes = fields.Integer(default=10)
    device_user_id = fields.Char(help="User ID enrolled on the biometric terminal")


class HrAttendance(models.Model):
    _inherit = "hr.attendance"

    device_serial = fields.Char(readonly=True)
    late_minutes = fields.Integer(compute="_compute_late_minutes", store=True)

    @api.depends("check_in", "employee_id.shift_start", "employee_id.grace_minutes")
    def _compute_late_minutes(self):
        for att in self:
            emp = att.employee_id
            if not att.check_in:
                att.late_minutes = 0
                continue
            tz = pytz.timezone(emp.tz or "UTC")
            local = pytz.utc.localize(att.check_in).astimezone(tz)
            start = int(emp.shift_start) * 60 + round(emp.shift_start % 1 * 60)
            arrived = local.hour * 60 + local.minute
            # Past the grace period, lateness counts from shift start
            late = arrived - start
            att.late_minutes = late if late > emp.grace_minutes else 0
Trimmed excerpt. The full module includes tests, fixtures and a README.

How it works

From a paragraph to a pull request

The long version
  1. 01

    Describe it

    In your own words. Paste the spreadsheet or a photo of the paper form if that's easier.

  2. 02

    Answer a couple of questions

    It asks only what it can't work out from your setup, like who's allowed to override.

  3. 03

    Try it on a sandbox

    A copy of your site with the module installed. Break it, then ask for changes.

  4. 04

    Merge when it's right

    Code lands as a pull request with tests. Your developer, or ours, reviews it first.

A punch is not attendance

Terminals are good at one thing. They record that user 1047 put a finger on the reader at 05:58:12. That’s a punch. It isn’t attendance yet.

Attendance is the answer to a different question: did this person work their shift, and how much of it? Getting from one to the other means pairing punches, ignoring the double tap when someone isn’t sure the reader beeped, handling the night shift that starts on Tuesday and ends on Wednesday, and applying a grace rule people actually agreed to. That translation layer is where spreadsheets get built, and it’s what we generate.

How an attendance management system works in Odoo and ERPNext

ERPNext with Frappe HR already has a solid model for this. Raw punches land as Employee Checkin records with a log type and device ID. A Shift Type defines the start and end, the grace period for late entry and early exit, and the working hours below which a day becomes half-day or absent. Auto attendance then marks Attendance records on a schedule. For device sync, there’s an open-source tool, and our guide to ERPNext biometric attendance integration walks through it. Most of our ERPNext work here is configuration plus code for the rules Shift Type can’t express.

Odoo keeps it simpler. hr.attendance stores a check-in and a check-out, the kiosk mode is in Community, and Odoo calculates overtime against working schedules. There’s no native biometric sync and no lateness rule beyond what you configure, so we add both through an addon: employee fields, a computed late value and an ir.cron job that talks to the devices.

Worked example: two shifts, three terminals and one argument about grace

Picture a distribution centre with 90 staff on two shifts, 06:00 to 14:00 and 14:00 to 22:00, and three fingerprint terminals at the gates. They run Odoo Community.

The operations manager and HR had a long debate about grace periods. Here’s where they landed. Arriving within 10 minutes of shift start is fine and counts as on time. Arriving after that is late, and the late minutes count from 06:00, not from 06:10. Their reasoning was that otherwise everyone just learns to arrive at 06:09.

So on Monday:

  • Ravi punches at 06:07. Late minutes: 0.
  • Maria punches at 06:14. Late minutes: 14, not 4.
  • Joel punches at 05:58, then again at 05:58 because he didn’t hear the beep. The sync keeps the first punch and drops the duplicate.

The code on this page does the lateness part. Times in Odoo are stored in UTC, so the check-in is converted to the employee’s timezone before comparing. Skip that step and everyone in a UTC+4 site looks four hours early, which is flattering but useless. The device sync, duplicate filter and missing-checkout task are separate files in the same addon. Each employee carries their assigned shift start, so moving someone from mornings to afternoons is a field change, not a code change.

Before you buy more fingerprint readers

Tracking to the second. Nobody pays by the second. Round consistently, write the rounding rule down, and move on.

Geofencing office staff. For field teams, a location stamp on mobile check-in makes sense. For an office of 20, it mostly signals distrust and drains phone batteries.

Letting supervisors edit punches. Corrections should be a separate request with a reason and an approver, not a quiet edit of the raw log. Once raw punches are editable, every dispute becomes your word against theirs.

Building payroll inside attendance. Attendance should produce clean hours and late minutes. Money belongs in payroll.

Where attendance goes next

Late minutes and overtime hours are inputs, not outputs. They feed HR and payroll, and absences need to reconcile with approved time off in leave management, otherwise someone on approved leave gets marked absent. If your staff check in at customer sites, look at field service. Logistics operators running round-the-clock shifts should read our page on ERP for logistics companies.

Guides and terms for attendance management

Terms used on this page

Attendance management module questions

Something missing? Email [email protected] and a person will answer.

Which biometric devices can you connect to?

Most terminals that expose their logs over the network, including ZKTeco and similar devices that many sites already have. ERPNext has an open-source sync tool that writes Employee Checkin records. For Odoo there's no built-in device sync, so we generate one. Tell us the model number first, because a few devices only export to USB.

Is attendance included in Odoo Community?

Yes. The Attendances app (hr.attendance) with kiosk mode is Community. Using attendance data in payslips needs Payroll, which is Enterprise.

How does ERPNext handle shifts and auto attendance?

In Frappe HR, Employee Checkin stores raw punches and Shift Type marks Attendance automatically based on grace periods and working hour thresholds. We configure that first and only add code for rules it can't express, like lateness counted from shift start.

What about local labour rules on breaks and overtime?

We generate whatever rule you give us, like unpaid breaks, maximum daily hours or weekly overtime thresholds. We don't decide what your labour law requires. Your HR lead or lawyer does, and they should review the rule text before it goes live.

Can we keep using our old time clock software during the switch?

Yes, and for a month you probably should. Run both, compare daily totals for a sample of employees, and switch off the old tool once the numbers match on normal days and on the awkward ones.

Do we own the device integration code?

You do. It's in your own repository, including the device sync. If you change terminal vendors later, your developer changes one adapter file, not the whole module.

Your next module is one paragraph away

Write it the way you’d explain it to a new hire. We’ll turn it into an app you can read, test and install.

ERPNext v16

Create your account

Free to start. No card needed.

By signing up you agree to our terms and privacy policy.