EH HR Disciplinary
Progressive discipline, acknowledged and audited.
Why this module
EH HR Disciplinary
The ladder does the counting
Each warning has a validity window. When you open a new case the module counts the employee's still-active warnings on that date and recommends the next step up the ladder (verbal, written, final). One button applies it, so the right level is a decision, not a guess.
An acknowledgement on the record
Issued warnings move to an acknowledge step gated to the employee themselves, and a free-text field records their response. The trail shows the warning was issued, seen, and closed, not just filed in a folder.
Changes you can prove
Every create, write and state change is written to an append-only, sha256 hash-chained log with a verify pass that flags the first edited row. Backdating or quietly softening a warning after the fact does not go unnoticed.
Day in the life
A repeat lateness case, start to close
A manager opens a disciplinary record for an employee. The form already shows two of that employee's warnings are still active, so the ladder recommends a final warning; one click applies it. The manager fills in the reason and issues the case, which is gated to HR managers. The employee opens their copy and acknowledges it, recording their response. HR closes the case once resolved. The warning carries a twelve month validity by default, after which it lapses and stops counting toward escalation. Every step, who issued, who acknowledged, who closed, lands in the hash-chained audit log, scoped to the employee's company.
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.
Each warning expires after its validity period (default twelve months). The active count and the ladder recommendation only consider warnings still inside their window on the new case's issue date, so old, lapsed warnings stop driving escalation automatically.
Cancelled cases are dropped from the active count and the escalation maths. A warning that was withdrawn never pushes the next case up the ladder.
When computing its own prior-active count, a saved record excludes its own id from the search, so a warning never counts itself toward its own escalation, even mid-compute on an unsaved NewId record.
Closed and cancelled are marked final in the workflow definition. The engine refuses any further transition out of a final state, even one a misconfigured definition might declare, so a closed case cannot be silently reopened.
Issue and close are gated to HR managers, acknowledge to the employee self group. A user outside a transition's allowed groups is refused, so the wrong person cannot advance someone else's case.
Records default to the user's company and cross-company writes are rejected without an explicitly audited override, closing the null-company leak that lets warnings bleed between companies.
The audit log takes a transaction-scoped Postgres advisory lock before appending, so two concurrent saves cannot fork the hash chain. The lock releases on commit or rollback.
Names come from a year-prefixed sequence assigned at create time and are read-only and non-copyable, so duplicating a record never reuses a reference.
What is inside
Built to do the job, end to end.
- One model, eh.hr.disciplinary. A single source-of-record model carrying employee, issuer, date, action type, severity, reason, acknowledgement, validity, expiry, active flag, prior-active count and recommended action. No parallel tables to reconcile.
- A data-driven workflow. Draft, issued, acknowledged, closed and cancelled states with issue, acknowledge, close and cancel transitions, all defined as workflow data records rather than hardcoded Python, so the steps and permissions are configurable.
- Escalation built in. Computed expiry date, an is-active flag, a count of the employee's other still-active warnings, and a recommended next action with a one-click apply button.
- Borrowed engine depth. Workflow, hash-chained audit and strict multi-company scope come from the shared platform mixins, so this small module inherits the same governance as every module beside it.
Honest about the edges
What this does not do, so nothing surprises you.
- This module manages disciplinary records and their workflow. It does not generate warning-letter PDFs or printed templates; the reason and acknowledgement are stored as text on the record.
- Warning lapse is computed live from the validity window, not driven by a scheduled job. There is no cron that flips a status or emails a reminder when a warning expires.
- The escalation ladder recommends a next step; it does not auto-issue the next warning or block you from choosing a different action type.
- This workflow has no built-in approval chain. Issue and close are permission-gated to HR managers, but there is no multi-step approver routing on a disciplinary case in this module.
- Acknowledgement is a workflow step plus a text field. It is not a signature-capture or e-signature feature.
- It depends on eh_hr_core, eh_hr_compat and eh_hr_engine_workflow, which install automatically. It is not a standalone add-on to plain Odoo HR.
Odoo HR disciplinary, employee warning management, progressive discipline Odoo, verbal written final warning, disciplinary action tracking, employee acknowledgement, warning expiry validity, escalation ladder HR, tamper evident audit trail, multi company HR Odoo, Odoo 19 HR module, self hosted HR discipline, HR misconduct record, warning letter workflow, Odoo Community HR
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