| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Discuss (mail)
• Employees (hr) • Attendances (hr_attendance) |
| Community Apps Dependencies | Show |
| Lines of code | 3587 |
| Technical Name |
eh_hr_visitor |
| License | LGPL-3 |
| Website | https://www.erpheritage.com.au/ |
| Versions | 16.0 17.0 18.0 19.0 |
Visitor Management
One reception tablet, two flows: staff attendance and guest sign-in, on one audit trail.
Why this module
Visitor Management
No second tablet, no second SaaS
The kiosk site and device pairing come from the attendance suite base. The reception tablet that runs staff attendance also serves visitor sign-in at /eh_hr/visitor/<site_code>, authenticated by the same device token. One piece of hardware, one bill, one audit trail.
NDA text frozen at sign-in
For NDA-required purposes the kiosk shows your configured NDA prose and stores the exact text on the visitor record at that moment. Reword the company NDA whenever you like; past visits keep the wording the visitor actually accepted, so an audit cannot drift.
Retention enforced in code
A daily cron deletes signed-out visitor rows past the company retention window, taking the NDA snapshot and any photo with the row. The privacy promise is enforced by the scheduler, not by paperwork or a reminder to a receptionist.
Day in the life
Visitor signs in. Host gets the email. Day continues.
A delivery driver pulls up to a reception tablet sitting on the visitor URL. They tap their name, organisation, and phone, pick Delivery, and because that purpose has NDA and photo off they tap Sign in straight away. The host is emailed through the standard mail queue with the visitor name, purpose, and visit number. The driver signs out at the same kiosk by entering their visit number. An afternoon contractor hits the Contractor purpose, which flips NDA and photo on: the kiosk shows the NDA, freezes the accepted text onto the record, and asks for a photo behind a consent screen before sign-in completes. At the company close hour the hourly cron catches a visitor who walked out without tapping out, signs them off, and flags the record as auto-signed-out so the register reads true overnight.
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.
action_sign_in skips any record already in signed_in, and action_sign_out skips anything not currently signed_in, so a double-tapped kiosk or a retried request cannot reopen or double-stamp a visit.
If the visit-number sequence has not been loaded on a fresh install, create() falls back to a timestamp-based number (V + YYYYMMDDHHMMSS) so the first sign-in still works before any data file has run.
The auto sign-out cron evaluates each company independently in its own partner timezone against its own close hour, so a multi-company database closes each site at the correct local time rather than one global cutoff.
Both the auto sign-out and retention crons process at most 500 rows per run and report progress through _commit_progress, so a large backlog is drained in bounded slices instead of one long transaction that could block the cron worker.
The bootstrap endpoint deliberately returns no host list. Host names come only from a typeahead that requires at least two characters, caps at ten matches scoped to the device company, and is rate limited, so a device token cannot bulk-pull the employee directory.
NDA acceptance is enforced both at the controller (sign-in is rejected with a 400 if the purpose requires an NDA and none was accepted) and in the ORM via an action guard and a model constraint, so a record cannot reach signed_in without the snapshot.
The retention sweep deletes only signed_out rows whose signed_out_on is past the cutoff, and the test suite proves the aged timestamp survives the ORM flush before the cron runs, so live visits and recently departed guests are never swept early.
Kiosk sign-out matches the visit number only within the calling device's company and only against still-signed-in visits, returning a clean not-found response rather than touching another company's register or re-signing-out a closed visit.
What is inside
Built to do the job, end to end.
- Models. eh.hr.visitor holds the visit: name, organisation, email, phone, host employee, purpose, sign-in and sign-out timestamps, state, NDA required and accepted flags, the NDA text snapshot, optional photo, notes, visit number, and company. It inherits mail.thread for chatter and tracking, with a computed duration in minutes. eh.hr.visitor.purpose carries the purpose name, a URL-safe code unique per company, sequence, and the NDA-required and photo-required toggles.
- Public kiosk endpoints. Routes under /eh_hr/visitor are authenticated by the kiosk device token, not the visitor. A shell page, a bootstrap call returning purposes plus NDA and photo consent text, a throttled host typeahead, and POST sign-in and sign-out endpoints. Every endpoint is rate limited per token and every sign-in and sign-out is written to the suite kiosk event log with the client IP.
- Two scheduled jobs. An hourly cron auto signs out visitors still on site past each company's configured close hour and marks the record. A daily cron deletes signed-out rows past the company retention window, removing the NDA snapshot and photo with the row. Both run as root, are batch-capped, and are isolated through cron progress reporting.
- Company settings. Per-company NDA text, photo consent text, auto-checkout on/off, close hour, and retention days, all exposed in Settings via res.config.settings related fields. Seeded defaults ship for the NDA and consent prose so the kiosk works the moment the module is installed.
- Backoffice and security. List, form, and search views with status decoration, an auto-signed-out ribbon, NDA and photo and notes tabs, and filters for signed-in, signed-out, today, last seven days, NDA accepted, and auto-signed-out. Four access tiers (user, manager, admin, auditor) reuse the suite groups, and a global record rule scopes visitors to the user's companies while letting purposes be shared or company-specific.
- Seeded data. Four starter purposes load on install: Meeting and Delivery (no NDA, no photo), Contractor (NDA and photo on), and Interview (NDA on). A shared visit-number sequence (V prefix, six-digit padding) and the host arrival email template ship in the same data set.
Honest about the edges
What this does not do, so nothing surprises you.
- Public-kiosk sign-out is by visit number only. Looking a visitor up by name to sign them out is done from the backoffice visitor form, not from the public kiosk endpoint.
- The host arrival email is sent only when the selected host has a work email; otherwise the module posts a note on the visitor chatter rather than emailing. There is no SMS or push notification channel.
- There is no pre-registration or expected-visitor invitation flow, no badge or label printing, and no QR or barcode check-in. Visitors enter their details at the kiosk at arrival time.
- Photo consent gating is enforced in the kiosk front end. The server stores the consent text and the captured image but does not itself re-prompt; a custom front end calling the endpoints directly is responsible for honouring consent.
- This module depends on eh_hr_attendance_base and eh_hr_core for the kiosk site, device pairing, rate limiting, and event log. It is not a standalone visitor app and does not run without the attendance suite installed.
- Retention and auto sign-out are driven by the standard Odoo cron. Deletion and end-of-day closing happen on the scheduler's cadence, not in real time at the moment a window elapses.
visitor management odoo, odoo 17 visitor sign in, front desk kiosk odoo, visitor log book odoo, nda capture visitor, contractor sign in odoo, reception kiosk hr attendance, host email notification visitor, visitor photo capture, visitor retention gdpr odoo, auto sign out visitor cron, multi company visitor register
Please log in to comment on this module