Security model
What Employee Document Expiry can read and write, what it stores, and what leaves your instance.
Passport numbers, visa numbers and national ID numbers are personal data of the most sensitive kind. This module is built on the assumption that they must not be visible to the whole staff, and that the default must be restrictive.
Groups
Both live under Employee Documents in the user form.
User
- Read, write, create on hr.employee.document
- Read only on hr.document.type — they need the list in order to file a document, and nothing more
- No delete, on either model
Manager
Implies User, and adds:
- Delete on hr.employee.document
- Full control of hr.document.type
- Visibility of every employee in their allowed companies
A user in neither group cannot read either model at all, and the menus are hidden.
Record rules
| Rule | Group | Domain |
|---|---|---|
| Own and direct reports | User | employee_id.user_id = user OR employee_id.parent_id.user_id = user |
| Company | Manager | company_id = False OR company_id in company_ids |
Odoo ORs rules that come from different groups, so a Manager sees the union — in practice, their companies. A plain User sees only their own documents and those of the people who report directly to them.
This is deliberately narrower than Odoo's own HR visibility. An HR Officer who can see every employee record does not automatically see every passport number; they need the Manager group for that.
Multi-company
company_id is a stored related field from the employee, indexed. The manager rule is scoped to company_ids, which is the allowed companies of the user — so a user who belongs to two companies but has only one active sees both in searches, exactly as Odoo behaves everywhere else.
A document belonging to a company the user has no access to is invisible, and this is covered by an automated test.
Deletion and personal data
employee_id is declared ondelete="cascade". Deleting an employee deletes their documents in the same transaction. Personal data does not outlive the record it belongs to. This is tested.
Uninstalling the module drops both tables and everything in them.
Attachments (Scans) are ordinary ir.attachment records and follow your existing attachment access rules and storage configuration — including filestore or S3 if you use one.
What the module never does
- No outbound network calls of any kind.
- No external Python dependencies, so no third-party code enters your stack.
- No sudo() on user-facing reads. sudo() is used in exactly two places: the daily cron (which must see every company) and the settings counters (which show totals, not records).
- No monkey-patching of core Odoo classes.
- Nothing is written to the server log except reminder counts and genuine errors. Document numbers are never logged.
Emails
The reminder email is sent through Odoo's own mail queue with your own outgoing mail server. It contains the employee name, document type, number, expiry date and department. If your policy forbids document numbers in email, either remove that row from the mail template (Settings → Technical → Email → Templates) or turn off Send Reminder Emails entirely and rely on activities, which never leave the database.
Reporting a vulnerability
Email info@technovision.dev with the details. Please do not open a public issue.