| REPOSITORY | |
|---|---|
| REPOSITORY | OCA/module-composition-analysis |
| GIT | |
| GIT | https://github.com/OCA/module-composition-analysis.git |
| GIT FOLDER | |
| GIT FOLDER | https://github.com/OCA/module-composition-analysis/tree/18.0/odoo_repository_migration |
| VERSION | |
| VERSION | 1.1.0 |
| CATEGORY | |
| CATEGORY | Tools |
| LICENSE | |
| LICENSE | AGPL-3 |
| APPLICATION | |
| APPLICATION | No |
| AUTO-INSTALLABLE | |
| AUTO-INSTALLABLE | No |
| AUTHORS | |
| AUTHORS | Odoo Community Association (OCA), Camptocamp |
| MAINTAINERS | |
| MAINTAINERS | Odoo Community Association (OCA), Camptocamp |
| COMMITTERS | |
| COMMITTERS | Sébastien Alix, Weblate, OCA-git-bot, oca-ci |
| WEBSITE | |
| WEBSITE | https://github.com/OCA/module-composition-analysis |
| LAST TRACKING UPDATE | |
| LAST TRACKING UPDATE | 2026-07-06 19:30:20 |
| ODOO DEPENDENCIES | |
| ODOO DEPENDENCIES |
OCA/connector: - component OCA/module-composition-analysis: - odoo_repository OCA/queue: - queue_job OCA/server-tools: - base_time_window odoo/odoo: - base_sparse_field - base - base_setup - web - bus - web_tour - html_editor |
| PYTHON DEPENDENCIES | |
| PYTHON DEPENDENCIES |
oca-port gitpython odoo-addons-parser pyyaml requests cachetools |
| SYSTEM DEPENDENCIES | |
| SYSTEM DEPENDENCIES | Not have |
| DESCRIPTION | |
| DESCRIPTION | This module collects and records modules migration data from Odoo repositories. Thanks to [oca-port](https://github.com/OCA/oca-port/) and data collected by `odoo_repository`, this module will generate migration data on each module for declared migration paths (e.g. 16.0 -> 18.0). Also, for specific cases you can declare what a module became in a given Odoo version, like OCA `web_domain_field` replaced by standard Odoo module `web` starting from 17.0 (with an optional explanation that could help users, like how to use this new module compared to the previous one). Given a migration path, a module can get one of this migration status: | Status | Description | | ------ | ----------- | | *Fully Ported* | All commits from source version are present in target version | | *To migrate* | The module doesn't exist on target version | | *Ported (missing commits?)* | Some commits from source version are not ported in target version (could be false-positive) | | *To review* | A migration PR has been detected | | *Replaced* | The module has been replaced by another one (not sharing the same git history) | | *Moved to standard?* | The module name has been detected in Odoo standard repositories for target version. High chance this module is or should be replaced by another one instead (by creating a timeline), so it mainly helps to detect such cases. | | *Moved to OCA* | the module name is available in an OCA repository (could be a false-positive because sharing the same name, in such case a timeline has to be created) | | *Moved to generic repo* | a specific module (only available in a project) in source version now exists in a generic repository (could be a false-positive if both modules have only their name in common) | It helps to build a consolidated knowledge database accross different Odoo versions for everyone: functionals and developers. |
| XML ID | Name | Model | Type | Status |
|---|---|---|---|---|
odoo_migration_path_view_form |
odoo.migration.path.form | odoo.migration.path | form | New |
odoo_migration_path_view_tree |
odoo.migration.path.list | odoo.migration.path | list | New |
odoo_module_branch_migration_view_form |
odoo.module.branch.migration.form | odoo.module.branch.migration | form | New |
odoo_module_branch_migration_view_search |
odoo.module.branch.migration.search | odoo.module.branch.migration | search | New |
odoo_module_branch_migration_view_tree |
odoo.module.branch.migration.list | odoo.module.branch.migration | list | New |
odoo_module_branch_timeline_view_form |
odoo.module.branch.timeline.form | odoo.module.branch.timeline | form | New |
odoo_module_branch_timeline_view_search |
odoo.module.branch.timeline.search | odoo.module.branch.timeline | search | New |
odoo_module_branch_timeline_view_tree |
odoo.module.branch.timeline.list | odoo.module.branch.timeline | list | New |
odoo_module_branch_view_form |
odoo.module.branch.form.inherit | odoo.module.branch | div | Inherits odoo_repository.odoo_module_branch_view_form |
odoo_module_branch_view_search |
odoo.module.branch.search.inherit | odoo.module.branch | filter | Inherits odoo_repository.odoo_module_branch_view_search |
odoo_repository_view_form |
odoo.repository.form.inherit | odoo.repository | group | Inherits odoo_repository.odoo_repository_view_form |
active
Boolean
default=True
name
Char
compute='_compute_name'
store=True
source_branch_id
Many2one → odoo.branch
comodel_name='odoo.branch'
ondelete='cascade'
required=True
target_branch_id
Many2one → odoo.branch
comodel_name='odoo.branch'
ondelete='cascade'
required=True
action_scan(self)
create(self, vals_list)
migration_ids
One2many → odoo.module.branch.migration
comodel_name='odoo.module.branch.migration'
inverse_name='module_branch_id'
string='Migrations'
migration_scan
Boolean
compute='_compute_migration_scan'
help='Technical field telling if this module is elligible for a migration scan.'
store=True
next_odoo_version_module_branch_id
Many2one → odoo.module.branch
comodel_name='odoo.module.branch'
compute='_compute_next_odoo_version_module_branch_id'
string='Next Odoo Version Module Branch'
timeline_ids
One2many → odoo.module.branch.timeline
comodel_name='odoo.module.branch.timeline'
inverse_name='module_branch_id'
string='Timeline'
create(self, vals_list)
open_next_module_branches(self)
write(self, vals)
active
Boolean
related='migration_path_id.active'
store=True
author_ids
Many2many
related='module_branch_id.author_ids'
display_name
Char
compute='_compute_display_name'
store=True
last_source_scanned_commit
Char
last_target_scanned_commit
Char
maintainer_ids
Many2many
related='module_branch_id.maintainer_ids'
migration_path_id
Many2one → odoo.migration.path
comodel_name='odoo.migration.path'
index=True
ondelete='cascade'
required=True
migration_scan
Boolean
compute='_compute_migration_scan'
help='Technical field telling if this migration path needs a migration scan.'
store=True
module_branch_id
Many2one → odoo.module.branch
comodel_name='odoo.module.branch'
index=True
ondelete='cascade'
required=True
string='Source'
module_id
Many2one
index=True
related='module_branch_id.module_id'
store=True
moved_to_generic
Boolean
compute='_compute_moved_to_generic'
help="Specific module now available in a generic repository. This module is maybe not exactly the same, and doesn't have the same scope so it deserves a check during a migration."
store=True
string='Now generic'
moved_to_oca
Boolean
compute='_compute_moved_to_oca'
help="Module now available in OCA. This module is maybe not exactly the same, and doesn't have the same scope so it deserves a check during a migration."
store=True
moved_to_standard
Boolean
compute='_compute_moved_to_standard'
help="Module now available in Odoo standard code. This module is maybe not exactly the same, and doesn't have the same scope so it deserves a check during a migration."
store=True
org_id
Many2one
related='module_branch_id.org_id'
store=True
pr_url
Char
compute='_compute_pr_url'
store=True
string='PR URL'
process
Char
index=True
renamed_to_module_id
Many2one → odoo.module
comodel_name='odoo.module'
compute='_compute_renamed_to_module_id'
index=True
store=True
string='Renamed to'
replaced_by_module_id
Many2one → odoo.module
comodel_name='odoo.module'
compute='_compute_replaced_by_module_id'
index=True
store=True
string='Replaced by'
repository_id
Many2one
ondelete='cascade'
related='module_branch_id.repository_id'
store=True
results
Serialized
results_text
Text
compute='_compute_results_text'
source_branch_id
Many2one
index=True
related='migration_path_id.source_branch_id'
store=True
state
Selection
compute='_compute_state'
index=True
selection=[('fully_ported', 'Fully Ported'), ('migrate', 'To migrate'), ('port_commits', 'Ported (missing commits?)'), ('review_migration', 'To review'), ('replaced', 'Replaced'), ('moved_to_standard', 'Moved to standard?'), ('moved_to_oca', 'Moved to OCA'), ('moved_to_generic', 'Moved to generic repo')]
store=True
string='Migration Status'
target_branch_id
Many2one
index=True
related='migration_path_id.target_branch_id'
store=True
target_module_branch_id
Many2one → odoo.module.branch
comodel_name='odoo.module.branch'
compute='_compute_target_module_branch_id'
index=True
ondelete='cascade'
store=True
string='Target'
force_update(self)
push_scanned_data(self, module_branch_id, data)
active
Boolean
default=True
last_known_module_branch_id
Many2one → odoo.module.branch
comodel_name='odoo.module.branch'
compute='_compute_last_known_module_branch_id'
help='Technical field to check if current selected module is the last one.'
string='Last Known Module'
migration_ids
Many2many → odoo.module.branch.migration
comodel_name='odoo.module.branch.migration'
compute='_compute_migration_ids'
string='Migrations'
migration_scan
Boolean
compute='_compute_migration_scan'
help='Technical field telling if this timeline needs a migration scan.'
module_branch_id
Many2one → odoo.module.branch
comodel_name='odoo.module.branch'
index=True
required=True
string='Module'
next_module_branch_id
Many2one
related='module_branch_id.next_odoo_version_module_branch_id'
string='New module'
next_module_id
Many2one → odoo.module
comodel_name='odoo.module'
index=True
ondelete='restrict'
string='New module name'
note
Html
odoo_version_id
Many2one
index=True
related='module_branch_id.branch_id.next_id'
store=True
string='Starting from version'
odoo_version_sequence
Integer
related='odoo_version_id.sequence'
store=True
org_id
Many2one
index=True
related='module_branch_id.org_id'
store=True
string='Organization'
repository_id
Many2one
index=True
related='module_branch_id.repository_id'
store=True
string='Repository'
state
Selection
default='renamed'
help='Renamed: modules still share the same Git history (it allows to check commits that could be ported)\nReplaced: module has been replaced (or merged) by another one that fulfill the same feature'
index=True
required=True
selection=[('renamed', 'has been renamed to'), ('replaced', 'has been replaced by')]
action_scan(self)
create(self, vals_list)
open_migrations(self)
unlink(self)
write(self, vals)
collect_migration_data
Boolean
default=False
help='Collect migration data based on the configured migration paths.'
string='Collect migration data'
action_scan(self, branch_ids=None, force=False, raise_exc=True)
| REPOSITORY | |
|---|---|
| REPOSITORY | OCA/module-composition-analysis |
| GIT | |
| GIT | https://github.com/OCA/module-composition-analysis.git |
| GIT FOLDER | |
| GIT FOLDER | https://github.com/OCA/module-composition-analysis/tree/16.0/odoo_repository_migration |
| VERSION | |
| VERSION | 1.3.4 |
| CATEGORY | |
| CATEGORY | Tools |
| LICENSE | |
| LICENSE | AGPL-3 |
| APPLICATION | |
| APPLICATION | No |
| AUTO-INSTALLABLE | |
| AUTO-INSTALLABLE | No |
| AUTHORS | |
| AUTHORS | Odoo Community Association (OCA), Camptocamp |
| MAINTAINERS | |
| MAINTAINERS | Odoo Community Association (OCA), Camptocamp |
| COMMITTERS | |
| COMMITTERS | GitHub, Sébastien Alix, Weblate, OCA-git-bot, oca-ci |
| WEBSITE | |
| WEBSITE | https://github.com/OCA/module-composition-analysis |
| LAST TRACKING UPDATE | |
| LAST TRACKING UPDATE | 2026-07-06 19:12:08 |
| ODOO DEPENDENCIES | |
| ODOO DEPENDENCIES |
OCA/connector: - component OCA/module-composition-analysis: - odoo_repository OCA/queue: - queue_job OCA/server-tools: - base_time_window odoo/odoo: - base_sparse_field - base - base_setup - web - bus - web_tour |
| PYTHON DEPENDENCIES | |
| PYTHON DEPENDENCIES |
oca-port gitpython odoo-addons-parser pyyaml requests cachetools |
| SYSTEM DEPENDENCIES | |
| SYSTEM DEPENDENCIES | Not have |
| DESCRIPTION | |
| DESCRIPTION | This module collects and records modules migration data from Odoo repositories. Thanks to [oca-port](https://github.com/OCA/oca-port/) and data collected by `odoo_repository`, this module will generate migration data on each module for declared migration paths (e.g. 16.0 -> 18.0). Also, for specific cases you can declare what a module became in a given Odoo version, like OCA `web_domain_field` replaced by standard Odoo module `web` starting from 17.0 (with an optional explanation that could help users, like how to use this new module compared to the previous one). Given a migration path, a module can get one of this migration status: | Status | Description | | ------ | ----------- | | *Fully Ported* | All commits from source version are present in target version | | *To migrate* | The module doesn't exist on target version | | *Ported (missing commits?)* | Some commits from source version are not ported in target version (could be false-positive) | | *To review* | A migration PR has been detected | | *Replaced* | The module has been replaced by another one (not sharing the same git history) | | *Moved to standard?* | The module name has been detected in Odoo standard repositories for target version. High chance this module is or should be replaced by another one instead (by creating a timeline), so it mainly helps to detect such cases. | | *Moved to OCA* | the module name is available in an OCA repository (could be a false-positive because sharing the same name, in such case a timeline has to be created) | | *Moved to generic repo* | a specific module (only available in a project) in source version now exists in a generic repository (could be a false-positive if both modules have only their name in common) | It helps to build a consolidated knowledge database accross different Odoo versions for everyone: functionals and developers. |
| XML ID | Name | Model | Type | Status |
|---|---|---|---|---|
odoo_migration_path_view_form |
odoo.migration.path.form | odoo.migration.path | form | New |
odoo_migration_path_view_tree |
odoo.migration.path.tree | odoo.migration.path | tree | New |
odoo_module_branch_migration_view_form |
odoo.module.branch.migration.form | odoo.module.branch.migration | form | New |
odoo_module_branch_migration_view_search |
odoo.module.branch.migration.search | odoo.module.branch.migration | search | New |
odoo_module_branch_migration_view_tree |
odoo.module.branch.migration.tree | odoo.module.branch.migration | tree | New |
odoo_module_branch_timeline_view_form |
odoo.module.branch.timeline.form | odoo.module.branch.timeline | form | New |
odoo_module_branch_timeline_view_search |
odoo.module.branch.timeline.search | odoo.module.branch.timeline | search | New |
odoo_module_branch_timeline_view_tree |
odoo.module.branch.timeline.tree | odoo.module.branch.timeline | tree | New |
odoo_module_branch_view_form |
odoo.module.branch.form.inherit | odoo.module.branch | div | Inherits odoo_repository.odoo_module_branch_view_form |
odoo_module_branch_view_search |
odoo.module.branch.search.inherit | odoo.module.branch | filter | Inherits odoo_repository.odoo_module_branch_view_search |
odoo_repository_view_form |
odoo.repository.form.inherit | odoo.repository | group | Inherits odoo_repository.odoo_repository_view_form |
active
Boolean
default=True
name
Char
compute='_compute_name'
store=True
source_branch_id
Many2one → odoo.branch
comodel_name='odoo.branch'
ondelete='cascade'
required=True
target_branch_id
Many2one → odoo.branch
comodel_name='odoo.branch'
ondelete='cascade'
required=True
action_scan(self)
create(self, vals_list)
migration_ids
One2many → odoo.module.branch.migration
comodel_name='odoo.module.branch.migration'
inverse_name='module_branch_id'
string='Migrations'
migration_scan
Boolean
compute='_compute_migration_scan'
help='Technical field telling if this module is elligible for a migration scan.'
store=True
next_odoo_version_module_branch_id
Many2one → odoo.module.branch
comodel_name='odoo.module.branch'
compute='_compute_next_odoo_version_module_branch_id'
string='Next Odoo Version Module Branch'
timeline_ids
One2many → odoo.module.branch.timeline
comodel_name='odoo.module.branch.timeline'
inverse_name='module_branch_id'
string='Timeline'
create(self, vals_list)
open_next_module_branches(self)
write(self, vals)
active
Boolean
related='migration_path_id.active'
store=True
author_ids
Many2many
related='module_branch_id.author_ids'
display_name
Char
compute='_compute_display_name'
store=True
last_source_scanned_commit
Char
last_target_scanned_commit
Char
maintainer_ids
Many2many
related='module_branch_id.maintainer_ids'
migration_path_id
Many2one → odoo.migration.path
comodel_name='odoo.migration.path'
index=True
ondelete='cascade'
required=True
migration_scan
Boolean
compute='_compute_migration_scan'
help='Technical field telling if this migration path needs a migration scan.'
store=True
module_branch_id
Many2one → odoo.module.branch
comodel_name='odoo.module.branch'
index=True
ondelete='cascade'
required=True
string='Source'
module_id
Many2one
index=True
related='module_branch_id.module_id'
store=True
moved_to_generic
Boolean
compute='_compute_moved_to_generic'
help="Specific module now available in a generic repository. This module is maybe not exactly the same, and doesn't have the same scope so it deserves a check during a migration."
store=True
string='Now generic'
moved_to_oca
Boolean
compute='_compute_moved_to_oca'
help="Module now available in OCA. This module is maybe not exactly the same, and doesn't have the same scope so it deserves a check during a migration."
store=True
moved_to_standard
Boolean
compute='_compute_moved_to_standard'
help="Module now available in Odoo standard code. This module is maybe not exactly the same, and doesn't have the same scope so it deserves a check during a migration."
store=True
org_id
Many2one
related='module_branch_id.org_id'
store=True
pr_url
Char
compute='_compute_pr_url'
store=True
string='PR URL'
process
Char
index=True
renamed_to_module_id
Many2one → odoo.module
comodel_name='odoo.module'
compute='_compute_renamed_to_module_id'
index=True
store=True
string='Renamed to'
replaced_by_module_id
Many2one → odoo.module
comodel_name='odoo.module'
compute='_compute_replaced_by_module_id'
index=True
store=True
string='Replaced by'
repository_id
Many2one
ondelete='cascade'
related='module_branch_id.repository_id'
store=True
results
Serialized
results_text
Text
compute='_compute_results_text'
source_branch_id
Many2one
index=True
related='migration_path_id.source_branch_id'
store=True
state
Selection
compute='_compute_state'
index=True
selection=[('fully_ported', 'Fully Ported'), ('migrate', 'To migrate'), ('port_commits', 'Ported (missing commits?)'), ('review_migration', 'To review'), ('replaced', 'Replaced'), ('moved_to_standard', 'Moved to standard?'), ('moved_to_oca', 'Moved to OCA'), ('moved_to_generic', 'Moved to generic repo')]
store=True
string='Migration Status'
target_branch_id
Many2one
index=True
related='migration_path_id.target_branch_id'
store=True
target_module_branch_id
Many2one → odoo.module.branch
comodel_name='odoo.module.branch'
compute='_compute_target_module_branch_id'
index=True
ondelete='cascade'
store=True
string='Target'
push_scanned_data(self, module_branch_id, data)
module_branch_id
Many2one → odoo.module.branch
comodel_name='odoo.module.branch'
index=True
required=True
string='Module'
next_module_branch_id
Many2one
related='module_branch_id.next_odoo_version_module_branch_id'
string='New module'
next_module_id
Many2one → odoo.module
comodel_name='odoo.module'
index=True
inverse='_inverse_next_fields'
ondelete='restrict'
string='New module name'
note
Html
odoo_version_id
Many2one
index=True
related='module_branch_id.branch_id.next_id'
store=True
string='Starting from version'
odoo_version_sequence
Integer
related='odoo_version_id.sequence'
store=True
org_id
Many2one
index=True
related='module_branch_id.org_id'
store=True
string='Organization'
repository_id
Many2one
index=True
related='module_branch_id.repository_id'
store=True
string='Repository'
state
Selection
default='renamed'
help='Renamed: modules still share the same Git history (it allows to check commits that could be ported)\nReplaced: module has been replaced (or merged) by another one that fulfill the same feature'
index=True
inverse='_inverse_next_fields'
required=True
selection=[('renamed', 'has been renamed to'), ('replaced', 'has been replaced by')]
No public methods.
collect_migration_data
Boolean
default=False
help='Collect migration data based on the configured migration paths.'
string='Collect migration data'
action_scan(self, branch_ids=None, force=False, raise_exc=True)