[REF] rename files, apply OCA convention, remove obsolete 6.1 syntax, make the module installable, add readme folders
parent
ed44832568
commit
f29ff2daa7
|
@ -1,59 +1,8 @@
|
||||||
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png
|
================
|
||||||
:target: https://www.gnu.org/licenses/agpl
|
Upgrade Analysis
|
||||||
:alt: License: AGPL-3
|
================
|
||||||
|
|
||||||
===============================
|
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
OpenUpgrade Database Comparison
|
!! This file is generated by oca-gen-addon-readme !!
|
||||||
===============================
|
!! changes will be overwritten. !!
|
||||||
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
This module provides the tool to generate the database analysis files that indicate how the Odoo data model and module data have changed between two versions of Odoo. Database analysis files for the core modules are included in the OpenUpgrade distribution so as a migration script developer you will not usually need to use this tool yourself. If you do need to run your analysis of a custom set of modules, please refer to the documentation here: https://doc.therp.nl/openupgrade/analysis.html
|
|
||||||
|
|
||||||
Installation
|
|
||||||
============
|
|
||||||
|
|
||||||
This module has a python dependency on openerp-client-lib. You need to make this module available in your Python environment, for instance by installing it with the pip tool.
|
|
||||||
|
|
||||||
Known issues / Roadmap
|
|
||||||
======================
|
|
||||||
|
|
||||||
* scripts/compare_noupdate_xml_records.py should be integrated in the analysis process (#590)
|
|
||||||
* Log removed modules in the module that owned them (#468)
|
|
||||||
* Detect renamed many2many tables (#213)
|
|
||||||
|
|
||||||
Bug Tracker
|
|
||||||
===========
|
|
||||||
|
|
||||||
Bugs are tracked on `GitHub Issues
|
|
||||||
<https://github.com/OCA/openupgrade/issues>`_. In case of trouble, please
|
|
||||||
check there if your issue has already been reported. If you spotted it first,
|
|
||||||
help us smash it by providing detailed and welcomed feedback.
|
|
||||||
|
|
||||||
Images
|
|
||||||
------
|
|
||||||
|
|
||||||
* Odoo Community Association: `Icon <https://odoo-community.org/logo.png>`_.
|
|
||||||
|
|
||||||
Contributors
|
|
||||||
------------
|
|
||||||
|
|
||||||
* Stefan Rijnhart <stefan@opener.amsterdam>
|
|
||||||
* Holger Brunn <hbrunn@therp.nl>
|
|
||||||
* Pedro M. Baeza <pedro.baeza@gmail.com>
|
|
||||||
* Ferdinand Gassauer <gass@cc-l-12.chircar.at>
|
|
||||||
* Florent Xicluna <florent.xicluna@gmail.com>
|
|
||||||
* Miquel Raïch <miquel.raich@eficent.com>
|
|
||||||
|
|
||||||
Maintainer
|
|
||||||
----------
|
|
||||||
|
|
||||||
.. image:: https://odoo-community.org/logo.png
|
|
||||||
:alt: Odoo Community Association
|
|
||||||
:target: https://odoo-community.org
|
|
||||||
|
|
||||||
This module is maintained by the OCA.
|
|
||||||
|
|
||||||
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
|
||||||
mission is to support the collaborative development of Odoo features and
|
|
||||||
promote its widespread use.
|
|
||||||
|
|
||||||
To contribute to this module, please visit https://odoo-community.org.
|
|
||||||
|
|
|
@ -1,2 +1,5 @@
|
||||||
from . import models
|
from . import models
|
||||||
|
from . import wizards
|
||||||
from . import blacklist
|
from . import blacklist
|
||||||
|
from . import apriori
|
||||||
|
from . import compare
|
||||||
|
|
|
@ -2,18 +2,21 @@
|
||||||
# Copyright 2016 Opener B.V. <https://opener.am>
|
# Copyright 2016 Opener B.V. <https://opener.am>
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
{
|
{
|
||||||
"name": "OpenUpgrade Records",
|
"name": "Upgrade Analysis",
|
||||||
|
"summary": "performs a difference analysis between modules"
|
||||||
|
" installed on two different Odoo instances",
|
||||||
"version": "14.0.1.0.0",
|
"version": "14.0.1.0.0",
|
||||||
"category": "Migration",
|
"category": "Migration",
|
||||||
"author": "Therp BV, Opener B.V., Odoo Community Association (OCA)",
|
"author": "Therp BV, Opener B.V., GRAP, Odoo Community Association (OCA)",
|
||||||
"website": "https://github.com/OCA/server-tools",
|
"website": "https://github.com/OCA/server-tools",
|
||||||
"data": [
|
"data": [
|
||||||
"views/openupgrade_record.xml",
|
|
||||||
"views/comparison_config.xml",
|
|
||||||
"views/analysis_wizard.xml",
|
|
||||||
"views/generate_records_wizard.xml",
|
|
||||||
"views/install_all_wizard.xml",
|
|
||||||
"security/ir.model.access.csv",
|
"security/ir.model.access.csv",
|
||||||
|
"views/menu.xml",
|
||||||
|
"views/view_upgrade_comparison_config.xml",
|
||||||
|
"views/view_upgrade_record.xml",
|
||||||
|
"wizards/view_upgrade_analysis_wizard.xml",
|
||||||
|
"wizards/view_upgrade_generate_record_wizard.xml",
|
||||||
|
"wizards/view_upgrade_install_wizard.xml",
|
||||||
],
|
],
|
||||||
"installable": True,
|
"installable": True,
|
||||||
"external_dependencies": {
|
"external_dependencies": {
|
||||||
|
|
|
@ -2,97 +2,12 @@
|
||||||
to help the matching process
|
to help the matching process
|
||||||
"""
|
"""
|
||||||
|
|
||||||
renamed_modules = {
|
renamed_modules = {}
|
||||||
# Odoo
|
|
||||||
'crm_reveal': 'crm_iap_lead',
|
|
||||||
'document': 'attachment_indexation',
|
|
||||||
'payment_ogone': 'payment_ingenico',
|
|
||||||
# OCA/hr
|
|
||||||
# TODO: Transform possible data
|
|
||||||
'hr_skill': 'hr_skills'
|
|
||||||
}
|
|
||||||
|
|
||||||
merged_modules = {
|
merged_modules = {}
|
||||||
# Odoo
|
|
||||||
'account_cancel': 'account',
|
|
||||||
'account_voucher': 'account',
|
|
||||||
'crm_phone_validation': 'crm',
|
|
||||||
'decimal_precision': 'base',
|
|
||||||
'delivery_hs_code': 'delivery',
|
|
||||||
'hw_scale': 'hw_drivers',
|
|
||||||
'hw_scanner': 'hw_drivers',
|
|
||||||
'hw_screen': 'hw_drivers',
|
|
||||||
'l10n_fr_certification': 'account',
|
|
||||||
'l10n_fr_sale_closing': 'l10n_fr',
|
|
||||||
'mrp_bom_cost': 'mrp_account',
|
|
||||||
'mrp_byproduct': 'mrp',
|
|
||||||
'payment_stripe_sca': 'payment_stripe',
|
|
||||||
'stock_zebra': 'stock',
|
|
||||||
'survey_crm': 'survey',
|
|
||||||
'test_pylint': 'test_lint',
|
|
||||||
'web_settings_dashboard': 'base_setup',
|
|
||||||
'website_crm_phone_validation': 'website_crm',
|
|
||||||
'website_sale_link_tracker': 'website_sale',
|
|
||||||
'website_survey': 'survey',
|
|
||||||
# OCA/account-financial-tools
|
|
||||||
'account_move_chatter': 'account',
|
|
||||||
# OCA/account-reconcile
|
|
||||||
'account_set_reconcilable': 'account',
|
|
||||||
# OCA/l10n-spain
|
|
||||||
'l10n_es_aeat_sii': 'l10n_es_aeat_sii_oca',
|
|
||||||
# OCA/server-backend
|
|
||||||
'base_suspend_security': 'base',
|
|
||||||
# OCA/social
|
|
||||||
'mass_mailing_unique': 'mass_mailing',
|
|
||||||
# OCA/timesheet
|
|
||||||
'sale_timesheet_existing_project': 'sale_timesheet',
|
|
||||||
# OCA/web
|
|
||||||
'web_favicon': 'base',
|
|
||||||
'web_widget_color': 'web',
|
|
||||||
'web_widget_many2many_tags_multi_selection': 'web',
|
|
||||||
# OCA/website
|
|
||||||
'website_canonical_url': 'website',
|
|
||||||
'website_logo': 'website',
|
|
||||||
}
|
|
||||||
|
|
||||||
# only used here for openupgrade_records analysis:
|
# only used here for upgrade_analysis
|
||||||
renamed_models = {
|
renamed_models = {}
|
||||||
# Odoo
|
|
||||||
'account.register.payments': 'account.payment.register',
|
|
||||||
'crm.reveal.industry': 'crm.iap.lead.industry',
|
|
||||||
'crm.reveal.role': 'crm.iap.lead.role',
|
|
||||||
'crm.reveal.seniority': 'crm.iap.lead.seniority',
|
|
||||||
'mail.blacklist.mixin': 'mail.thread.blacklist',
|
|
||||||
'mail.mail.statistics': 'mailing.trace',
|
|
||||||
'mail.statistics.report': 'mailing.trace.report',
|
|
||||||
'mail.mass_mailing': 'mailing.mailing',
|
|
||||||
'mail.mass_mailing.contact': 'mailing.contact',
|
|
||||||
'mail.mass_mailing.list': 'mailing.list',
|
|
||||||
'mail.mass_mailing.list_contact_rel': 'mailing.contact.subscription',
|
|
||||||
'mail.mass_mailing.stage': 'utm.stage',
|
|
||||||
'mail.mass_mailing.tag': 'utm.tag',
|
|
||||||
'mail.mass_mailing.test': 'mailing.mailing.test',
|
|
||||||
'mass.mailing.list.merge': 'mailing.list.merge',
|
|
||||||
'mass.mailing.schedule.date': 'mailing.mailing.schedule.date',
|
|
||||||
'mrp.subproduct': 'mrp.bom.byproduct',
|
|
||||||
'sms.send_sms': 'sms.composer',
|
|
||||||
'stock.fixed.putaway.strat': 'stock.putaway.rule',
|
|
||||||
'survey.mail.compose.message': 'survey.invite',
|
|
||||||
'website.redirect': 'website.rewrite',
|
|
||||||
# OCA/...
|
|
||||||
}
|
|
||||||
|
|
||||||
# only used here for openupgrade_records analysis:
|
# only used here for upgrade_analysis
|
||||||
merged_models = {
|
merged_models = {}
|
||||||
# Odoo
|
|
||||||
'account.invoice': 'account.move',
|
|
||||||
'account.invoice.line': 'account.move.line',
|
|
||||||
'account.invoice.tax': 'account.move.line',
|
|
||||||
'account.voucher': 'account.move',
|
|
||||||
'account.voucher.line': 'account.move.line',
|
|
||||||
'lunch.order.line': 'lunch.order',
|
|
||||||
'mail.mass_mailing.campaign': 'utm.campaign',
|
|
||||||
'slide.category': 'slide.slide',
|
|
||||||
'survey.page': 'survey.question',
|
|
||||||
# OCA/...
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# coding: utf-8
|
|
||||||
# Copyright 2011-2015 Therp BV <https://therp.nl>
|
# Copyright 2011-2015 Therp BV <https://therp.nl>
|
||||||
# Copyright 2015-2016 Opener B.V. <https://opener.am>
|
# Copyright 2015-2016 Opener B.V. <https://opener.am>
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
# flake8: noqa: C901
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
# library providing a function to analyse two progressive database
|
# library providing a function to analyse two progressive database
|
||||||
|
@ -11,12 +11,13 @@
|
||||||
import collections
|
import collections
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from odoo.addons.openupgrade_records.lib import apriori
|
from . import apriori
|
||||||
|
|
||||||
|
|
||||||
def module_map(module):
|
def module_map(module):
|
||||||
return apriori.renamed_modules.get(
|
return apriori.renamed_modules.get(
|
||||||
module, apriori.merged_modules.get(module, module))
|
module, apriori.merged_modules.get(module, module)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def model_rename_map(model):
|
def model_rename_map(model):
|
||||||
|
@ -24,8 +25,7 @@ def model_rename_map(model):
|
||||||
|
|
||||||
|
|
||||||
def model_map(model):
|
def model_map(model):
|
||||||
return apriori.renamed_models.get(
|
return apriori.renamed_models.get(model, apriori.merged_models.get(model, model))
|
||||||
model, apriori.merged_models.get(model, model))
|
|
||||||
|
|
||||||
|
|
||||||
def inv_model_map(model):
|
def inv_model_map(model):
|
||||||
|
@ -34,12 +34,12 @@ def inv_model_map(model):
|
||||||
|
|
||||||
|
|
||||||
IGNORE_FIELDS = [
|
IGNORE_FIELDS = [
|
||||||
'create_date',
|
"create_date",
|
||||||
'create_uid',
|
"create_uid",
|
||||||
'id',
|
"id",
|
||||||
'write_date',
|
"write_date",
|
||||||
'write_uid',
|
"write_uid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def compare_records(dict_old, dict_new, fields):
|
def compare_records(dict_old, dict_new, fields):
|
||||||
|
@ -51,17 +51,19 @@ def compare_records(dict_old, dict_new, fields):
|
||||||
Return True of False.
|
Return True of False.
|
||||||
"""
|
"""
|
||||||
for field in fields:
|
for field in fields:
|
||||||
if field == 'module':
|
if field == "module":
|
||||||
if module_map(dict_old['module']) != dict_new['module']:
|
if module_map(dict_old["module"]) != dict_new["module"]:
|
||||||
return False
|
return False
|
||||||
elif field == 'model':
|
elif field == "model":
|
||||||
if model_rename_map(dict_old['model']) != dict_new['model']:
|
if model_rename_map(dict_old["model"]) != dict_new["model"]:
|
||||||
return False
|
return False
|
||||||
elif field == 'other_prefix':
|
elif field == "other_prefix":
|
||||||
if dict_old['module'] != dict_old['prefix'] or \
|
if (
|
||||||
dict_new['module'] != dict_new['prefix']:
|
dict_old["module"] != dict_old["prefix"]
|
||||||
|
or dict_new["module"] != dict_new["prefix"]
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
if dict_old['model'] == 'ir.ui.view':
|
if dict_old["model"] == "ir.ui.view":
|
||||||
# basically, to avoid the assets_backend case
|
# basically, to avoid the assets_backend case
|
||||||
return False
|
return False
|
||||||
elif dict_old[field] != dict_new[field]:
|
elif dict_old[field] != dict_new[field]:
|
||||||
|
@ -80,71 +82,69 @@ def search(item, item_list, fields):
|
||||||
continue
|
continue
|
||||||
return other
|
return other
|
||||||
# search for renamed fields
|
# search for renamed fields
|
||||||
if 'field' in fields:
|
if "field" in fields:
|
||||||
for other in item_list:
|
for other in item_list:
|
||||||
if not item['field'] or item['field'] is not None or \
|
if not item["field"] or item["field"] is not None or item["isproperty"]:
|
||||||
item['isproperty']:
|
|
||||||
continue
|
continue
|
||||||
if compare_records(
|
if compare_records(dict(item, field=other["field"]), other, fields):
|
||||||
dict(item, field=other['field']), other, fields):
|
|
||||||
return other
|
return other
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def fieldprint(old, new, field, text, reprs):
|
def fieldprint(old, new, field, text, reprs):
|
||||||
fieldrepr = "%s (%s)" % (old['field'], old['type'])
|
fieldrepr = "{} ({})".format(old["field"], old["type"])
|
||||||
fullrepr = '%-12s / %-24s / %-30s' % (
|
fullrepr = "{:<12} / {:<24} / {:<30}".format(old["module"], old["model"], fieldrepr)
|
||||||
old['module'], old['model'], fieldrepr)
|
|
||||||
if not text:
|
if not text:
|
||||||
text = "%s is now '%s' ('%s')" % (field, new[field], old[field])
|
text = "{} is now '{}' ('{}')".format(field, new[field], old[field])
|
||||||
if field == 'relation':
|
if field == "relation":
|
||||||
text += ' [nothing to do]'
|
text += " [nothing to do]"
|
||||||
reprs[module_map(old['module'])].append("%s: %s" % (fullrepr, text))
|
reprs[module_map(old["module"])].append("{}: {}".format(fullrepr, text))
|
||||||
if field == 'module':
|
if field == "module":
|
||||||
text = "previously in module %s" % old[field]
|
text = "previously in module %s" % old[field]
|
||||||
fullrepr = '%-12s / %-24s / %-30s' % (
|
fullrepr = "{:<12} / {:<24} / {:<30}".format(
|
||||||
new['module'], old['model'], fieldrepr)
|
new["module"], old["model"], fieldrepr
|
||||||
reprs[module_map(new['module'])].append("%s: %s" % (fullrepr, text))
|
)
|
||||||
|
reprs[module_map(new["module"])].append("{}: {}".format(fullrepr, text))
|
||||||
|
|
||||||
|
|
||||||
def report_generic(new, old, attrs, reprs):
|
def report_generic(new, old, attrs, reprs):
|
||||||
for attr in attrs:
|
for attr in attrs:
|
||||||
if attr == 'required':
|
if attr == "required":
|
||||||
if old[attr] != new['required'] and new['required']:
|
if old[attr] != new["required"] and new["required"]:
|
||||||
text = "now required"
|
text = "now required"
|
||||||
if new['req_default']:
|
if new["req_default"]:
|
||||||
text += ', req_default: %s' % new['req_default']
|
text += ", req_default: %s" % new["req_default"]
|
||||||
fieldprint(old, new, '', text, reprs)
|
fieldprint(old, new, "", text, reprs)
|
||||||
elif attr == 'stored':
|
elif attr == "stored":
|
||||||
if old[attr] != new[attr]:
|
if old[attr] != new[attr]:
|
||||||
if new['stored']:
|
if new["stored"]:
|
||||||
text = "is now stored"
|
text = "is now stored"
|
||||||
else:
|
else:
|
||||||
text = "not stored anymore"
|
text = "not stored anymore"
|
||||||
fieldprint(old, new, '', text, reprs)
|
fieldprint(old, new, "", text, reprs)
|
||||||
elif attr == 'isfunction':
|
elif attr == "isfunction":
|
||||||
if old[attr] != new[attr]:
|
if old[attr] != new[attr]:
|
||||||
if new['isfunction']:
|
if new["isfunction"]:
|
||||||
text = "now a function"
|
text = "now a function"
|
||||||
else:
|
else:
|
||||||
text = "not a function anymore"
|
text = "not a function anymore"
|
||||||
fieldprint(old, new, '', text, reprs)
|
fieldprint(old, new, "", text, reprs)
|
||||||
elif attr == 'isproperty':
|
elif attr == "isproperty":
|
||||||
if old[attr] != new[attr]:
|
if old[attr] != new[attr]:
|
||||||
if new[attr]:
|
if new[attr]:
|
||||||
text = "now a property"
|
text = "now a property"
|
||||||
else:
|
else:
|
||||||
text = "not a property anymore"
|
text = "not a property anymore"
|
||||||
fieldprint(old, new, '', text, reprs)
|
fieldprint(old, new, "", text, reprs)
|
||||||
elif attr == 'isrelated':
|
elif attr == "isrelated":
|
||||||
if old[attr] != new[attr]:
|
if old[attr] != new[attr]:
|
||||||
if new[attr]:
|
if new[attr]:
|
||||||
text = "now related"
|
text = "now related"
|
||||||
else:
|
else:
|
||||||
text = "not related anymore"
|
text = "not related anymore"
|
||||||
fieldprint(old, new, '', text, reprs)
|
fieldprint(old, new, "", text, reprs)
|
||||||
elif old[attr] != new[attr]:
|
elif old[attr] != new[attr]:
|
||||||
fieldprint(old, new, attr, '', reprs)
|
fieldprint(old, new, attr, "", reprs)
|
||||||
|
|
||||||
|
|
||||||
def compare_sets(old_records, new_records):
|
def compare_sets(old_records, new_records):
|
||||||
|
@ -160,7 +160,7 @@ def compare_sets(old_records, new_records):
|
||||||
def clean_records(records):
|
def clean_records(records):
|
||||||
result = []
|
result = []
|
||||||
for record in records:
|
for record in records:
|
||||||
if record['field'] not in IGNORE_FIELDS:
|
if record["field"] not in IGNORE_FIELDS:
|
||||||
result.append(record)
|
result.append(record)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -168,8 +168,8 @@ def compare_sets(old_records, new_records):
|
||||||
new_records = clean_records(new_records)
|
new_records = clean_records(new_records)
|
||||||
|
|
||||||
origlen = len(old_records)
|
origlen = len(old_records)
|
||||||
new_models = set([column['model'] for column in new_records])
|
new_models = {column["model"] for column in new_records}
|
||||||
old_models = set([column['model'] for column in old_records])
|
old_models = {column["model"] for column in old_records}
|
||||||
|
|
||||||
matched_direct = 0
|
matched_direct = 0
|
||||||
matched_other_module = 0
|
matched_other_module = 0
|
||||||
|
@ -184,7 +184,7 @@ def compare_sets(old_records, new_records):
|
||||||
|
|
||||||
non_obsolete_old_records = []
|
non_obsolete_old_records = []
|
||||||
for column in copy.copy(old_records):
|
for column in copy.copy(old_records):
|
||||||
if column['model'] in obsolete_models:
|
if column["model"] in obsolete_models:
|
||||||
in_obsolete_models += 1
|
in_obsolete_models += 1
|
||||||
else:
|
else:
|
||||||
non_obsolete_old_records.append(column)
|
non_obsolete_old_records.append(column)
|
||||||
|
@ -205,152 +205,193 @@ def compare_sets(old_records, new_records):
|
||||||
return count
|
return count
|
||||||
|
|
||||||
matched_direct = match(
|
matched_direct = match(
|
||||||
['module', 'mode', 'model', 'field'],
|
["module", "mode", "model", "field"],
|
||||||
['relation', 'type', 'selection_keys', 'inherits', 'stored',
|
[
|
||||||
'isfunction', 'isrelated', 'required', 'table'])
|
"relation",
|
||||||
|
"type",
|
||||||
|
"selection_keys",
|
||||||
|
"inherits",
|
||||||
|
"stored",
|
||||||
|
"isfunction",
|
||||||
|
"isrelated",
|
||||||
|
"required",
|
||||||
|
"table",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
# other module, same type and operation
|
# other module, same type and operation
|
||||||
matched_other_module = match(
|
matched_other_module = match(
|
||||||
['mode', 'model', 'field', 'type'],
|
["mode", "model", "field", "type"],
|
||||||
['module', 'relation', 'selection_keys', 'inherits', 'stored',
|
[
|
||||||
'isfunction', 'isrelated', 'required', 'table'])
|
"module",
|
||||||
|
"relation",
|
||||||
|
"selection_keys",
|
||||||
|
"inherits",
|
||||||
|
"stored",
|
||||||
|
"isfunction",
|
||||||
|
"isrelated",
|
||||||
|
"required",
|
||||||
|
"table",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
# other module, same operation, other type
|
# other module, same operation, other type
|
||||||
matched_other_type = match(
|
matched_other_type = match(
|
||||||
['mode', 'model', 'field'],
|
["mode", "model", "field"],
|
||||||
['relation', 'type', 'selection_keys', 'inherits', 'stored',
|
[
|
||||||
'isfunction', 'isrelated', 'required', 'table'])
|
"relation",
|
||||||
|
"type",
|
||||||
|
"selection_keys",
|
||||||
|
"inherits",
|
||||||
|
"stored",
|
||||||
|
"isfunction",
|
||||||
|
"isrelated",
|
||||||
|
"required",
|
||||||
|
"table",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
printkeys = [
|
printkeys = [
|
||||||
'relation', 'required', 'selection_keys',
|
"relation",
|
||||||
'req_default', 'inherits', 'mode', 'attachment',
|
"required",
|
||||||
]
|
"selection_keys",
|
||||||
|
"req_default",
|
||||||
|
"inherits",
|
||||||
|
"mode",
|
||||||
|
"attachment",
|
||||||
|
]
|
||||||
for column in old_records:
|
for column in old_records:
|
||||||
# we do not care about removed non stored function fields
|
# we do not care about removed non stored function fields
|
||||||
if not column['stored'] and (
|
if not column["stored"] and (column["isfunction"] or column["isrelated"]):
|
||||||
column['isfunction'] or column['isrelated']):
|
|
||||||
continue
|
continue
|
||||||
if column['mode'] == 'create':
|
if column["mode"] == "create":
|
||||||
column['mode'] = ''
|
column["mode"] = ""
|
||||||
extra_message = ", ".join(
|
extra_message = ", ".join(
|
||||||
[k + ': ' + str(column[k]) if k != str(column[k]) else k
|
[
|
||||||
for k in printkeys if column[k]]
|
k + ": " + str(column[k]) if k != str(column[k]) else k
|
||||||
|
for k in printkeys
|
||||||
|
if column[k]
|
||||||
|
]
|
||||||
)
|
)
|
||||||
if extra_message:
|
if extra_message:
|
||||||
extra_message = " " + extra_message
|
extra_message = " " + extra_message
|
||||||
fieldprint(
|
fieldprint(column, "", "", "DEL" + extra_message, reprs)
|
||||||
column, '', '', "DEL" + extra_message, reprs)
|
|
||||||
|
|
||||||
printkeys.extend([
|
printkeys.extend(
|
||||||
'hasdefault',
|
[
|
||||||
])
|
"hasdefault",
|
||||||
|
]
|
||||||
|
)
|
||||||
for column in new_records:
|
for column in new_records:
|
||||||
# we do not care about newly added non stored function fields
|
# we do not care about newly added non stored function fields
|
||||||
if not column['stored'] and (
|
if not column["stored"] and (column["isfunction"] or column["isrelated"]):
|
||||||
column['isfunction'] or column['isrelated']):
|
|
||||||
continue
|
continue
|
||||||
if column['mode'] == 'create':
|
if column["mode"] == "create":
|
||||||
column['mode'] = ''
|
column["mode"] = ""
|
||||||
printkeys_plus = printkeys.copy()
|
printkeys_plus = printkeys.copy()
|
||||||
if column['isfunction'] or column['isrelated']:
|
if column["isfunction"] or column["isrelated"]:
|
||||||
printkeys_plus.extend(['isfunction', 'isrelated', 'stored'])
|
printkeys_plus.extend(["isfunction", "isrelated", "stored"])
|
||||||
extra_message = ", ".join(
|
extra_message = ", ".join(
|
||||||
[k + ': ' + str(column[k]) if k != str(column[k]) else k
|
[
|
||||||
for k in printkeys_plus if column[k]]
|
k + ": " + str(column[k]) if k != str(column[k]) else k
|
||||||
|
for k in printkeys_plus
|
||||||
|
if column[k]
|
||||||
|
]
|
||||||
)
|
)
|
||||||
if extra_message:
|
if extra_message:
|
||||||
extra_message = " " + extra_message
|
extra_message = " " + extra_message
|
||||||
fieldprint(
|
fieldprint(column, "", "", "NEW" + extra_message, reprs)
|
||||||
column, '', '', "NEW" + extra_message, reprs)
|
|
||||||
|
|
||||||
for line in [
|
for line in [
|
||||||
"# %d fields matched," % (origlen - len(old_records)),
|
"# %d fields matched," % (origlen - len(old_records)),
|
||||||
"# Direct match: %d" % matched_direct,
|
"# Direct match: %d" % matched_direct,
|
||||||
"# Found in other module: %d" % matched_other_module,
|
"# Found in other module: %d" % matched_other_module,
|
||||||
"# Found with different type: %d" % matched_other_type,
|
"# Found with different type: %d" % matched_other_type,
|
||||||
"# In obsolete models: %d" % in_obsolete_models,
|
"# In obsolete models: %d" % in_obsolete_models,
|
||||||
"# Not matched: %d" % len(old_records),
|
"# Not matched: %d" % len(old_records),
|
||||||
"# New columns: %d" % len(new_records)
|
"# New columns: %d" % len(new_records),
|
||||||
]:
|
]:
|
||||||
reprs['general'].append(line)
|
reprs["general"].append(line)
|
||||||
return reprs
|
return reprs
|
||||||
|
|
||||||
|
|
||||||
def compare_xml_sets(old_records, new_records):
|
def compare_xml_sets(old_records, new_records):
|
||||||
reprs = collections.defaultdict(list)
|
reprs = collections.defaultdict(list)
|
||||||
|
|
||||||
def match(match_fields, match_type='direct'):
|
def match(match_fields, match_type="direct"):
|
||||||
matched_records = []
|
matched_records = []
|
||||||
for column in copy.copy(old_records):
|
for column in copy.copy(old_records):
|
||||||
found = search(column, new_records, match_fields)
|
found = search(column, new_records, match_fields)
|
||||||
if found:
|
if found:
|
||||||
old_records.remove(column)
|
old_records.remove(column)
|
||||||
new_records.remove(found)
|
new_records.remove(found)
|
||||||
if match_type != 'direct':
|
if match_type != "direct":
|
||||||
column['old'] = True
|
column["old"] = True
|
||||||
found['new'] = True
|
found["new"] = True
|
||||||
column[match_type] = found['module']
|
column[match_type] = found["module"]
|
||||||
found[match_type] = column['module']
|
found[match_type] = column["module"]
|
||||||
found['domain'] = column['domain'] != found['domain'] and \
|
found["domain"] = (
|
||||||
column['domain'] != '[]' and found['domain'] is False
|
column["domain"] != found["domain"]
|
||||||
column['domain'] = False
|
and column["domain"] != "[]"
|
||||||
column['noupdate_switched'] = False
|
and found["domain"] is False
|
||||||
found['noupdate_switched'] = \
|
)
|
||||||
column['noupdate'] != found['noupdate']
|
column["domain"] = False
|
||||||
if match_type != 'direct':
|
column["noupdate_switched"] = False
|
||||||
|
found["noupdate_switched"] = column["noupdate"] != found["noupdate"]
|
||||||
|
if match_type != "direct":
|
||||||
matched_records.append(column)
|
matched_records.append(column)
|
||||||
matched_records.append(found)
|
matched_records.append(found)
|
||||||
elif (match_type == 'direct' and found['domain']) or \
|
elif (match_type == "direct" and found["domain"]) or found[
|
||||||
found['noupdate_switched']:
|
"noupdate_switched"
|
||||||
|
]:
|
||||||
matched_records.append(found)
|
matched_records.append(found)
|
||||||
return matched_records
|
return matched_records
|
||||||
|
|
||||||
# direct match
|
# direct match
|
||||||
modified_records = match(['module', 'model', 'name'])
|
modified_records = match(["module", "model", "name"])
|
||||||
|
|
||||||
# other module, same full xmlid
|
# other module, same full xmlid
|
||||||
moved_records = match(['model', 'name'], 'moved')
|
moved_records = match(["model", "name"], "moved")
|
||||||
|
|
||||||
# other module, same suffix, other prefix
|
# other module, same suffix, other prefix
|
||||||
renamed_records = match(['model', 'suffix', 'other_prefix'], 'renamed')
|
renamed_records = match(["model", "suffix", "other_prefix"], "renamed")
|
||||||
|
|
||||||
for record in old_records:
|
for record in old_records:
|
||||||
record['old'] = True
|
record["old"] = True
|
||||||
record['domain'] = False
|
record["domain"] = False
|
||||||
record['noupdate_switched'] = False
|
record["noupdate_switched"] = False
|
||||||
for record in new_records:
|
for record in new_records:
|
||||||
record['new'] = True
|
record["new"] = True
|
||||||
record['domain'] = False
|
record["domain"] = False
|
||||||
record['noupdate_switched'] = False
|
record["noupdate_switched"] = False
|
||||||
|
|
||||||
sorted_records = sorted(
|
sorted_records = sorted(
|
||||||
old_records + new_records + moved_records + renamed_records +
|
old_records + new_records + moved_records + renamed_records + modified_records,
|
||||||
modified_records,
|
key=lambda k: (k["model"], "old" in k, k["name"]),
|
||||||
key=lambda k: (k['model'], 'old' in k, k['name'])
|
|
||||||
)
|
)
|
||||||
for entry in sorted_records:
|
for entry in sorted_records:
|
||||||
content = ''
|
content = ""
|
||||||
if 'old' in entry:
|
if "old" in entry:
|
||||||
content = 'DEL %(model)s: %(name)s' % entry
|
content = "DEL %(model)s: %(name)s" % entry
|
||||||
if 'moved' in entry:
|
if "moved" in entry:
|
||||||
content += ' [potentially moved to %(moved)s module]' % entry
|
content += " [potentially moved to %(moved)s module]" % entry
|
||||||
elif 'renamed' in entry:
|
elif "renamed" in entry:
|
||||||
content += ' [renamed to %(renamed)s module]' % entry
|
content += " [renamed to %(renamed)s module]" % entry
|
||||||
elif 'new' in entry:
|
elif "new" in entry:
|
||||||
content = 'NEW %(model)s: %(name)s' % entry
|
content = "NEW %(model)s: %(name)s" % entry
|
||||||
if 'moved' in entry:
|
if "moved" in entry:
|
||||||
content += ' [potentially moved from %(moved)s module]' % entry
|
content += " [potentially moved from %(moved)s module]" % entry
|
||||||
elif 'renamed' in entry:
|
elif "renamed" in entry:
|
||||||
content += ' [renamed from %(renamed)s module]' % entry
|
content += " [renamed from %(renamed)s module]" % entry
|
||||||
if 'old' not in entry and 'new' not in entry:
|
if "old" not in entry and "new" not in entry:
|
||||||
content = '%(model)s: %(name)s' % entry
|
content = "%(model)s: %(name)s" % entry
|
||||||
if entry['domain']:
|
if entry["domain"]:
|
||||||
content += ' (deleted domain)'
|
content += " (deleted domain)"
|
||||||
if entry['noupdate']:
|
if entry["noupdate"]:
|
||||||
content += ' (noupdate)'
|
content += " (noupdate)"
|
||||||
if entry['noupdate_switched']:
|
if entry["noupdate_switched"]:
|
||||||
content += ' (noupdate switched)'
|
content += " (noupdate switched)"
|
||||||
reprs[module_map(entry['module'])].append(content)
|
reprs[module_map(entry["module"])].append(content)
|
||||||
return reprs
|
return reprs
|
||||||
|
|
||||||
|
|
||||||
|
@ -360,79 +401,84 @@ def compare_model_sets(old_records, new_records):
|
||||||
"""
|
"""
|
||||||
reprs = collections.defaultdict(list)
|
reprs = collections.defaultdict(list)
|
||||||
|
|
||||||
new_models = {column['model']: column['module'] for column in new_records}
|
new_models = {column["model"]: column["module"] for column in new_records}
|
||||||
old_models = {column['model']: column['module'] for column in old_records}
|
old_models = {column["model"]: column["module"] for column in old_records}
|
||||||
|
|
||||||
obsolete_models = []
|
obsolete_models = []
|
||||||
for column in copy.copy(old_records):
|
for column in copy.copy(old_records):
|
||||||
model = column['model']
|
model = column["model"]
|
||||||
if model in old_models:
|
if model in old_models:
|
||||||
if model not in new_models:
|
if model not in new_models:
|
||||||
if model_map(model) not in new_models:
|
if model_map(model) not in new_models:
|
||||||
obsolete_models.append(model)
|
obsolete_models.append(model)
|
||||||
text = 'obsolete model %s' % model
|
text = "obsolete model %s" % model
|
||||||
if column['model_type']:
|
if column["model_type"]:
|
||||||
text += " [%s]" % column['model_type']
|
text += " [%s]" % column["model_type"]
|
||||||
reprs[module_map(column['module'])].append(text)
|
reprs[module_map(column["module"])].append(text)
|
||||||
reprs['general'].append('obsolete model %s [module %s]' % (
|
reprs["general"].append(
|
||||||
model, module_map(column['module'])))
|
"obsolete model %s [module %s]"
|
||||||
|
% (model, module_map(column["module"]))
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
moved_module = ''
|
moved_module = ""
|
||||||
if module_map(column['module']) != new_models[model_map(
|
if module_map(column["module"]) != new_models[model_map(model)]:
|
||||||
model)]:
|
moved_module = " in module %s" % new_models[model_map(model)]
|
||||||
moved_module = ' in module %s' % new_models[model_map(
|
text = "obsolete model {} (renamed to {}{})".format(
|
||||||
model)]
|
model,
|
||||||
text = 'obsolete model %s (renamed to %s%s)' % (
|
model_map(model),
|
||||||
model, model_map(model), moved_module)
|
moved_module,
|
||||||
if column['model_type']:
|
)
|
||||||
text += " [%s]" % column['model_type']
|
if column["model_type"]:
|
||||||
reprs[module_map(column['module'])].append(text)
|
text += " [%s]" % column["model_type"]
|
||||||
reprs['general'].append(
|
reprs[module_map(column["module"])].append(text)
|
||||||
'obsolete model %s (renamed to %s) [module %s]' % (
|
reprs["general"].append(
|
||||||
model, model_map(model),
|
"obsolete model %s (renamed to %s) [module %s]"
|
||||||
module_map(column['module'])))
|
% (model, model_map(model), module_map(column["module"]))
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if module_map(column['module']) != new_models[model]:
|
if module_map(column["module"]) != new_models[model]:
|
||||||
text = 'model %s (moved to %s)' % (
|
text = "model {} (moved to {})".format(model, new_models[model])
|
||||||
model, new_models[model])
|
if column["model_type"]:
|
||||||
if column['model_type']:
|
text += " [%s]" % column["model_type"]
|
||||||
text += " [%s]" % column['model_type']
|
reprs[module_map(column["module"])].append(text)
|
||||||
reprs[module_map(column['module'])].append(text)
|
text = "model {} (moved from {})".format(model, old_models[model])
|
||||||
text = 'model %s (moved from %s)' % (
|
if column["model_type"]:
|
||||||
model, old_models[model])
|
text += " [%s]" % column["model_type"]
|
||||||
if column['model_type']:
|
|
||||||
text += " [%s]" % column['model_type']
|
|
||||||
|
|
||||||
for column in copy.copy(new_records):
|
for column in copy.copy(new_records):
|
||||||
model = column['model']
|
model = column["model"]
|
||||||
if model in new_models:
|
if model in new_models:
|
||||||
if model not in old_models:
|
if model not in old_models:
|
||||||
if inv_model_map(model) not in old_models:
|
if inv_model_map(model) not in old_models:
|
||||||
text = 'new model %s' % model
|
text = "new model %s" % model
|
||||||
if column['model_type']:
|
if column["model_type"]:
|
||||||
text += " [%s]" % column['model_type']
|
text += " [%s]" % column["model_type"]
|
||||||
reprs[column['module']].append(text)
|
reprs[column["module"]].append(text)
|
||||||
reprs['general'].append('new model %s [module %s]' % (
|
reprs["general"].append(
|
||||||
model, column['module']))
|
"new model {} [module {}]".format(model, column["module"])
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
moved_module = ''
|
moved_module = ""
|
||||||
if column['module'] != module_map(old_models[inv_model_map(
|
if column["module"] != module_map(old_models[inv_model_map(model)]):
|
||||||
model)]):
|
moved_module = (
|
||||||
moved_module = ' in module %s' % old_models[
|
" in module %s" % old_models[inv_model_map(model)]
|
||||||
inv_model_map(model)]
|
)
|
||||||
text = 'new model %s (renamed from %s%s)' % (
|
text = "new model {} (renamed from {}{})".format(
|
||||||
model, inv_model_map(model), moved_module)
|
model,
|
||||||
if column['model_type']:
|
inv_model_map(model),
|
||||||
text += " [%s]" % column['model_type']
|
moved_module,
|
||||||
reprs[column['module']].append(text)
|
)
|
||||||
reprs['general'].append(
|
if column["model_type"]:
|
||||||
'new model %s (renamed from %s) [module %s]' % (
|
text += " [%s]" % column["model_type"]
|
||||||
model, inv_model_map(model), column['module']))
|
reprs[column["module"]].append(text)
|
||||||
|
reprs["general"].append(
|
||||||
|
"new model %s (renamed from %s) [module %s]"
|
||||||
|
% (model, inv_model_map(model), column["module"])
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if column['module'] != module_map(old_models[model]):
|
if column["module"] != module_map(old_models[model]):
|
||||||
text = 'model %s (moved from %s)' % (
|
text = "model {} (moved from {})".format(model, old_models[model])
|
||||||
model, old_models[model])
|
if column["model_type"]:
|
||||||
if column['model_type']:
|
text += " [%s]" % column["model_type"]
|
||||||
text += " [%s]" % column['model_type']
|
reprs[column["module"]].append(text)
|
||||||
reprs[column['module']].append(text)
|
|
||||||
return reprs
|
return reprs
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from . import openupgrade_record
|
from . import upgrade_comparison_config
|
||||||
from . import comparison_config
|
from . import upgrade_attribute
|
||||||
from . import analysis_wizard
|
from . import upgrade_record
|
||||||
from . import generate_records_wizard
|
|
||||||
from . import install_all_wizard
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Copyright 2011-2015 Therp BV <https://therp.nl>
|
||||||
|
# Copyright 2016 Opener B.V. <https://opener.am>
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
from odoo import fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class UpgradeAttribute(models.Model):
|
||||||
|
_name = "upgrade.attribute"
|
||||||
|
_description = "Upgrade Attribute"
|
||||||
|
|
||||||
|
name = fields.Char(readonly=True)
|
||||||
|
|
||||||
|
value = fields.Char(readonly=True)
|
||||||
|
|
||||||
|
record_id = fields.Many2one(
|
||||||
|
comodel_name="upgrade.record",
|
||||||
|
ondelete="CASCADE",
|
||||||
|
readonly=True,
|
||||||
|
)
|
|
@ -8,25 +8,25 @@ from odoo import fields, models
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
from odoo.tools.translate import _
|
from odoo.tools.translate import _
|
||||||
|
|
||||||
from ..lib import apriori
|
from .. import apriori
|
||||||
|
|
||||||
|
|
||||||
class OpenupgradeComparisonConfig(models.Model):
|
class UpgradeComparisonConfig(models.Model):
|
||||||
_name = "openupgrade.comparison.config"
|
_name = "upgrade.comparison.config"
|
||||||
_description = "OpenUpgrade Comparison Configuration"
|
_description = "Upgrade Comparison Configuration"
|
||||||
|
|
||||||
name = fields.Char()
|
name = fields.Char()
|
||||||
server = fields.Char(required=True)
|
|
||||||
|
server = fields.Char(required=True, default="localhost")
|
||||||
|
|
||||||
port = fields.Integer(required=True, default=8069)
|
port = fields.Integer(required=True, default=8069)
|
||||||
protocol = fields.Selection(
|
|
||||||
[("http://", "XML-RPC")],
|
|
||||||
# ('https://', 'XML-RPC Secure')], not supported by libopenerp
|
|
||||||
required=True,
|
|
||||||
default="http://",
|
|
||||||
)
|
|
||||||
database = fields.Char(required=True)
|
database = fields.Char(required=True)
|
||||||
username = fields.Char(required=True)
|
|
||||||
password = fields.Char(required=True)
|
username = fields.Char(required=True, default="admin")
|
||||||
|
|
||||||
|
password = fields.Char(required=True, default="admin")
|
||||||
|
|
||||||
last_log = fields.Text()
|
last_log = fields.Text()
|
||||||
|
|
||||||
def get_connection(self):
|
def get_connection(self):
|
||||||
|
@ -51,8 +51,8 @@ class OpenupgradeComparisonConfig(models.Model):
|
||||||
def analyze(self):
|
def analyze(self):
|
||||||
""" Run the analysis wizard """
|
""" Run the analysis wizard """
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
wizard = self.env["openupgrade.analysis.wizard"].create(
|
wizard = self.env["upgrade.analysis.wizard"].create(
|
||||||
{"server_config": self.id}
|
{"server_config_id": self.id}
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
"name": wizard._description,
|
"name": wizard._description,
|
|
@ -5,27 +5,18 @@
|
||||||
from odoo import api, fields, models
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
|
||||||
class Attribute(models.Model):
|
class UpgradeRecord(models.Model):
|
||||||
_name = "openupgrade.attribute"
|
_name = "upgrade.record"
|
||||||
_description = "OpenUpgrade Attribute"
|
_description = "Upgrade Record"
|
||||||
|
|
||||||
name = fields.Char(readonly=True)
|
name = fields.Char(readonly=True)
|
||||||
value = fields.Char(readonly=True)
|
|
||||||
record_id = fields.Many2one(
|
|
||||||
"openupgrade.record",
|
|
||||||
ondelete="CASCADE",
|
|
||||||
readonly=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Record(models.Model):
|
|
||||||
_name = "openupgrade.record"
|
|
||||||
_description = "OpenUpgrade Record"
|
|
||||||
|
|
||||||
name = fields.Char(readonly=True)
|
|
||||||
module = fields.Char(readonly=True)
|
module = fields.Char(readonly=True)
|
||||||
|
|
||||||
model = fields.Char(readonly=True)
|
model = fields.Char(readonly=True)
|
||||||
|
|
||||||
field = fields.Char(readonly=True)
|
field = fields.Char(readonly=True)
|
||||||
|
|
||||||
mode = fields.Selection(
|
mode = fields.Selection(
|
||||||
[("create", "Create"), ("modify", "Modify")],
|
[("create", "Create"), ("modify", "Modify")],
|
||||||
help="Set to Create if a field is newly created "
|
help="Set to Create if a field is newly created "
|
||||||
|
@ -33,16 +24,26 @@ class Record(models.Model):
|
||||||
"existing field, set to Modify.",
|
"existing field, set to Modify.",
|
||||||
readonly=True,
|
readonly=True,
|
||||||
)
|
)
|
||||||
type = fields.Selection( # Uh oh, reserved keyword
|
|
||||||
|
type = fields.Selection(
|
||||||
[("field", "Field"), ("xmlid", "XML ID"), ("model", "Model")],
|
[("field", "Field"), ("xmlid", "XML ID"), ("model", "Model")],
|
||||||
readonly=True,
|
readonly=True,
|
||||||
)
|
)
|
||||||
attribute_ids = fields.One2many("openupgrade.attribute", "record_id", readonly=True)
|
|
||||||
|
attribute_ids = fields.One2many(
|
||||||
|
comodel_name="upgrade.attribute", inverse_name="record_id", readonly=True
|
||||||
|
)
|
||||||
|
|
||||||
noupdate = fields.Boolean(readonly=True)
|
noupdate = fields.Boolean(readonly=True)
|
||||||
|
|
||||||
domain = fields.Char(readonly=True)
|
domain = fields.Char(readonly=True)
|
||||||
|
|
||||||
prefix = fields.Char(compute="_compute_prefix_and_suffix")
|
prefix = fields.Char(compute="_compute_prefix_and_suffix")
|
||||||
|
|
||||||
suffix = fields.Char(compute="_compute_prefix_and_suffix")
|
suffix = fields.Char(compute="_compute_prefix_and_suffix")
|
||||||
|
|
||||||
model_original_module = fields.Char(compute="_compute_model_original_module")
|
model_original_module = fields.Char(compute="_compute_model_original_module")
|
||||||
|
|
||||||
model_type = fields.Char(compute="_compute_model_type")
|
model_type = fields.Char(compute="_compute_model_type")
|
||||||
|
|
||||||
@api.depends("name")
|
@api.depends("name")
|
|
@ -0,0 +1,7 @@
|
||||||
|
* Stefan Rijnhart <stefan@opener.amsterdam>
|
||||||
|
* Holger Brunn <hbrunn@therp.nl>
|
||||||
|
* Pedro M. Baeza <pedro.baeza@gmail.com>
|
||||||
|
* Ferdinand Gassauer <gass@cc-l-12.chircar.at>
|
||||||
|
* Florent Xicluna <florent.xicluna@gmail.com>
|
||||||
|
* Miquel Raïch <miquel.raich@eficent.com>
|
||||||
|
* Sylvain LE GAL <https://twitter.com/legalsylvain>
|
|
@ -0,0 +1 @@
|
||||||
|
This module provides the tool to generate the database analysis files that indicate how the Odoo data model and module data have changed between two versions of Odoo. Database analysis files for the core modules are included in the OpenUpgrade distribution so as a migration script developer you will not usually need to use this tool yourself. If you do need to run your analysis of a custom set of modules, please refer to the documentation here: https://doc.therp.nl/openupgrade/analysis.html
|
|
@ -0,0 +1,3 @@
|
||||||
|
* scripts/compare_noupdate_xml_records.py should be integrated in the analysis process (#590)
|
||||||
|
* Log removed modules in the module that owned them (#468)
|
||||||
|
* Detect renamed many2many tables (#213)
|
|
@ -1,4 +1,7 @@
|
||||||
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
"access_openupgrade_record","openupgrade.record all","model_openupgrade_record",,1,0,0,0
|
access_upgrade_record,upgrade.record all,model_upgrade_record,,1,0,0,0
|
||||||
"access_openupgrade_attribute","openupgrade.attribute all","model_openupgrade_attribute",,1,0,0,0
|
access_upgrade_attribute,upgrade.attribute all,model_upgrade_attribute,,1,0,0,0
|
||||||
"access_openupgrade_comparison_config","openupgrade.comparison.config","model_openupgrade_comparison_config",base.group_system,1,1,1,1
|
access_upgrade_comparison_config,upgrade.comparison.config,model_upgrade_comparison_config,base.group_system,1,1,1,1
|
||||||
|
access_upgrade_analysis_wizard,access_upgrade_analysis_wizard,model_upgrade_analysis_wizard,base.group_system,1,1,1,1
|
||||||
|
access_upgrade_generate_record_wizard,access_upgrade_generate_record_wizard,model_upgrade_generate_record_wizard,base.group_system,1,1,1,1
|
||||||
|
access_upgrade_install_wizard,access_upgrade_install_wizard,model_upgrade_install_wizard,base.group_system,1,1,1,1
|
||||||
|
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<!-- Top level menu under 'Database structure' -->
|
||||||
|
<menuitem
|
||||||
|
id="menu_upgrade"
|
||||||
|
name="upgrade Development"
|
||||||
|
parent="base.menu_administration"
|
||||||
|
sequence="99"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</odoo>
|
|
@ -1,13 +1,11 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record id="view_openupgrade_comparison_config_tree" model="ir.ui.view">
|
<record id="view_upgrade_comparison_config_tree" model="ir.ui.view">
|
||||||
<field name="name">view.openupgrade.comparison_config.tree</field>
|
<field name="model">upgrade.comparison.config</field>
|
||||||
<field name="model">openupgrade.comparison.config</field>
|
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="OpenUpgrade Comparison Config">
|
<tree>
|
||||||
<field name="name" />
|
<field name="name" />
|
||||||
<field name="protocol" />
|
|
||||||
<field name="server" />
|
<field name="server" />
|
||||||
<field name="port" />
|
<field name="port" />
|
||||||
<field name="database" />
|
<field name="database" />
|
||||||
|
@ -15,14 +13,12 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_openupgrade_comparison_config_form" model="ir.ui.view">
|
<record id="view_upgrade_comparison_config_form" model="ir.ui.view">
|
||||||
<field name="name">view.openupgrade.comparison_config.form</field>
|
<field name="model">upgrade.comparison.config</field>
|
||||||
<field name="model">openupgrade.comparison.config</field>
|
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="OpenUpgrade Comparison Config" version="6.1">
|
<form>
|
||||||
<group>
|
<group>
|
||||||
<field name="name" />
|
<field name="name" />
|
||||||
<field name="protocol" />
|
|
||||||
<field name="server" />
|
<field name="server" />
|
||||||
<field name="port" />
|
<field name="port" />
|
||||||
<field name="database" />
|
<field name="database" />
|
||||||
|
@ -57,21 +53,18 @@
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
)
|
|
||||||
<record
|
<record id="action_upgrade_comparison_config_tree" model="ir.actions.act_window">
|
||||||
id="action_openupgrade_comparison_config_tree"
|
<field name="name">upgrade Comparison Configs</field>
|
||||||
model="ir.actions.act_window"
|
|
||||||
>
|
|
||||||
<field name="name">OpenUpgrade Comparison Configs</field>
|
|
||||||
<field name="type">ir.actions.act_window</field>
|
<field name="type">ir.actions.act_window</field>
|
||||||
<field name="res_model">openupgrade.comparison.config</field>
|
<field name="res_model">upgrade.comparison.config</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
action="action_openupgrade_comparison_config_tree"
|
action="action_upgrade_comparison_config_tree"
|
||||||
id="menu_openupgrade_comparison_config"
|
id="menu_upgrade_comparison_config"
|
||||||
name="Comparison Configurations"
|
name="Comparison Configurations"
|
||||||
parent="menu_openupgrade"
|
parent="menu_upgrade"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
|
@ -1,17 +1,8 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<!-- Top level menu under 'Database structure' -->
|
<record id="view_upgrade_record_search" model="ir.ui.view">
|
||||||
<menuitem
|
<field name="model">upgrade.record</field>
|
||||||
id="menu_openupgrade"
|
|
||||||
name="OpenUpgrade Development"
|
|
||||||
parent="base.menu_administration"
|
|
||||||
sequence="99"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<record id="view_openupgrade_record_search" model="ir.ui.view">
|
|
||||||
<field name="name">Search view for openupgrade records</field>
|
|
||||||
<field name="model">openupgrade.record</field>
|
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<search>
|
<search>
|
||||||
<field name="module" />
|
<field name="module" />
|
||||||
|
@ -39,11 +30,10 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_openupgrade_record_tree" model="ir.ui.view">
|
<record id="view_upgrade_record_tree" model="ir.ui.view">
|
||||||
<field name="name">view.openupgrade.record.tree</field>
|
<field name="model">upgrade.record</field>
|
||||||
<field name="model">openupgrade.record</field>
|
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="OpenUpgrade Records">
|
<tree>
|
||||||
<field name="module" />
|
<field name="module" />
|
||||||
<field name="model" />
|
<field name="model" />
|
||||||
<field name="field" />
|
<field name="field" />
|
||||||
|
@ -54,11 +44,10 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_openupgrade_record_form" model="ir.ui.view">
|
<record id="view_upgrade_record_form" model="ir.ui.view">
|
||||||
<field name="name">view.openupgrade.record.form</field>
|
<field name="model">upgrade.record</field>
|
||||||
<field name="model">openupgrade.record</field>
|
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="OpenUpgrade Record" version="6.1">
|
<form>
|
||||||
<field name="module" />
|
<field name="module" />
|
||||||
<field name="model" />
|
<field name="model" />
|
||||||
<field name="field" />
|
<field name="field" />
|
||||||
|
@ -80,17 +69,17 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="action_openupgrade_record_tree" model="ir.actions.act_window">
|
<record id="action_upgrade_record_tree" model="ir.actions.act_window">
|
||||||
<field name="name">OpenUpgrade Records</field>
|
<field name="name">upgrade Records</field>
|
||||||
<field name="type">ir.actions.act_window</field>
|
<field name="type">ir.actions.act_window</field>
|
||||||
<field name="res_model">openupgrade.record</field>
|
<field name="res_model">upgrade.record</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
action="action_openupgrade_record_tree"
|
action="action_upgrade_record_tree"
|
||||||
id="menu_openupgrade_records"
|
id="menu_upgrade_records"
|
||||||
name="Records"
|
name="Records"
|
||||||
parent="menu_openupgrade"
|
parent="menu_upgrade"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
|
@ -0,0 +1,3 @@
|
||||||
|
from . import upgrade_analysis_wizard
|
||||||
|
from . import upgrade_generate_record_wizard
|
||||||
|
from . import upgrade_install_wizard
|
|
@ -8,15 +8,15 @@ import os
|
||||||
from odoo import fields, models
|
from odoo import fields, models
|
||||||
from odoo.modules import get_module_path
|
from odoo.modules import get_module_path
|
||||||
|
|
||||||
from ..lib import compare
|
from .. import compare
|
||||||
|
|
||||||
|
|
||||||
class AnalysisWizard(models.TransientModel):
|
class UpgradeAnalysisWizard(models.TransientModel):
|
||||||
_name = "openupgrade.analysis.wizard"
|
_name = "upgrade.analysis.wizard"
|
||||||
_description = "OpenUpgrade Analysis Wizard"
|
_description = "upgrade Analysis Wizard"
|
||||||
|
|
||||||
server_config = fields.Many2one(
|
server_config_id = fields.Many2one(
|
||||||
"openupgrade.comparison.config", "Configuration", required=True
|
"upgrade.comparison.config", "Configuration", required=True
|
||||||
)
|
)
|
||||||
state = fields.Selection(
|
state = fields.Selection(
|
||||||
[("init", "Init"), ("ready", "Ready")], readonly=True, default="init"
|
[("init", "Init"), ("ready", "Ready")], readonly=True, default="init"
|
||||||
|
@ -33,7 +33,7 @@ class AnalysisWizard(models.TransientModel):
|
||||||
change set
|
change set
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def write_file(module, version, content, filename="openupgrade_analysis.txt"):
|
def write_file(module, version, content, filename="upgrade_analysis.txt"):
|
||||||
module_path = get_module_path(module)
|
module_path = get_module_path(module)
|
||||||
if not module_path:
|
if not module_path:
|
||||||
return "ERROR: could not find module path:\n"
|
return "ERROR: could not find module path:\n"
|
||||||
|
@ -53,9 +53,9 @@ class AnalysisWizard(models.TransientModel):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
connection = self.server_config.get_connection()
|
connection = self.server_config_id.get_connection()
|
||||||
remote_record_obj = connection.env["openupgrade.record"]
|
remote_record_obj = connection.env["upgrade.record"]
|
||||||
local_record_obj = self.env["openupgrade.record"]
|
local_record_obj = self.env["upgrade.record"]
|
||||||
|
|
||||||
# Retrieve field representations and compare
|
# Retrieve field representations and compare
|
||||||
remote_records = remote_record_obj.field_dump()
|
remote_records = remote_record_obj.field_dump()
|
||||||
|
@ -168,9 +168,9 @@ class AnalysisWizard(models.TransientModel):
|
||||||
"base",
|
"base",
|
||||||
modules["base"].installed_version,
|
modules["base"].installed_version,
|
||||||
general,
|
general,
|
||||||
"openupgrade_general_log.txt",
|
"upgrade_general_log.txt",
|
||||||
)
|
)
|
||||||
self.server_config.write({"last_log": general})
|
self.server_config_id.write({"last_log": general})
|
||||||
self.write({"state": "ready", "log": general})
|
self.write({"state": "ready", "log": general})
|
||||||
|
|
||||||
return {
|
return {
|
|
@ -10,8 +10,8 @@ from odoo.modules.registry import Registry
|
||||||
|
|
||||||
|
|
||||||
class GenerateWizard(models.TransientModel):
|
class GenerateWizard(models.TransientModel):
|
||||||
_name = "openupgrade.generate.records.wizard"
|
_name = "upgrade.generate.record.wizard"
|
||||||
_description = "OpenUpgrade Generate Records Wizard"
|
_description = "Upgrade Generate Record Wizard"
|
||||||
_rec_name = "state"
|
_rec_name = "state"
|
||||||
|
|
||||||
state = fields.Selection([("init", "init"), ("ready", "ready")], default="init")
|
state = fields.Selection([("init", "init"), ("ready", "ready")], default="init")
|
||||||
|
@ -35,9 +35,9 @@ class GenerateWizard(models.TransientModel):
|
||||||
TODO: update module list and versions, then update all modules?"""
|
TODO: update module list and versions, then update all modules?"""
|
||||||
# Truncate the records table
|
# Truncate the records table
|
||||||
if openupgrade_tools.table_exists(
|
if openupgrade_tools.table_exists(
|
||||||
self.env.cr, "openupgrade_attribute"
|
self.env.cr, "upgrade_attribute"
|
||||||
) and openupgrade_tools.table_exists(self.env.cr, "openupgrade_record"):
|
) and openupgrade_tools.table_exists(self.env.cr, "upgrade_record"):
|
||||||
self.env.cr.execute("TRUNCATE openupgrade_attribute, openupgrade_record;")
|
self.env.cr.execute("TRUNCATE upgrade_attribute, upgrade_record;")
|
||||||
|
|
||||||
# Run any quirks
|
# Run any quirks
|
||||||
self.quirk_standard_calendar_attendances()
|
self.quirk_standard_calendar_attendances()
|
||||||
|
@ -67,7 +67,7 @@ class GenerateWizard(models.TransientModel):
|
||||||
|
|
||||||
# Set domain property
|
# Set domain property
|
||||||
self.env.cr.execute(
|
self.env.cr.execute(
|
||||||
""" UPDATE openupgrade_record our
|
""" UPDATE upgrade_record our
|
||||||
SET domain = iaw.domain
|
SET domain = iaw.domain
|
||||||
FROM ir_model_data imd
|
FROM ir_model_data imd
|
||||||
JOIN ir_act_window iaw ON imd.res_id = iaw.id
|
JOIN ir_act_window iaw ON imd.res_id = iaw.id
|
||||||
|
@ -79,13 +79,13 @@ class GenerateWizard(models.TransientModel):
|
||||||
)
|
)
|
||||||
self.env.cache.invalidate(
|
self.env.cache.invalidate(
|
||||||
[
|
[
|
||||||
(self.env["openupgrade.record"]._fields["domain"], None),
|
(self.env["upgrade.record"]._fields["domain"], None),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set noupdate property from ir_model_data
|
# Set noupdate property from ir_model_data
|
||||||
self.env.cr.execute(
|
self.env.cr.execute(
|
||||||
""" UPDATE openupgrade_record our
|
""" UPDATE upgrade_record our
|
||||||
SET noupdate = imd.noupdate
|
SET noupdate = imd.noupdate
|
||||||
FROM ir_model_data imd
|
FROM ir_model_data imd
|
||||||
WHERE our.type = 'xmlid'
|
WHERE our.type = 'xmlid'
|
||||||
|
@ -101,7 +101,7 @@ class GenerateWizard(models.TransientModel):
|
||||||
|
|
||||||
# Log model records
|
# Log model records
|
||||||
self.env.cr.execute(
|
self.env.cr.execute(
|
||||||
"""INSERT INTO openupgrade_record
|
"""INSERT INTO upgrade_record
|
||||||
(module, name, model, type)
|
(module, name, model, type)
|
||||||
SELECT imd2.module, imd2.module || '.' || imd.name AS name,
|
SELECT imd2.module, imd2.module || '.' || imd.name AS name,
|
||||||
im.model, 'model' AS type
|
im.model, 'model' AS type
|
|
@ -9,9 +9,9 @@ from odoo.osv.expression import AND
|
||||||
from ..blacklist import BLACKLIST_MODULES
|
from ..blacklist import BLACKLIST_MODULES
|
||||||
|
|
||||||
|
|
||||||
class InstallAll(models.TransientModel):
|
class UpgradeInstallWizard(models.TransientModel):
|
||||||
_name = "openupgrade.install.all.wizard"
|
_name = "upgrade.install.wizard"
|
||||||
_description = "OpenUpgrade Install All Wizard"
|
_description = "Upgrade Install Wizard"
|
||||||
|
|
||||||
state = fields.Selection(
|
state = fields.Selection(
|
||||||
[("init", "init"), ("ready", "ready")], readonly=True, default="init"
|
[("init", "init"), ("ready", "ready")], readonly=True, default="init"
|
||||||
|
@ -22,7 +22,7 @@ class InstallAll(models.TransientModel):
|
||||||
def default_get(self, fields):
|
def default_get(self, fields):
|
||||||
"""Update module list and retrieve the number
|
"""Update module list and retrieve the number
|
||||||
of installable modules"""
|
of installable modules"""
|
||||||
res = super(InstallAll, self).default_get(fields)
|
res = super().default_get(fields)
|
||||||
update, add = self.env["ir.module.module"].update_list()
|
update, add = self.env["ir.module.module"].update_list()
|
||||||
modules = self.env["ir.module.module"].search(
|
modules = self.env["ir.module.module"].search(
|
||||||
[("state", "not in", ["uninstallable", "unknown"])]
|
[("state", "not in", ["uninstallable", "unknown"])]
|
|
@ -1,13 +1,12 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record id="view_openupgrade_analysis_wizard_form" model="ir.ui.view">
|
<record id="view_upgrade_analysis_wizard_form" model="ir.ui.view">
|
||||||
<field name="name">view.openupgrade.analysis_wizard.form</field>
|
<field name="model">upgrade.analysis.wizard</field>
|
||||||
<field name="model">openupgrade.analysis.wizard</field>
|
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="OpenUpgrade Analysis Wizard">
|
<form>
|
||||||
<group>
|
<group>
|
||||||
<field name="server_config" readonly="1" />
|
<field name="server_config_id" readonly="1" />
|
||||||
<field name="state" />
|
<field name="state" />
|
||||||
<field
|
<field
|
||||||
name="log"
|
name="log"
|
|
@ -1,18 +1,17 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record id="view_openupgrade_generate_records_wizard_form" model="ir.ui.view">
|
<record id="view_upgrade_generate_record_wizard_form" model="ir.ui.view">
|
||||||
<field name="name">view.openupgrade.generate_records_wizard.form</field>
|
<field name="model">upgrade.generate.record.wizard</field>
|
||||||
<field name="model">openupgrade.generate.records.wizard</field>
|
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="OpenUpgrade Generate Records Wizard">
|
<form string="upgrade Generate Record Wizard">
|
||||||
<field name="state" invisible="1" />
|
<field name="state" invisible="1" />
|
||||||
<group states="init" colspan="4">
|
<group states="init" colspan="4">
|
||||||
<p
|
<p
|
||||||
>This will reinitialize all the modules installed on this database. Do not continue if you use this database in production.</p>
|
>This will reinitialize all the modules installed on this database. Do not continue if you use this database in production.</p>
|
||||||
</group>
|
</group>
|
||||||
<group states="ready" colspan="4">
|
<group states="ready" colspan="4">
|
||||||
<p>Modules initialized and records created</p>
|
<p>Modules initialized and record created</p>
|
||||||
</group>
|
</group>
|
||||||
<footer>
|
<footer>
|
||||||
<button
|
<button
|
||||||
|
@ -28,19 +27,19 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="action_generate_records" model="ir.actions.act_window">
|
<record id="action_upgrade_generate_record_wizard" model="ir.actions.act_window">
|
||||||
<field name="name">Generate Records</field>
|
<field name="name">Generate Records</field>
|
||||||
<field name="type">ir.actions.act_window</field>
|
<field name="type">ir.actions.act_window</field>
|
||||||
<field name="res_model">openupgrade.generate.records.wizard</field>
|
<field name="res_model">upgrade.generate.record.wizard</field>
|
||||||
<field name="view_mode">form,tree</field>
|
<field name="view_mode">form,tree</field>
|
||||||
<field name="target">new</field>
|
<field name="target">new</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
name="Generate Records"
|
name="Generate Records"
|
||||||
id="menu_openupgrade_generate_records"
|
id="menu_upgrade_generate_record"
|
||||||
parent="menu_openupgrade"
|
parent="menu_upgrade"
|
||||||
action="action_generate_records"
|
action="action_upgrade_generate_record_wizard"
|
||||||
sequence="15"
|
sequence="15"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record id="view_openupgrade_install_all_wizard_form" model="ir.ui.view">
|
<record id="view_upgrade_install_wizard_form" model="ir.ui.view">
|
||||||
<field name="name">view.openupgrade.install_all_wizard.form</field>
|
<field name="model">upgrade.install.wizard</field>
|
||||||
<field name="model">openupgrade.install.all.wizard</field>
|
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="OpenUpgrade Install All Modules Wizard">
|
<form>
|
||||||
<field name="state" invisible="1" />
|
<field name="state" invisible="1" />
|
||||||
<group states="init" colspan="4">
|
<group states="init" colspan="4">
|
||||||
<p
|
<p
|
||||||
|
@ -29,19 +28,19 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="action_install_all" model="ir.actions.act_window">
|
<record id="action_upgrade_install_wizard" model="ir.actions.act_window">
|
||||||
<field name="name">Install All Modules</field>
|
<field name="name">Install Modules</field>
|
||||||
<field name="type">ir.actions.act_window</field>
|
<field name="type">ir.actions.act_window</field>
|
||||||
<field name="res_model">openupgrade.install.all.wizard</field>
|
<field name="res_model">upgrade.install.wizard</field>
|
||||||
<field name="view_mode">form,tree</field>
|
<field name="view_mode">form,tree</field>
|
||||||
<field name="target">new</field>
|
<field name="target">new</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
name="Install All Modules"
|
name="Install Modules"
|
||||||
id="menu_openupgrade_install_all"
|
id="menu_upgrade_install"
|
||||||
parent="menu_openupgrade"
|
parent="menu_upgrade"
|
||||||
action="action_install_all"
|
action="action_upgrade_install_wizard"
|
||||||
sequence="14"
|
sequence="14"
|
||||||
/>
|
/>
|
||||||
|
|
Loading…
Reference in New Issue