Model the business workflow before the module

A good custom Odoo module translates a missing business rule into models, states, permissions, views, and automated actions that cooperate with standard Odoo behavior. It should extend the platform at known seams instead of creating a second application inside the database.

Use Odoo ORM and inheritance intentionally

  • Start with actors, states, transitions, validations, and audit requirements.
  • Use model inheritance when extending a standard concept; create a new model for genuinely new business entities.
  • Implement access rights and record rules alongside UI buttons, never after them.
  • Keep computed fields and automated actions deterministic and avoid hidden network calls in model methods.
  • Use scheduled jobs/queues for slow integrations instead of blocking form saves.

A controlled record lifecycle

Users transition a record through explicit states; server-side rules validate permission and data, then side effects are queued after the authoritative state is saved.

Diagram

Custom workflow inside Odoo lifecycle

Users transition a record through explicit states; server-side rules validate permission and data, then side effects are queued after the authoritative state is saved.

Adding a purchase approval extension

Make the state transition explicit

A model action validates the current state and permission before changing the workflow state.

models/purchase_order.pypython
def action_submit_for_approval(self):
    for order in self:
        if order.state != 'draft':
            raise UserError('Only draft orders can be submitted')
        order.approval_state = 'pending'

Custom-module patterns that fight Odoo

Module checklist

  • Draw states and actors first.
  • Choose inheritance versus new model deliberately.
  • Implement access, record rules, and transition checks server-side.
  • Isolate external calls from synchronous model writes.
  • Test module install, upgrade, permissions, and standard-flow compatibility.