| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Attendances (hr_attendance)
• Discuss (mail) • Employees (hr) |
| Community Apps Dependencies | Show |
| Lines of code | 4006 |
| Technical Name |
eh_hr_face_kiosk |
| License | LGPL-3 |
| Website | https://www.erpheritage.com.au/ |
| Versions | 16.0 17.0 18.0 19.0 |
Face Kiosk Attendance
Turn any tablet into a self-hosted face clock-in kiosk that lives entirely inside your Odoo 16 database.
Why this module
Face Kiosk Attendance
Raw images never hit the server
The device computes the 128-dimension embedding locally and sends only that float array. Templates require a granted face consent record, and withdrawing consent deactivates every template in the same transaction with an audit log entry.
No subscription, no cloud round-trip
The whole flow lives inside your Odoo 16 database. Any modern browser on the local network becomes a kiosk through a public shell page at /eh_hr/kiosk/<site_code>, paired by a device token, with no app to install.
Convenience, not anti-spoofing
This identifies an enrolled face to make clocking in fast. It is not a liveness or anti-spoofing control: a printed photo or a screen can match, and a modified client can submit any embedding. We say so plainly so you deploy it for the right job.
Day in the life
Morning shift change at a warehouse site
Staff walk up to a wall-mounted tablet showing the kiosk shell. Each person looks at the camera, the browser builds an embedding locally and posts it with the device token. The server cosine-matches against active templates for that company, sees no open attendance for the matched employee, and writes a check-in. If a per-site geofence is enabled, an off-site browser is rejected before any match runs. A low-confidence near-miss raises an attendance exception for a manager to review rather than silently clocking the wrong person. Every attempt, pass, and post lands in the kiosk audit log.
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.
Withdrawing a face consent deactivates every active template tied to it in the same transaction and writes a cascade entry to the audit log, so a later compliance review can prove what was deactivated and when.
A retention-sweep cron extends to face data: when a consent record expires, its active templates are deactivated in the same sweep, keeping stale biometrics out of the match pool.
The match endpoint is DB-backed rate-limited per token (or per client IP), so a leaked kiosk token cannot hammer the endpoint. Requests without a valid active device token return 401.
Templates are scoped by the device company. The match search filters on company_id, so a face enrolled in one company can never match at another company's kiosk.
When the best match sits above the configured distance threshold, no attendance is posted; instead a low-confidence identity attendance exception is raised for review, and the miss is logged.
A template cannot be created or reactivated unless its consent record is type face, belongs to the same employee, and is in granted state. The embedding is validated as a numeric JSON array of the declared dimension.
If a site enforces a geofence and the client sends no usable coordinates, the match is refused with a geofence_required reason and the failure is logged rather than falling through to a match.
What is inside
Built to do the job, end to end.
- eh.hr.face.template model. Stores the JSON embedding, declared dimension, model identity and version, capture method, quality score, company, and a required link to a granted face consent record. Validations enforce numeric arrays and consent type and employee match.
- Match and shell controllers. A public POST endpoint at /eh_hr/kiosk/face/match authenticated by an X-EH-Kiosk-Token header, plus a public kiosk shell page at /eh_hr/kiosk/<site_code> that serves face-api.js and the kiosk assets with an mtime-based cache-busting version stamp.
- HR-admin enrolment wizard. An OWL-driven multi-sample capture wizard that grants or reuses a face consent, requires an explicit consent acknowledgement, and stores three to five samples per employee as individual templates for varied lighting and angles.
- Employee integration. hr.employee gains a computed face-enrolled flag driven by active template existence, an active-template count, and actions to open enrolment or review templates per employee from the employee form.
Honest about the edges
What this does not do, so nothing surprises you.
- Not an anti-spoofing or liveness control: a printed photo or a screen showing an enrolled face can match, and a modified client can submit any embedding. Use it for convenience, not to prove who physically attended.
- face-api.js is not bundled. The model files are sizable and operators may want a specific release, so you run the one-time setup in static/lib/face-api before the kiosk works.
- Match accuracy depends on the device camera, lighting, and enrolment quality. Three to five samples in varied conditions are recommended for reliable matching.
- The match runs a linear cosine scan over active templates per company. This is fine for dozens to low hundreds of employees per site; very large populations (roughly 2k+ templates) would want a vector index.
- Requires the eh_hr_attendance_base and eh_hr_core suite modules and Odoo's hr_attendance. It is part of an attendance suite, not a standalone drop-in.
- The kiosk shell is a public page secured by a device token from the pairing flow, not by an Odoo login. Treat device tokens as credentials.
face recognition attendance odoo 16, biometric clock in odoo, kiosk attendance odoo, face api js odoo, contactless attendance, no badge attendance, self hosted face kiosk, employee time clock odoo 16, tablet attendance kiosk, consent gated biometric attendance, geofenced clock in, hr attendance face match
Please log in to comment on this module