EH HR Document
Employee documents with a live expiry status and a daily chatter reminder, on the same audited HR platform.
Why this module
EH HR Document
Status that never goes stale
Valid, expiring and expired are computed live from the expiry date and today, not stored, so the status stays right as the clock advances with no nightly refresh to trust.
Every change on the audit chain
Adding, editing or deleting a document writes a row to an append-only, hash-chained log you can verify on demand, so you can show who changed which document and when.
Records locked to their company
Each document carries a required company, and cross-company writes are refused even under sudo unless an explicit, audited override is set, so one company never edits another's records by accident.
Day in the life
A visa that does not lapse unnoticed
You record an employee's visa with its expiry date. From that moment the document shows Valid, and once it falls inside thirty days it flips to Expiring soon, highlighted amber in the list. Each day the expiry cron finds it in the window and posts a note to the document's chatter naming the date it expires. The day after expiry it reads Expired and turns red. Every one of those record edits is on the hash-chained audit log, and the whole register is scoped to the company that owns the employee.
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.
Documents left without an expiry date are treated as never-expiring: the status is No expiry and days-to-expiry is zero, and the daily cron skips them entirely rather than alerting on a blank date.
Audit rows are appended under a Postgres transaction-scoped advisory lock, so two concurrent edits cannot fork the hash chain; the lock releases automatically on commit or rollback.
Moving a document to a company the user does not belong to is rejected, and even a permitted cross-company write emits a dedicated audit row recording the new company and every affected record id before it proceeds.
Relational and date values in the before/after snapshot are coerced identically for both the stored payload and the hash material, so recordsets and dates never break serialization or the integrity chain.
The employee self group can read documents but cannot create, edit or delete them; officers can create and edit but not delete; only HR admin can remove a record, and the delete is itself audited.
Documents are linked to the employee with ondelete cascade, so removing an employee cleanly removes their document register without orphan rows, and each deletion is recorded in the audit log first.
What is inside
Built to do the job, end to end.
- Models this module adds. One model, eh.hr.document, holding the title, employee, document type, official number, issue date, expiry date and the computed days-to-expiry and status fields.
- Document types in the box. A fixed type list of Passport, Visa or permit, Licence, Contract, Certificate and Other, so the register stays tidy and reportable rather than free-text.
- The expiry cron. A daily ir.cron runs _cron_check_expiry, which searches documents expiring within thirty days and posts a chatter note on each so the reminder lives on the record.
- Platform foundations it stands on. Built on eh_hr_core and eh_hr_compat: the audited mixin for the hash-chained log and the company-aware mixin for strict multi-company scoping, plus standard Odoo hr and mail.thread chatter.
- Access and placement. Three access tiers (admin, officer, employee self) and a Documents menu under Employee Requests gated to the HR Officer group.
Honest about the edges
What this does not do, so nothing surprises you.
- The daily reminder is a note posted to the document chatter, not an outbound email or push notification; followers see it through standard Odoo chatter notifications.
- The expiring window is fixed at thirty days in code and is not exposed as a configurable setting in this module.
- There is no file upload or attachment field on the model itself beyond standard Odoo chatter attachments; it records document metadata and dates, not the scanned document as a managed field.
- The status and days-to-expiry fields are computed and not stored, so they cannot be grouped or filtered on directly in the database without adding a stored field.
- Document types are a fixed selection (passport, visa, licence, contract, certificate, other) and are not user-extendable from the interface.
- This module targets Odoo 17 Community and depends on eh_hr_core and eh_hr_compat; it is not a standalone add-on.
odoo employee document management, odoo document expiry tracking, odoo passport visa expiry alert, odoo hr document register, employee licence renewal reminder odoo, odoo 17 hr documents, odoo contract certificate tracking, odoo document expiry cron, hr document audit log odoo, multi company employee documents odoo
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