HR Attendance Pro for Odoo 18
Event-sourced attendance with an immutable log, a rebuildable day projection, kiosk and mobile capture, and workflowed corrections.
Why this module
HR Attendance Pro for Odoo 18
History you cannot quietly rewrite
Every tap lands once in an append-only log guarded against edits and deletes. Amendments go through a correction workflow that writes new events linked back to the request, so the record of what happened stays intact and auditable.
Payroll-grade day numbers, derived not typed
A compute service pairs check-ins with check-outs, applies the shift, rounding, and grace rules, and upserts one day row per employee per date. It is idempotent: re-running converges, so late biometric events and offline kiosk catches reconcile cleanly.
Reads as normal Odoo attendance
Derived sessions project into standard hr.attendance, so payroll, reporting, and other modules just work while the event chain stays the source of record. Rows you create by hand in core attendance are never touched.
Day in the life
A shift from tap to timesheet
An employee taps in at the door kiosk; the device sends a signed batch and the event is deduped on its correlation id, tagged with timezone and matched against a geofence. Another clocks in from the mobile app with an idempotency key. Through the day, breaks and check-outs append to the log. The compute service derives each person's day: worked minutes net of breaks, late and early-leave against the rostered shift, overtime past a full day, status of present, partial, absent, leave, or day off. A missing check-out raises an anomaly that notifies the line manager. The employee files a correction with a reason and a photo; it runs the approval chain, and on apply the system creates the corrected events rather than editing the originals. Overnight, the reconcile cron recomputes the trailing days so anything that arrived late settles.
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.
Every event carries a correlation id with a UNIQUE constraint. Replays from a flaky kiosk, a retried mobile post, or a re-sent webhook batch dedupe silently instead of double-counting.
The event model blocks writes to value fields and refuses deletes outside the retention path. Attendance data is amended only through the correction workflow, which appends new events.
Events after midnight that are the tail of an overnight shift are attributed to the correct civil date using the shift end time, not the wall-clock day they happened on.
The day projection is keyed on (company, employee, date) and upserts. The nightly reconcile cron recomputes trailing days in batches of 200 with a commit between batches, so a worker restart does not lose progress and re-running converges.
Clock times round to a configurable increment by nearest, up, or down, and the first in or last out can snap to the rostered time when it falls inside the grace window, so paid time is measured from the schedule, not a tap that was two minutes off.
Kiosk tokens are short-lived HMAC-SHA256 JWTs, device events are throttled, endpoints are rate limited in the database across workers, and the employee directory is gated behind a per-device flag and a server-capped page size so a leaked token cannot pull names and photos.
Record rules scope events, days, and corrections to self, team, and company; shift rosters are isolated per company. Device resolution rejects a device whose company does not match the employee.
Re-applying an approved correction is a no-op: produced events embed the correction id in their correlation id, so the UNIQUE constraint rejects duplicates.
The retention cron archives events past the configured window, then after a grace period exports them to a CSV attachment before purging, so old rows leave hot reads without vanishing from the audit trail.
What is inside
Built to do the job, end to end.
- Immutable event log. eh.hr.attendance.event is append-only with a UNIQUE correlation id, covering and partial indexes for day-window scans, write and unlink guards, and source tagging for manual, kiosk, mobile, biometric, import, webhook, and correction.
- Derived day projection. eh.hr.attendance.day holds one row per employee per date with worked, break, late, early-leave, and overtime minutes, status, anomaly codes, and the policy version used, rebuildable from events at any time.
- Compute and projection services. An idempotent compute service resolves shift and thresholds, pairs intervals, applies rounding and grace, and upserts the day. A projection service mirrors paired sessions into standard hr.attendance and retires sessions that no longer exist.
- Kiosk, mobile, and webhook capture. JSON endpoints for kiosk pairing and signed event batches, a mobile clock-in with required idempotency keys, and an HMAC-verified webhook for biometric vendors and HRIS, all funneling through one ingest pipeline.
- Shifts, rosters, and geofences. Shifts carry grace, overtime, rounding, overnight, and a working calendar. Per-employee per-day assignments override the company shift with the shortest covering range winning. Geofences match events by haversine distance.
- Corrections, anomalies, and crons. Corrections run a declared workflow with a serial approval chain and escalation, producing linked events on apply. Anomaly detection flags missing taps, overlaps, and over-long days and notifies managers. Nightly reconcile and retention crons keep data converged and trimmed.
Honest about the edges
What this does not do, so nothing surprises you.
- Targets Odoo 18 Community. The kiosk, mobile, and webhook endpoints are JSON APIs; client apps and biometric device integrations are configured separately and are not bundled.
- Workflow state machine, approval chains, late and overtime policy constants, and notification dispatch live in the platform engine modules this app depends on, not inside this module. It owns ingestion, derivation, and the surfaces.
- Leave-aware status uses the platform leave projection when present and falls back to core hr.leave validated requests otherwise; it does not compute leave itself.
- Geofence matching is a linear scan over active fences per company, which is fine for typical fleet sizes; very large fence sets would benefit from a spatial index that is not yet built.
- The off-shift anomaly code is reserved and conservative on this branch; it does not currently flag early-arrival as off-shift.
- Kiosk secrets are stored via ir.config_parameter and are encrypted at rest only if the operator has wired database-level encryption; the module does not add its own field encryption layer.
odoo 18 attendance, odoo attendance tracking, odoo time clock, employee check in check out odoo, odoo kiosk attendance, biometric attendance odoo, geofence attendance odoo, odoo overtime calculation, late arrival tracking odoo, shift scheduling odoo, attendance correction approval odoo, odoo attendance app community, multi company attendance odoo, mobile attendance odoo, attendance audit log odoo
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