EH HR Workflow Engine
State machines declared as data, so any HR record becomes draft to approve to done by composing one mixin, with no Python deploy for new steps.
Why this module
EH HR Workflow Engine
New steps ship as data
States and transitions are rows in eh.hr.workflow.definition. Adding a transition, regrouping who may run it, or inserting a new state is a configuration change applied from the Workflows menu, never a Python deploy.
Any record becomes workflow driven
A model declares _workflow_code and inherits eh.hr.workflow.mixin. It gains a status field whose options come from the definition, an action_transition entry point, and a state_label, with no per feature state machine to re-implement.
Transitions enforce who and when
Each transition can be gated to res.groups with an admin bypass, blocked from final states by the is_final marker, and routed through the approval engine when requires_approval is set, with the real submitter captured before the engine sudo.
Day in the life
A correction request moves through its workflow
An officer opens a record that inherits the workflow mixin. The statusbar already shows the definition's initial state because it is set as a field default, so the first transition button is live before the first save. The officer fires submit through action_transition; the engine checks the transition is declared from the current state and that the user holds one of the transition's groups, advances the state, and emits a workflow.transition event that is cross written to the platform audit log. Because the submit transition is marked requires_approval, the engine opens an approval request and records who submitted it, so that person cannot later approve their own request. When the chain approves, the approval engine calls back into the workflow engine service to apply the follow up transition, and a final state then forbids any further moves.
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.
is_final is the authoritative terminal marker. action_transition refuses any move out of a final state, even a transition a misconfigured definition wrongly declares from it, raising a clear UserError rather than silently advancing.
On a gated transition the real submitter is captured as submitted_by before the approval engine takes sudo, so the user who fired the transition cannot approve their own request later even if they hold an approver group. The approval engine raises AccessError on a self decision.
transition_code can arrive positionally from server side callers or via the transition_code context key from view header buttons, which cannot pass positional arguments. The method stays button callable and raises UserError when no code resolves.
A transition that is not declared from the record's current state, or a user outside all of the transition's allowed groups, is rejected with a specific UserError naming the code and state, so misconfiguration fails loudly instead of corrupting status.
requires_approval opens an approval chain as a side effect that gates the follow up transition, not the current one. The state advance still happens, which avoids records appearing stuck in their pre submit state and repeated approval requests against the same record.
A unique(code, active) constraint allows only one active definition per workflow code, so the runtime lookup that resolves a model's _workflow_code is unambiguous while inactive prior versions can be retained for history.
Every transition emits a structured platform event that the platform cross writes to the append only, SHA-256 hash chained audit log under a Postgres advisory lock, so transition history is ordered, tamper evident, and replayable.
What is inside
Built to do the job, end to end.
- Models this module adds. eh.hr.workflow.definition, eh.hr.workflow.state, eh.hr.workflow.transition, and the abstract eh.hr.workflow.mixin that consumer models inherit.
- How states reach the UI. The mixin exposes a Selection status field whose options are resolved dynamically from the definition and ordered as the definition orders its states, so the standard statusbar widget renders the progression with no static selection list.
- Transition controls. Each transition carries from and to states, an optional res.groups gate with admin bypass, a requires_approval flag with an approval_chain_code, and an optional post_action_method resolved on the record after the transition completes.
- Service entry point. A registered eh.hr.workflow.engine service exposes apply_transition, the entry point the approval engine calls back into to apply a transition once a chain approves.
- Admin surface. A Workflows form under HR configuration, restricted to the HR admin group, where states and transitions are edited as inline lists with handle ordering, kind, and final markers.
- Platform integration. The mixin builds on the platform mixin, so each record carries a correlation id and every transition is emitted as a typed event and written to the shared platform audit trail.
Honest about the edges
What this does not do, so nothing surprises you.
- This module provides the workflow engine and mixin. It ships no pre built workflow definitions or demo data; states and transitions are authored as configuration or supplied by feature modules that compose the mixin.
- Approval routing, the approval chains, and escalation crons live in the separate approval engine module. This module only opens a request when requires_approval is set and applies the follow up transition the engine resolves on close.
- The audit log, hash chaining, advisory lock ordering, and platform event bus are provided by the HR core platform, not by this module. This module emits the events and relies on the platform to persist them.
- post_action_method must be a zero argument method that already exists on the consumer model. It is resolved by name after the transition and is not sandboxed.
- There is no graphical workflow designer. Definitions are edited through the standard form with inline state and transition lists.
- This release targets Odoo 18 Community and depends on eh_hr_core.
odoo 18 hr workflow engine, declarative state machine odoo, odoo workflow as data, configurable approval workflow odoo, odoo hr workflow mixin, group gated transitions odoo, odoo community hr platform, state machine odoo records, odoo approval routing, audited workflow transitions odoo, odoo 18 hr approval, no code workflow steps odoo
Please log in to comment on this module