| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Lines of code | 78 |
| Technical Name |
eh_hr_compat |
| License | LGPL-3 |
| Website | https://erpheritage.com.au |
| Versions | 16.0 17.0 18.0 19.0 |
| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Lines of code | 78 |
| Technical Name |
eh_hr_compat |
| License | LGPL-3 |
| Website | https://erpheritage.com.au |
| Versions | 16.0 17.0 18.0 19.0 |
EH HR Compatibility
One authored source, version-portable across Odoo releases.
Why this module
EH HR Compatibility
Branch once, here, not everywhere
Version-specific facts are resolved a single time from odoo.release.version_info and exposed as constants like CONTRACT_MODEL. Feature modules import the constant instead of scattering if-version checks through their own code.
Nothing to maintain twice
This module defines no models, holds no singletons or caches, and imports nothing from the rest of the platform. It is importable before the Odoo registry is even built, so it carries no business logic and no data to reconcile.
Renames that refuse to drop data
safe_field_rename only renames a column when the old name exists and the new one does not, checked against information_schema first. A re-run or a partially-applied upgrade is a no-op instead of a data-loss event.
Day in the life
A developer points one HR codebase at a different Odoo series.
A model that used to read hr.contract now needs hr.version on a newer Odoo, and res.users.groups_id has become group_ids. Instead of editing every call site, the feature modules already import CONTRACT_MODEL and call user_groups() and groups_field() from this layer, which pick the right name from the live _fields at runtime. A pre-migrate script calls safe_field_rename to move a renamed column, and because the column was already renamed on a prior attempt the helper simply returns False and moves on. An admin screen needs the access-level dropdown that Odoo builds from an implication chain of groups; setup_access_dropdown wires the groups to a shared category on older Odoo or to a res.groups.privilege on the newer series where category_id was removed, looking records up by name so a re-install does not duplicate them. Nothing in the feature modules had to know which Odoo it landed on.
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.
safe_field_rename queries information_schema for both the old and new column names and only renames when the old exists and the new does not. Re-running a migration, or running it against a database that was already upgraded, is a safe no-op that returns False rather than erroring or destroying data.
user_groups, group_users and groups_field read the live _fields of the record to decide between groups_id and group_ids, and between users and user_ids, so the same call works whether the security-groups field was renamed in the running series or not. No hardcoded version comparison is used for the read path.
setup_access_dropdown detects whether res.groups exposes privilege_id or category_id and writes the access-level grouping to whichever exists, creating the category or privilege only if a record of that name is not already present. Missing group xmlids are filtered out instead of raising, so a partial install does not abort the helper.
The shim imports only odoo.release and touches no environment, records or models at import time, so it loads before the registry is built. It deliberately avoids any import from other platform modules, which keeps it free of circular-dependency and load-order surprises.
legacy_view_mode returns action view_mode strings unchanged on Odoo 17 and later, and rewrites list to tree for older series, so a single authored view_mode string resolves to the vocabulary each series expects.
What is inside
Built to do the job, end to end.
- Models this module adds. None. There are no model classes, no _inherit, and no database tables. The module is two Python files of constants and pure helper functions plus the package __init__.
- What it actually exposes. Constants ODOO_VERSION, IS_17_PLUS, IS_18_PLUS, IS_19_PLUS and CONTRACT_MODEL, and functions tracking, legacy_view_mode, owl_import_path, safe_field_rename, user_groups, group_users, groups_field and setup_access_dropdown, all importable from odoo.addons.eh_hr_compat.
- Odoo dependencies. base only. It pulls in nothing else and imports nothing from the rest of the EH HR Platform, by design.
- Data, views and security. None. The manifest data list is empty and there are no XML, CSV, security or asset files. The only non-code assets are the listing icon and banner.
Honest about the edges
What this does not do, so nothing surprises you.
- This is plumbing, not a feature. On its own it changes nothing a user can see; it exists to be imported by the other EH HR Platform modules.
- It contains no business logic, no models, no fields, no automations and no scheduled jobs, so there is nothing to configure after install.
- It does not migrate data by itself. safe_field_rename is a helper that your migration scripts call; the module ships no migration scripts of its own.
- The tracking helper supports the modern tracking=True form only. The older track_visibility shape is documented for shape, not actively supported.
- owl_import_path returns the current OWL import string and is intended for a separate build-time JS transformer; this Python package does not rewrite JavaScript.
- The build version is 1.0.0 and the version-specific helpers are written against the Odoo 18 baseline and the renames on either side of it; behaviour on a series this branch does not target is out of scope.
odoo 18 hr compatibility, odoo version shim, hr.contract hr.version rename, groups_id group_ids odoo 19, odoo safe column rename migration, idempotent pre-migrate script, odoo list tree view_mode, version agnostic odoo addon, res.groups privilege_id, odoo api compatibility layer, stateless odoo module, eh hr platform
Please log in to comment on this module