$ 129.36
In-App Purchases| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
Discuss (mail)
|
| Lines of code | 5104 |
| Technical Name |
dynamic_state_approval |
| License | LGPL-3 |
| Website | https://www.linkedin.com/in/abd-el-hamed-saad/ |
| Versions | 18.0 19.0 |
| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
Discuss (mail)
|
| Lines of code | 5104 |
| Technical Name |
dynamic_state_approval |
| License | LGPL-3 |
| Website | https://www.linkedin.com/in/abd-el-hamed-saad/ |
| Versions | 18.0 19.0 |
TEMPLATE-DRIVEN APPROVAL WORKFLOWS FOR ANY ODOO MODEL
Approval Workflow Engine
Build custom approval workflows from reusable templates — define states, transitions, gate rules, and access controls entirely from the UI. No code changes required.
Key Highlights
Template Library
Ready-to-use approval templates for Journal Entries, Transfers, Sales, Purchase Orders, and generic multi-step approvals
Custom State Machine
Define states with color coding, sequences, and links to standard Odoo states. Add transition buttons with labels, types, and ordering
Gate Rules
Block or hide native Odoo buttons (Post, Validate, Confirm) until the required custom state is reached — no code changes needed
Access Control
Restrict each transition to specific users or groups. Domain-based visibility rules for conditional button display
Live Dashboard
Real-time counters for every custom state across all active workflows. Drill down directly to filtered record lists
Multi-Company & Domain
Isolate workflows per company. Apply domain filters to restrict a workflow to specific record types (e.g. Customer Invoices only)
From Journal Entry approvals to Stock Transfer validations — configure multi-step approval workflows
directly from the UI using pre-built templates or build your own from scratch.
Ready-to-Use Workflow Templates
Browse the built-in template library — pre-configured approval flows for Journal Entries, Stock Transfers,
Sales Orders, Purchase Orders, and generic 2- or 3-step approvals.
Click Apply to create a live workflow in seconds.
- Journal Entry C — Accounting / Journal Entry (3-step: Draft → Approve C → Manger C → Posted)
- Journal Entry Bill — Accounting / Journal Entry (2-step: Draft → Approve B → Manger B → Posted)
- Transfer D — Inventory / Transfer — Delivery Orders only (domain filtered)
- Transfer R — Inventory / Transfer — Receipts only (domain filtered)
- Sales Order — Sales / Sales Order (2-step approval before confirmation)
- Purchase Order — Purchasing / Purchase Order (2-step approval before confirmation)
- 2 Approve — General / any model (generic 2-step: Draft → Approve → Done)
- 3 Approve — General / any model (generic 3-step: Draft → Approve → Manager → Done)
workflow.template — Kanban / List / Form views💡 Example: Click Apply on "Transfer D" → dialog opens → type field name → click Create Workflow → 7 states + 2 transitions + 1 gate rule created instantly
Apply Template in One Step
The Apply wizard pre-fills the model, field name, and states from the template JSON.
Confirm the workflow name and click Create Workflow — states, transitions, and gate rules are all created automatically.
- Info notice — "Button users and groups are not copied from templates. Set button access manually after the workflow is created."
- Workflow Name — pre-filled from template name (e.g., "Transfer D"), editable before creation
- State Name — technical field name for the custom state field (e.g.,
Delivery_state→ createsx_delivery_state) - Create Workflow — one click creates the full workflow: states, transitions, gate rules, and injects the field into the model
workflow.template.apply.wizard — TransientModel dialog💡 Example: Template "Transfer D" applied with State Name
Delivery_state → creates field x_delivery_state on stock.picking with 7 states and 2 transition buttons
Custom States with Color Coding
Define any number of custom states with technical names, display labels, color styles, and sequences.
Map each custom state to a standard Odoo state for seamless two-way synchronization.
Drag & drop rows to reorder states in the status bar.
- State Name — display label shown in the status bar and chatter (e.g., Draft, Waiting, Ready, Approve D, Manger D, Done, Cancelled)
- Technical Name — unique internal identifier stored in the database (e.g.,
draft,confirmed,assigned,approve_d,manger_d) - Linked Standard State — maps the custom state to a native Odoo state for compatibility (e.g., Waiting →
confirmed, Done →done, Cancelled →cancel) - State Style — color-coded pill in the status bar (Gray, Blue, Orange, Dark Blue, Green, Red) — chatter on the right logs every state added
workflow.state — inline editable list in workflow.config form💡 Example: State "Waiting" → technical:
confirmed → linked standard: confirmed → style: Blue | State "Manger D" → technical: manger_d → no link → style: Green
Dynamic Action Buttons
Each transition becomes a clickable button injected into the form header.
Configure button label, type (Primary / Success / Danger / Warning), sequence,
confirmation message, icon, and the from/to states it connects.
Technical name is auto-generated from states.
- Button Label — text displayed on the form header button (e.g., "Approve D")
- Workflow — parent workflow this transition belongs to (e.g., "Transfer D (Transfer)")
- Technical Name — auto-generated Python method name from states (e.g.,
action_draft_waiting_confirmed_to_done) - From States — button appears only when record is in one of these states (multi-select: Draft, Waiting)
- To State — the state the record moves to when the button is clicked (e.g., Approve D)
- Button Type — visual style of the button (Primary / Success / Danger / Warning / Link)
- Confirmation Message — optional popup shown before executing the transition (e.g., "Are you sure you want to proceed?")
workflow.transition — form dialog from Transitions tab💡 Example: "Approve D": From [Draft, Waiting] → To Approve D, type Primary, icon
fa-check, sequence 10 → button injected into Transfer form header automatically
User & Group Restrictions
Restrict each transition button to specific users or security groups.
Unauthorized users who attempt the action receive a clear error listing who is allowed —
enforced server-side for full security.
- Specific Users — button is restricted to an explicit list of named users; others get an error message when clicking
- User Group — restricts the button to an entire security group (e.g., Purchase Manager, Inventory / Administrator)
- Allowed Users — the actual users assigned (e.g., Administrator, test) — enforced server-side on every click
visibility_type, allowed_user_ids, group_ids on workflow.transition💡 Example:
visibility_type = 'user', allowed: [Administrator, test] → unauthorized user clicks "Approve D" → error: "You are not authorized to perform this action. Allowed: Administrator, test"
Block Native Odoo Buttons
Gate rules intercept standard Odoo buttons (Post, Validate, Confirm, etc.)
and block or hide them until a required custom approval state is reached.
Choose from Block Only, Hide Always, or Hide Until State visibility modes.
Set a custom error message for a professional user experience.
- Button — the native Odoo button being gated (e.g., "Validate (button_validate) ×2" means it appears twice in the view)
- Gate Name — friendly label for this rule (e.g., "Validate") — used in error messages
- Visibility — enforcement mode: Block Only (visible but blocked), Hide Always (always hidden), Hide Until State (hidden until required state is reached)
- Occurrence — which instance to gate when the same button appears multiple times (Auto / [1] / [2])
- Required Custom State — the workflow state that must be reached before the button works (e.g., "Manger D")
- Error Message — shown to the user when blocked (e.g., "Manger D approval is required before validation.")
workflow.state.gate — Gates tab in workflow.config💡 Example: Gate "Validate" → blocks
button_validate → required state: Manger D → visibility: Block Only → error: "Manger D approval is required before validation."
Auto-Discover Form Buttons
Click Discover Buttons to automatically scan the model's primary form view and extract all native action buttons.
Handles duplicate button occurrences with [1] / [2] occurrence selectors.
- Discover Buttons — scans the model's primary form view XML and extracts all native
<button>elements automatically - Label — the button's display text as shown in the form (e.g., Cancel, Check Availability, Mark as Todo, Validate, Print)
- Method — the Python method name on the model called when clicked (e.g.,
action_cancel,action_assign,button_validate) - Notification — "20 button(s) found for Transfer" — success message shown after scan; Validate appears with count ×2 (appears twice in view)
workflow.view.button — action action_discover_buttons()💡 Example: Transfer model → 20 buttons discovered including Validate (
button_validate ×2), Cancel (action_cancel), Check Availability (action_assign), Packages, Put in Pack, Scraps
Apply to Specific Record Types
Use the built-in domain builder to restrict a workflow to a subset of records.
Example: apply only to Customer Invoices or Outgoing Transfers.
A live counter shows how many records match the current domain.
- Field selector — pick any field on the model (e.g., "Type" =
move_typeon Journal Entry) - Operator — condition type: is / is not / is in / is not in / contains / > / < / etc.
- Values — multi-select from available options (e.g., Journal Entry, Customer Invoice, Vendor Bill, Customer Credit Note...)
- Code editor — raw domain preview:
[("move_type", "in", ["entry"])]— editable directly for advanced use - New Rule — add additional AND/OR conditions to build complex multi-field filters
apply_domain on workflow.config — widget: domain💡 Example: Journal Entry workflow → domain
[("move_type","in",["in_invoice","in_refund"])] → applies only to Vendor Bills and Vendor Credit Notes, ignoring all other journal entries
Gate Blocks at Runtime
When a user tries to click a gated button before reaching the required state,
a descriptive error is raised showing exactly which state must be reached first.
Enforcement is server-side — no client-side bypass is possible.
- Approve D button — workflow transition button injected into the Transfer form header by the engine
- Custom state bar — Draft → Waiting → Ready → Approve D → Manger D → Done → Cancelled (all custom states displayed natively)
- Validate button clicked — user attempts to validate while record is in "Approve D" state (not yet in "Manger D")
- Validation Error dialog — "Cannot proceed: the record must reach the 'Manger D' state first. Manger D approval is required before validation." — enforced server-side, no bypass possible
_get_error_message() on workflow.state.gate💡 Example: WH/OUT/00013 in state "Waiting" → user clicks Validate → gate checks current state vs required "Manger D" → raises: "Cannot proceed: the record must reach the 'Manger D' state first."
State Counters & Drilldown
The dedicated dashboard aggregates record counts per custom state across every active workflow.
Click any counter to open a filtered list of matching records for immediate action.
Managers get a birds-eye view of all pending approvals across the organization.
- Journal Entry card — groups all active workflows on Journal Entry (Journal Entry C) with per-state counters: Draft / Approve C / Manger C / Posted / Cancelled
- Transfer card — shows Transfer D and Transfer R side by side with their own state counters per workflow
- Ready: 2 — clicking any counter opens a filtered list of records in that exact state (e.g., transfers in "Ready" state = 2 records)
- Drilldown list view — records from multiple workflows shown together with workflow state columns (Transfer D, Transfer R, Status) — each row is a live record ready for action
WfDashboard💡 Example: "Ready: 2" clicked → list filtered to
x_delivery_state = assigned → shows WH/IN/00007 and WH/IN/00005 ready for the next approval step
Duplicate Domain Protection
The engine prevents two active workflows from targeting the same model and domain combination.
A clear validation error is shown before saving, protecting data integrity and preventing conflicting approval flows.
- "Oh snap!" title — error dialog triggered on save when a duplicate model+domain combination is detected
- Error message — "A workflow configuration for model 'Journal Entry' with the same domain already exists (Journal Entry Bill). Each model+domain combination must be unique per company."
- Stay here — keeps the form open so the user can correct the domain or rename the workflow
- Discard changes — abandons the conflicting configuration without saving
_check_duplicate_domain() on workflow.config💡 Example: Two workflows on
account.move both with domain [("move_type","in",["in_invoice","in_refund"])] → save blocked: "Journal Entry Bill already owns this domain for My Company"
Template library with 8 built-in approval patterns for common Odoo models
Custom states with color coding, sequences, and standard state mapping
Transition buttons auto-injected into form headers — no view customization needed
Per-transition access control by specific users or security groups (server-side enforced)
Gate rules: block / hide standard Odoo buttons until required approval state is reached
Auto button discovery: scans model form views and detects all native action buttons
Domain-based filtering: apply workflow to a subset of records (e.g. Customer Invoices only)
Live dashboard with state counters and one-click drilldown to filtered record lists
Full chatter tracking: state changes, field edits, and line additions/removals logged automatically
Multi-company support: isolate workflows per company with no cross-company conflicts
Duplicate domain protection: prevents conflicting approval flows on the same record type
Clean uninstall: removes all generated fields, views, and automation rules automatically
Release 18.0.2.0.0
April 2026- Template library with 8 ready-to-use approval patterns
- Auto-save before adding states or transitions (JS widget)
- Full chatter tracking for form fields and One2many lines
- Smart
needs_updatedetection — fires only on view-relevant changes - Cache invalidation on access-control field changes
- Notification Manager integration for transition events
- Button registry sync for external notification modules
Release 18.0.1.0.0
December 2025- Core workflow engine: states, transitions, and gate rules
- Dynamic field generation via Odoo Studio API
- Auto-detection of native form view buttons
- Domain-based filtering per workflow
- Multi-company isolation
- OWL dashboard with state counters and drilldown
- Duplicate domain validation
- Clean uninstall hook
- Translations: Arabic (ar_001), French (fr), Spanish (es_AR), Turkish (tr)
Developer
Abd Elhamed Saad
Odoo Developer & Consultant
Connect on LinkedInFor support, customization requests, or feature enhancements
License: LGPL-3 | Category: Productivity | Version: 18.0.2.0.0
Please log in to comment on this module