| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Project (project)
• Discuss (mail) • Attendances (hr_attendance) • Employees (hr) |
| Community Apps Dependencies | Show |
| Lines of code | 4431 |
| Technical Name |
eh_hr_attendance_jobcost |
| License | LGPL-3 |
| Website | https://www.erpheritage.com.au/ |
| Versions | 16.0 17.0 18.0 19.0 |
Attendance Job Costing
Cost every face-kiosk punch to a job, project, and task, so attendance time reaches the analytic ledger instead of a flat timesheet.
Why this module
Attendance Job Costing
Attendance time has no cost dimension
Standard hr.attendance records who and when, but not what job the hours belong to. Without an analytic account on the row, kiosk time never reaches job costing or project profitability and stays a flat clock card.
Capture the job at the moment of the punch
After the face match, the kiosk offers the worker's allowed jobs. One tap writes the analytic account, project, and task onto the attendance row that was just created, so the cost dimension is captured at source, not reconstructed later.
Workers only see jobs they are on
An allowed-analytic whitelist per employee limits the picker to valid jobs, a default job pre-selects the common case, and a company toggle forces the picker when every punch must be costed.
Day in the life
A site crew clocks in across two jobs
A labourer walks up to the kiosk, the camera matches the face, and the picker shows the two jobs that worker is assigned to. They tap the right one and the welcome screen returns. Behind the scenes the kiosk POSTs the selection to a device-token-protected endpoint, which writes the analytic account onto the attendance row and logs a kiosk event. The supervisor opens the attendance list, switches on the analytic column, and sees every punch already costed to a job. Hours flow into the analytic ledger with no manual timesheet entry.
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.
Both kiosk endpoints require a valid X-EH-Kiosk-Token matching an active terminal. A missing or unknown token returns 401, so the picker cannot be driven from an unregistered device.
The options endpoint only returns analytic accounts in the device company or shared (no company), and a punch is rejected with 404 if the target attendance or employee does not belong to the device company.
If an employee has an allowed-analytic list, the kiosk offers only those accounts and filters out archived ones. An empty list falls back to active company accounts, capped at 200 rows so the picker stays responsive.
A pre-selected default is only returned when that default account is actually inside the offered set, so a stale default that the worker is no longer allowed to use is never surfaced.
A model constraint blocks saving an attendance row whose task does not belong to the selected project, on both the kiosk path and the backend form, raising a ValidationError instead of writing a mismatched cost line.
The picker only interrupts the success screen when a job is genuinely needed (require toggle on, or more than one option). A skip button writes the default and re-arms the kiosk bounce-back timer so the screen clears like a normal punch.
What is inside
Built to do the job, end to end.
- Fields on hr.attendance. Adds eh_analytic_account_id (indexed), eh_project_id (indexed), and eh_task_id with a project-scoped domain. A model constraint keeps the task and project consistent.
- Employee defaults and whitelist. hr.employee gains a default analytic account, a default project, and a many2many allowed-analytic list that drives what the kiosk offers each worker.
- Company toggle and settings. res.company gets eh_hr_require_job_punch, surfaced in the attendance kiosk settings block via res.config.settings, to force the picker on every punch.
- Two kiosk endpoints. A controller exposes GET /eh_hr/kiosk/job/options to list jobs and POST /eh_hr/kiosk/punch/job to write the selection back, both token-gated, with a kiosk event logged on each job punch.
- Kiosk job picker JS and styling. A picker screen injected into the face kiosk shell intercepts the match response, shows the job list after a successful match, posts the choice, and returns to the welcome screen.
- Backend views. List and form views surface the analytic, project, and task columns next to the existing attendance fields, and the employee form exposes the defaults and allowed jobs under a Job costing group.
Honest about the edges
What this does not do, so nothing surprises you.
- Requires the ERP Heritage attendance base and face kiosk modules plus Odoo analytic and project; it is an add-on, not a standalone attendance app.
- Targets Odoo 17 Community. It is not packaged or tested here for other Odoo versions.
- The kiosk captures a single analytic account, project, and task per punch. It does not split one attendance span across multiple jobs.
- There is no time proration, cost-rate calculation, or billing engine. The module captures the analytic dimension and relies on standard analytic accounting downstream.
- There is no approval or escalation workflow. A captured job can be corrected by an HR administrator on the attendance form.
- Kiosk endpoints write with elevated rights gated by the device token and a company match. The module ships no extra security groups or record rules beyond that scoping.
- The picker offers analytic accounts; project and task can be set on the backend form but the shipped kiosk picker selects the analytic account only.
attendance job costing odoo 17, hr attendance analytic account, project time tracking attendance, analytic accounting attendance odoo, construction labour costing odoo, field attendance job costing, kiosk job picker odoo, billable hours attendance, face kiosk job costing, per employee allowed jobs, attendance project task odoo, odoo 17 community attendance addon
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