Prefer stable extension points: inherited models with super(), XML view inheritance with precise xpath, and new models instead of monkey-patching core. Keep custom code in one Git repo per version branch, avoid editing enterprise or community source directly, document dependencies, and run automated tests on critical methods so OpenUpgrade and -u surface breaks early in CI staging.
Steps
- Create custom addon namespace with clear depends list in __manifest__.py.
- Extend models via _inherit; never copy-paste entire core methods unless necessary.
- Inherit views with //field or //group xpath anchors, not fragile position attributes.
- Use @api.constrains and computed fields instead of overriding write when possible.
- Store configuration in ir.config_parameter or settings models, not hard-coded IDs.
- Maintain version branches 16.0, 17.0, 18.0 aligned to Odoo releases.
- Run -u custom_module on CI database clone on every merge request.
Common mistakes
- Studio-only changes without export to module for Git tracking.
- Overriding button_validate on stock.picking without calling super.
- Hard-coded database IDs in Python after data reload.
- Copying full QWeb templates instead of xpath inherit.
- Forking OCA modules without upstream merge discipline.
Odoo version notes
Upgrade-safe customization patterns apply to Community and Enterprise 16–18. Odoo Studio exports help but still need version porting. Enterprise web_studio creates modules that must be upgraded like any addon. The ERP Firm keeps customizations in Git with Rescue & Run upgrade testing.
When to bring in help
If the fix touches custom modules, regulated traceability, or production outages, a focused rescue sprint beats months of trial and error. See our Odoo service.