The Migration Problem
Migrating custom Odoo modules between versions is one of the most dreaded tasks in the Odoo ecosystem. Each major version introduces breaking changes: removed APIs, renamed methods, changed view syntax, new ORM behaviors, and restructured base modules. A module that works perfectly on Odoo 17 might have dozens of issues on Odoo 18 or 19. AI coding agents can analyze your custom modules, identify every breaking change, and generate the fixes — turning a multi-week migration into a multi-day project.
What Changes Between Versions
# Common breaking changes AI detects:
# 1. API Changes
# Odoo 17 → 18: attrs removal
# Before: attrs="{'invisible': [('state', '!=', 'draft')]}"
# After: invisible="state != 'draft'"
# 2. Import Path Changes
# Before: from odoo.exceptions import except_orm
# After: from odoo.exceptions import UserError
# 3. Method Removals
# Before: record.message_post_with_view(...)
# After: record.message_post_with_source(...)
# 4. Field Changes
# Before: fields.Many2one('res.users', oldname='user_id')
# After: oldname parameter removed in newer versions
# 5. View Syntax
# Before: <tree string="Orders">
# After: <list string="Orders"> (Odoo 17+)
# 6. Widget Changes
# Before: widget="many2many_tags" options="{'color_field': 'color'}"
# After: widget="many2many_tags" color_field="color"AI Migration Workflow
# Step 1: AI scans all custom modules
"Scanning 12 custom modules...
Total Python files: 89
Total XML files: 124
Total JS files: 15
Total CSV/data files: 34"
# Step 2: AI identifies breaking changes
"Migration Report: Odoo 17 → 19
Critical (will crash):
├── 23 × attrs= usage in XML views → convert to new syntax
├── 5 × removed method calls → replace with alternatives
├── 3 × removed import paths → update imports
└── 2 × removed field parameters → clean up
Warning (may cause issues):
├── 12 × deprecated method usage → will be removed next version
├── 8 × tree → list view tag change
├── 4 × JavaScript widget API changes
└── 3 × changed default values
Info (style/convention):
├── 15 × old-style string formatting → f-strings recommended
├── 7 × missing type hints on public methods
└── 5 × deprecated coding patterns
Total issues: 87 (33 critical, 27 warning, 27 info)"Automatic Fixes
1. attrs Conversion (Odoo 17 → 18+)
# AI converts all attrs to new syntax:
# Before (Odoo 17):
<field name="amount"
attrs="{'invisible': [('state', '!=', 'draft')],
'required': [('type', '=', 'invoice')]}"/>
# After (Odoo 18+):
<field name="amount"
invisible="state != 'draft'"
required="type == 'invoice'"/>
# Complex domain conversion:
# Before: attrs="{'invisible': [('a', '=', 'x'), ('b', '!=', 'y')]}"
# After: invisible="a == 'x' and b != 'y'"
# OR domain conversion:
# Before: attrs="{'invisible': ['|', ('a', '=', 1), ('b', '=', 2)]}"
# After: invisible="a == 1 or b == 2"
# AI handles all domain operators: =, !=, >, <, in, not in, like, ilike2. Method Migration
# AI replaces deprecated/removed methods:
# Before:
def write(self, vals):
result = super(MyModel, self).write(vals)
self.message_post_with_view(
'module.mail_template_view',
subject='Updated',
)
return result
# After (AI-generated):
def write(self, vals):
result = super().write(vals) # simplified super() call
self.message_post_with_source(
'module.mail_template_view',
subject='Updated',
)
return result3. Import Fixes
# AI updates all import paths:
# Before:
from odoo.exceptions import except_orm, Warning
from odoo.tools import pycompat
from odoo import SUPERUSER_ID, api, fields, models, _
# After:
from odoo.exceptions import UserError, ValidationError
# pycompat removed — use standard Python 3
from odoo import api, fields, models, _, SUPERUSER_IDMigration Script Generation
# AI generates pre-migration and post-migration scripts:
# pre-migrate.py (runs before module update)
def migrate(cr, version):
"""Pre-migration: rename columns before ORM loads."""
# Renamed field: old_field → new_field
cr.execute("""
ALTER TABLE my_model
RENAME COLUMN old_field TO new_field
""")
# Removed field: archive data before column drops
cr.execute("""
CREATE TABLE IF NOT EXISTS _migration_backup_my_model AS
SELECT id, removed_field FROM my_model
""")
# post-migrate.py (runs after module update)
def migrate(cr, version):
"""Post-migration: data transformations."""
from odoo import api, SUPERUSER_ID
env = api.Environment(cr, SUPERUSER_ID, {})
# Convert old state values to new ones
records = env['my.model'].search([
('state', '=', 'old_state')
])
records.write({'state': 'new_state'})
# Recompute stored fields that changed formula
env['my.model'].search([])._compute_total_amount()JavaScript/OWL Migration
- Widget API changes between versions
- OWL component lifecycle method renames
- Template syntax updates
- Asset bundle restructuring
- New hook patterns replacing old patterns
Migration Checklist AI Generates
| Check | Status | Details |
|---|---|---|
| Python API changes | Auto-fixed | 5 methods updated |
| View attrs removal | Auto-fixed | 23 views converted |
| Import paths | Auto-fixed | 3 files updated |
| Field changes | Auto-fixed | 2 parameters removed |
| JavaScript widgets | Needs review | 4 files flagged |
| Data migration | Script ready | Review before running |
| Test updates | Auto-fixed | 8 test methods updated |
| Manifest version | Auto-fixed | 19.0.x.x.x |
Migration Speed
| Module Size | Manual Migration | AI-Assisted |
|---|---|---|
| Small (5-10 files) | 1-2 days | 2-4 hours |
| Medium (20-50 files) | 3-5 days | 1-2 days |
| Large (100+ files) | 2-4 weeks | 3-5 days |
DeployMonkey AI Migration
DeployMonkey's AI coding agent scans your custom Odoo modules and generates migration patches for version upgrades. Upload your module, specify the target version, and get a detailed migration report with auto-generated fixes for most breaking changes.