Health Screen for Face Kiosk
A configurable yes or no health declaration that runs at the attendance kiosk before face capture, denies entry on flagged answers, and keeps a snapshotted audit row of every declaration.
Why this module
Health Screen for Face Kiosk
The screen runs at the right moment
A kiosk shell hook intercepts the welcome screen the first time it appears, queries the health endpoint, and shows the questions before the face capture loop starts. A denied answer leaves the welcome screen hidden, so face capture never begins for that session.
Reword questions without breaking history
Each declaration stores a JSON snapshot of every question text, the yes or no answer, and the deny on yes flag at submission time. Future rewordings of a question do not corrupt past audit rows. Declaration rows are create plus delete only for managers and auditors, never editable.
Per company, no phone home
Questions and declarations are isolated by global company record rules, cadence and retention are per company settings, and questions with no company apply database wide. Endpoints authenticate with the kiosk device token and are rate limited. Runs entirely on your own Odoo.
Day in the life
A reception tablet on a shift change
An employee taps to clock in. Before the camera engages, the kiosk shows the active questions for that device's company. They answer no to feeling unwell, yes to fit for work, and submit. The server snapshots the answers, records an allowed declaration, logs a kiosk event, and the welcome screen returns so face capture proceeds. Had any deny on yes question been answered yes, the kiosk would have shown an entry not permitted screen, recorded a denied declaration, and held face capture. With once per day cadence, the next tap that day skips straight to the camera. A nightly cron deletes declarations past the company's retention horizon.
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.
Once per day cadence computes the local day start from the company partner timezone, converts it to UTC, and searches allowed declarations from that boundary, so a single declaration covers the full local day rather than a rolling 24 hours.
If the company timezone string is missing or invalid, the day boundary calculation falls back to UTC instead of raising, so the cadence check never breaks the kiosk.
The retention sweep walks companies one at a time, applies each company's own horizon (default 365 days), and stops at a batch limit of 2000 deletions per run so a large backlog does not run unbounded, reporting progress to ir.cron when invoked as a job.
Global ir.rule records scope questions and declarations to company_ids, while a question with no company set is visible to every company, so shared and company-specific questions coexist.
The answer snapshot stores the question text as it read at submission, so editing or deactivating a question later does not alter historical declaration rows. Declaration fields are readonly with no write access in the security matrix.
The submit endpoint tolerates non-list bodies with a 400, skips entries that are not dicts or carry non-integer question ids, and ignores ids that do not resolve to an existing question, recording only valid answers.
Both kiosk endpoints throttle by device token or client IP (120 reads, 60 submits) and reject calls without a valid active device token with a 401, so a public route is not an open door.
What is inside
Built to do the job, end to end.
- Two models, one snapshot. eh.hr.health.question holds the prose, sequence, deny on yes flag, active flag, and optional company. eh.hr.health.declaration holds one row per submission with the JSON answer snapshot, allowed or denied decision, kiosk site and device links, company, and a computed reference name.
- Two token-auth endpoints. GET /eh_hr/kiosk/health/questions returns the active questions, enabled flag, and cadence for the device's company. POST /eh_hr/kiosk/health/submit takes an array of answers, snapshots them, sets allowed or denied, creates the declaration, and logs a kiosk event.
- Kiosk shell hook. A template inherit injects the health stylesheet and script into the face kiosk shell. The script builds the question and deny screens, intercepts the welcome screen via a mutation observer, and resolves to proceed or block based on the server decision and cadence.
- Company settings and cron. Three company fields (enable, cadence, retention days) surface in Settings via related config fields. A daily code cron runs the retention sweep. Four health questions ship seeded inactive for the operator to activate and reword.
Honest about the edges
What this does not do, so nothing surprises you.
- This is a kiosk add-on, not standalone. It requires eh_hr_attendance_base, eh_hr_face_kiosk, and eh_hr_core, and it hooks the existing face kiosk shell rather than providing its own attendance device.
- Declarations are created at submission time, which runs before face identification, so declaration rows are not automatically linked to an employee. The employee field exists but is populated only if a flow sets it.
- A deny outcome records a denied declaration, logs a kiosk event, and holds face capture client side. It does not create a separate attendance exception record or send a notification.
- Questions are yes or no only. There are no free-text question answers, scoring, conditional branching, or weighting.
- The once per day skip relies on a client side localStorage marker for the every clock in versus once per day decision in the browser, alongside the server side already declared check. A cleared kiosk browser cache resets that local marker.
- Retention is a hard delete by company horizon. There is no archive, export, or soft delete of swept declarations.
- The module supplies the declaration mechanism and audit trail. It is not medical advice and does not assess fitness for work beyond recording the answers the operator's questions ask.
odoo kiosk health declaration, attendance health screening odoo, fitness for work declaration, deny entry attendance kiosk, covid screening odoo hr, health questionnaire face kiosk, notifiable illness check, odoo 19 community attendance health, workplace safety screen, hr attendance health declaration, health declaration audit trail, per company health screen cadence, kiosk health questions, self hosted hr health screen
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.
Please log in to comment on this module