Skip to Content
Odoo Menu
  • Sign in
  • Try it free
  • Apps
    Finance
    • Accounting
    • Invoicing
    • Expenses
    • Spreadsheet (BI)
    • Documents
    • Sign
    Sales
    • CRM
    • Sales
    • POS Shop
    • POS Restaurant
    • Subscriptions
    • Rental
    Websites
    • Website Builder
    • eCommerce
    • Blog
    • Forum
    • Live Chat
    • eLearning
    Supply Chain
    • Inventory
    • Manufacturing
    • PLM
    • Purchase
    • Maintenance
    • Quality
    Human Resources
    • Employees
    • Recruitment
    • Time Off
    • Appraisals
    • Referrals
    • Fleet
    Marketing
    • Social Marketing
    • Email Marketing
    • SMS Marketing
    • Events
    • Marketing Automation
    • Surveys
    Services
    • Project
    • Timesheets
    • Field Service
    • Helpdesk
    • Planning
    • Appointments
    Productivity
    • Discuss
    • Approvals
    • IoT
    • VoIP
    • Knowledge
    • WhatsApp
    Third party apps Odoo Studio Odoo Cloud Platform
  • Industries
    Retail
    • Book Store
    • Clothing Store
    • Furniture Store
    • Grocery Store
    • Hardware Store
    • Toy Store
    Food & Hospitality
    • Bar and Pub
    • Restaurant
    • Fast Food
    • Guest House
    • Beverage Distributor
    • Hotel
    Real Estate
    • Real Estate Agency
    • Architecture Firm
    • Construction
    • Property Management
    • Gardening
    • Property Owner Association
    Consulting
    • Accounting Firm
    • Odoo Partner
    • Marketing Agency
    • Law firm
    • Talent Acquisition
    • Audit & Certification
    Manufacturing
    • Textile
    • Metal
    • Furnitures
    • Food
    • Brewery
    • Corporate Gifts
    Health & Fitness
    • Sports Club
    • Eyewear Store
    • Fitness Center
    • Wellness Practitioners
    • Pharmacy
    • Hair Salon
    Trades
    • Handyman
    • IT Hardware & Support
    • Solar Energy Systems
    • Shoe Maker
    • Cleaning Services
    • HVAC Services
    Others
    • Nonprofit Organization
    • Environmental Agency
    • Billboard Rental
    • Photography
    • Bike Leasing
    • Software Reseller
    Browse all Industries
  • Community
    Learn
    • Tutorials
    • Documentation
    • Certifications
    • Training
    • Blog
    • Podcast
    Empower Education
    • Education Program
    • Scale Up! Business Game
    • Visit Odoo
    Get the Software
    • Download
    • Compare Editions
    • Releases
    Collaborate
    • Github
    • Forum
    • Events
    • Translations
    • Become a Partner
    • Services for Partners
    • Register your Accounting Firm
    Get Services
    • Find a Partner
    • Find an Accountant
      • Get a Tailored Demo
    • Implementation Services
    • Customer References
    • Support
    • Upgrades
    Github Youtube Twitter Linkedin Instagram Facebook Spotify
    +32 2 290 34 90
    • Get a Tailored Demo
  • Pricing
  • Help
  1. APPS
  2. Platform
  3. EH HR Platform Core v 19.0
  4. Sales Conditions FAQ

EH HR Platform Core

by ERP Heritage https://erpheritage.com.au
Odoo
v 19.0 Third Party 18
Download for v 19.0 Deploy on Odoo.sh
Apps purchases are linked to your Odoo account, please sign in or sign up first.
Availability
Odoo Online
Odoo.sh
On Premise
Odoo Apps Dependencies • Discuss (mail)
• Employees (hr)
Community Apps Dependencies Show
EH HR Compatibility
Lines of code 875
Technical Name eh_hr_core
LicenseLGPL-3
Websitehttps://erpheritage.com.au
Versions 16.0 17.0 18.0 19.0
You bought this module and need support? Click here!
Availability
Odoo Online
Odoo.sh
On Premise
Odoo Apps Dependencies • Discuss (mail)
• Employees (hr)
Community Apps Dependencies Show
EH HR Compatibility
Lines of code 875
Technical Name eh_hr_core
LicenseLGPL-3
Websitehttps://erpheritage.com.au
Versions 16.0 17.0 18.0 19.0
ERP Heritage · HR Platform
ERP Heritage / HR Platform

EH HR Platform Core

The audited, multi-company foundation every EH HR module is built on.

Free · LGPL-3FreeLGPL-3v1.0.0
Hash-chained audit
Multi-company strict
Feature flags
Typed settings
Rate limiter

Why this module

EH HR Platform Core

01 / INTEGRITY

An audit trail you can prove

Every create, write, and unlink on an audited model writes an append-only row whose sha256 hash chains to the row before it. A transaction-scoped Postgres advisory lock serializes appends so two concurrent writes can never fork the chain. verify_chain() walks the whole log in bounded batches and names the first row that does not match. The access rules grant read only, never write, create, or delete.

02 / ISOLATION

Multi-company that does not leak

The company-aware mixin makes company_id required, defaults it to the active company, and refuses any write that moves a record into a company the user does not belong to. Even a sudo cross-company write is rejected unless an explicit context key is set, and every such elevation is written to the audit log with all affected record ids. A global record rule isolates the audit log itself per company.

03 / FOUNDATION

Thin core, sharp edges

One dependency-light layer that the workflow, approval, policy, notification, and feature modules all build on. Typed per-company settings that version on write instead of destroying the old value, runtime feature flags with deterministic percentage rollout, a restart-durable rate limiter, and a four-tier access ladder. The hard cross-cutting concerns live here, once, correctly.

Day in the life

An HR officer changes a record, and the trail holds.

An officer updates an employee record. Behind the form, the audited mixin captures a before snapshot of only the whitelisted fields, lets the write commit, then appends a single audit row with the before and after payload, the actor, a correlation id, and the owning company. The row's hash folds in the previous row's hash, so the entry is locked into an ordered chain the moment it lands. A second officer in another company saves at the same instant. A Postgres advisory lock makes the two appends strictly serial, so both rows chain cleanly with no fork. Later an auditor with read-only access runs verify_chain over the whole log and gets back a clean result, proof that nothing was edited after the fact. Neither officer can see the other company's trail, because a global record rule scopes the audit log per company. No mail.thread, no plugin, just the platform doing its job.

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.

AUDIT / CONCURRENCY

A hash chain is inherently serial. Two concurrent transactions could read the same tail and fork it, so appends take a transaction-scoped Postgres advisory lock (pg_advisory_xact_lock) that releases automatically on commit or rollback. Appends are strictly ordered under any worker count.

AUDIT / UPGRADE-SAFE

The owning company_id column is deliberately excluded from the hash material. Adding it never alters an existing row's hash, so a chain written before the column existed still verifies after the upgrade that introduces per-company isolation.

AUDIT / SERIALIZATION

A missing actor is normalized to 0 on both the append and the verify path. An earlier version hashed it as 0 on append but as the string False on verify, which silently broke the chain for every actorless system row. Both paths now share one canonical material function.

MULTI-COMPANY / SUDO GUARD

Cross-company writes are refused even under sudo unless the explicit allow_cross_company context key is set. When the override is used, every affected record id is written to the audit log, not just the first, so a multi-record elevation is fully reconstructable.

SETTINGS / IMMUTABLE HISTORY

Writing a setting does not overwrite the old value. The previous active entry is archived and pointed at its successor, and a unique constraint allows exactly one active entry per company and key, so the current value is unambiguous and the full history survives.

RATE LIMIT / RESTART-DURABLE

The public-endpoint throttle is a single atomic SQL upsert with RETURNING, so two gunicorn or gevent workers racing the same bucket can never both read a stale count. The counter lives in a table, not an in-memory dict, so it is shared across workers and survives a restart. A header-less caller collapses to one shared bounded bucket.

CRON / SELF-CONTAINED

The rate-limit table is vacuumed by a daily cron that deletes only closed windows past a cutoff, keeping the high-churn counter table small no matter how busy the endpoints get. The cron is defined without the ir.cron numbercall and doall fields that Odoo 19 dropped.

TIMEZONE / DST-SAFE

Event timestamps are stored in UTC. Computing the civil date an event belongs to, and the UTC window that bounds an employee's local day, is centralized in one timezone service that correctly handles the 23-hour and 25-hour days at DST transitions and falls back from employee to company timezone to UTC.

What is inside

Built to do the job, end to end.

  • Hash-chained audit log. eh.hr.audit.log records who did what to which record, with before and after JSON payloads, a correlation id, and the owning company. Each row stores the sha256 of the previous row plus its own fields. Appends are serialized by a Postgres advisory lock, and verify_chain() walks the log with keyset pagination and a per-batch cache clear so the working set stays bounded at any size. The model has no create, write, or unlink access for anyone.
  • Audited record mixin. eh.hr.audited.mixin emits audit rows automatically on create, write, and unlink. A class-level whitelist controls which fields are captured (default: all stored fields except mail and bookkeeping fields), writes capture a before snapshot of only the changed audited fields, and a write that changes nothing audited emits no row.
  • Strict company-aware mixin. eh.hr.company.aware.mixin makes company_id required and defaulted, rejects writes into a company the user is not a member of, blocks cross-company moves even under sudo unless explicitly overridden, and audits every elevation with all affected record ids. It deliberately refuses the leaky null-company global-rule pattern.
  • Typed, versioned settings. eh.hr.settings.entry is a per-company key/value registry with typed values (string, integer, float, boolean, JSON) used instead of ir.config_parameter. Writes version the old value rather than destroying it, a unique constraint guarantees one active entry per company and key, and a res.config.settings page surfaces the platform-wide knobs.
  • Feature flags and rate limiter. eh.hr.feature.flag gates rollouts by company, user group, date window, and deterministic percentage on user id, used to roll engine versions out safely. eh.hr.rate.limit is an atomic fixed-window counter for public kiosk, mobile, and visitor endpoints that is worker-shared, restart-durable, and vacuumed daily.
  • Service layer, timezone, and OWL kit. A plain-Python service registry (register_service, locate_service) keeps business logic off the ORM and reusable across crons, RPC, wizards, and triggers, with a DST-safe timezone service and a platform mixin that mints correlation ids and emits bus events cross-written to the audit log. The frontend ships HrCard and HrStat OWL components with a skeleton loading state and a debounced toast service. A four-tier access ladder (Employee, Manager, Officer, Admin) plus Auditor and Kiosk Device groups is wired on install.

Honest about the edges

What this does not do, so nothing surprises you.

  • This is a platform layer, not a feature app. It ships mixins, services, the audit log, settings, flags, and a component kit. The actual HR surfaces (attendance, leave, and so on) live in separate eh_hr modules that depend on this one.
  • Workflow state machines, approval chains, the policy DSL, and notification dispatch are explicitly not in this module. They belong to the engine modules (workflow, approval, policy, notification).
  • The audit log exposes a configurable retention setting and a verify_chain integrity check, but this module does not ship an automatic archival or pruning cron. Old rows are not exported or removed unless a consuming module or operator does so.
  • The platform event bus is in-process (bus.bus). Clustered or cross-node delivery requires swapping in a queue or message-broker adapter; the hook is there but no external broker is included.
  • A redact-PII-in-exports flag is exposed as a setting, but the redaction itself is applied by the feature modules that produce exports, not by this core layer.
  • Cross-version compatibility (Odoo 16 to 19) is provided through the eh_hr_compat dependency for groups, constraints, and access helpers. This listing targets the Odoo 19 Community release line.
Search

Odoo 19 HR audit log, Odoo HR multi-company, append-only audit trail Odoo, hash chained audit Odoo, Odoo HR feature flags, Odoo rate limiting, Odoo HR settings registry, Odoo OWL component kit, Odoo HR platform module, Odoo 19 Community HR, tamper evident audit Odoo, per-company settings Odoo, Odoo correlation id tracing, DST safe timezone Odoo HR, Odoo HR access groups

ERP Heritage

Production-grade Odoo accounting, built to an engineering bar and documented honestly. Support: info@erpheritage.com.au

v1.0.0 · LGPL-3 · Odoo 19 Community

Please log in to comment on this module

  • The author can leave a single reply to each comment.
  • This section is meant to ask simple questions or leave a rating. Every report of a problem experienced while using the module should be addressed to the author directly (refer to the following point).
  • If you want to start a discussion with the author, please use the developer contact information. They can usually be found in the description.
Community
  • Tutorials
  • Documentation
  • Forum
Open Source
  • Download
  • Github
  • Runbot
  • Translations
Services
  • Odoo.sh Hosting
  • Support
  • Upgrade
  • Custom Developments
  • Education
  • Find an Accountant
  • Find a Partner
  • Become a Partner
About us
  • Our company
  • Brand Assets
  • Contact us
  • Jobs
  • Events
  • Podcast
  • Blog
  • Customers
  • Legal • Privacy
  • Security

Odoo is a suite of open source business apps that cover all your company needs: CRM, eCommerce, accounting, inventory, point of sale, project management, etc.

Odoo's unique value proposition is to be at the same time very easy to use and fully integrated.

Website made with