diff --git a/DEVELOP.rst b/DEVELOP.rst
index 01fa29f..f4d104c 100644
--- a/DEVELOP.rst
+++ b/DEVELOP.rst
@@ -162,6 +162,22 @@ The list of the operations are written in the subfolder
.. code-block:: yaml
- ['account.account', 'user_type_id', 'account_type', 'Commit https://github.com/odoo/odoo/commit/26b2472f4977ccedbb0b5ed5f']
+* ``removed_models/migrate_FROM_TO/NAME.yaml`` — removed models rule. Display errors / warnings if files contains a given partern:
+ * errors: "old_model_name", 'old_model_name', old_table_name["',]
+ * warnings: old.model.name, old_model_name
+
+ For example, for migration from version 15.0 to 16.0:
+ .. code-block:: yaml
+ - ["account.account.type", "Commit https://github.com/odoo/odoo/commit/26b2472f4977ccedbb0b5ed5f"]
+
+* ``renamed_models/migrate_FROM_TO/NAME.yaml`` — renamed models rule. Display errors / warnings if files contains a given partern:
+ * errors: "old_model_name", 'old_model_name', old_table_name["',]
+ * warnings: old.model.name, old_model_name
+
+ For example, for migration from version 15.0 to 16.0:
+ .. code-block:: yaml
+ - ["stock.production.lot", "stock.lot", None]
+
How to improve the library
==========================
diff --git a/odoo_module_migrate/base_migration_script.py b/odoo_module_migrate/base_migration_script.py
index 787cbbd..ad71e4e 100644
--- a/odoo_module_migrate/base_migration_script.py
+++ b/odoo_module_migrate/base_migration_script.py
@@ -20,6 +20,8 @@ class BaseMigrationScript(object):
_FILE_RENAMES = {}
_REMOVED_FIELDS = []
_RENAMED_FIELDS = []
+ _RENAMED_MODELS = []
+ _REMOVED_MODELS = []
_GLOBAL_FUNCTIONS = [] # [function_object]
_module_path = ''
@@ -57,13 +59,13 @@ def parse_rules(self):
"type": TYPE_DICT,
"doc": {},
},
- # [(model_name, field_name, more_info), ...)]
- "_REMOVED_FIELDS": {
+ # [(old.model.name, new.model.name, more_info)]
+ "_RENAMED_MODELS": {
"type": TYPE_ARRAY,
"doc": [],
},
- # [(model_name, old_field_name, new_field_name, more_info), ...)]
- "_RENAMED_FIELDS": {
+ # [(old.model.name, more_info)]
+ "_REMOVED_MODELS": {
"type": TYPE_ARRAY,
"doc": [],
},
@@ -188,12 +190,12 @@ def process_file(self,
)
absolute_file_path = os.path.join(root, new_name)
- removed_fields = self.handle_removed_fields(self._REMOVED_FIELDS)
- renamed_fields = self.handle_renamed_fields(self._RENAMED_FIELDS)
-
+ renamed_models = self.handle_renamed_models(self._RENAMED_MODELS)
# Operate changes in the file (replacements, removals)
replaces = self._TEXT_REPLACES.get("*", {})
replaces.update(self._TEXT_REPLACES.get(extension, {}))
+ replaces.update(renamed_models.get('replaces'))
+ replaces.update(removed_models.get('replaces'))
new_text = tools._replace_in_file(
absolute_file_path, replaces,
@@ -203,14 +205,15 @@ def process_file(self,
# pattern
errors = self._TEXT_ERRORS.get("*", {})
errors.update(self._TEXT_ERRORS.get(extension, {}))
+ errors.update(renamed_models.get('errors'))
+ errors.update(removed_models.get('errors'))
for pattern, error_message in errors.items():
if re.findall(pattern, new_text):
logger.error(error_message)
warnings = self._TEXT_WARNINGS.get("*", {})
warnings.update(self._TEXT_WARNINGS.get(extension, {}))
- warnings.update(removed_fields.get('warnings'))
- warnings.update(renamed_fields.get('warnings'))
+ warnings.update(renamed_models.get('warnings'))
for pattern, warning_message in warnings.items():
if re.findall(pattern, new_text):
logger.warning(
@@ -309,6 +312,85 @@ def handle_deprecated_modules(self, manifest_path, deprecated_modules):
if current_manifest_text != new_manifest_text:
tools._write_content(manifest_path, new_manifest_text)
+ def handle_renamed_models(self, renamed_models):
+ ''' renamed_models = [(old.model, new.model, msg)]
+ returns dictionary of all replaces / warnings / errors produced
+ by a model renamed
+ {
+ 'replaces':
+ {
+ "old_model_name", 'old_model_name': new_model_name
+ old_table_name["',]: new_table_name["',]
+ },
+ 'warnings':
+ {
+ old.model.name: warning msg
+ old_model_name: warning msg
+ }
+ }
+ '''
+ res = {'replaces': {}, 'warnings': {}, 'errors': {}}
+ for old_model_name, new_model_name, more_info in renamed_models:
+ old_table_name = old_model_name.replace('.', '_')
+ new_table_name = new_model_name.replace('.', '_')
+ old_name_esc = re.escape(old_model_name)
+ res['replaces'].update({
+ r"\"%s\"" % old_name_esc: '"%s"' % new_model_name,
+ r"\'%s\'" % old_name_esc: "'%s'" % new_model_name,
+ r"\"%s\"" % old_table_name: "\"%s\"" % new_table_name,
+ r"\'%s\'" % old_table_name: "'%s'" % new_table_name,
+ r"model_%s\"" % old_table_name: "model_%s\"" % new_table_name,
+ r"model_%s\'" % old_table_name: "model_%s'" % new_table_name,
+ r"model_%s," % old_table_name: "model_%s," % new_table_name,
+ })
+ msg = "The model %s has been renamed to %s.%s" % (
+ old_model_name, new_model_name, (" %s" % more_info) or "")
+ res['warnings'].update({
+ old_name_esc: msg,
+ old_table_name: msg,
+ })
+ return res
+
+ def handle_removed_models(self, removed_models):
+ ''' removed_models = [(old.model, msg)]
+ returns dictionary of all replaces / warnings / errors produced
+ by a model renamed
+ {
+ 'error':
+ {
+ "old_model_name", 'old_model_name': new_model_name
+ old_table_name["',]: new_table_name["',]
+ },
+ 'warnings':
+ {
+ old.model.name: warning msg
+ old_model_name: warning msg
+ }
+ }
+ '''
+ res = {'replaces': {}, 'warnings': {}, 'errors': {}}
+ for model_name, more_info in removed_models:
+ table_name = model_name.replace('.', '_')
+ model_name_esc = re.escape(model_name)
+
+ msg = "The model %s has been .%s" % (
+ model_name, (" %s" % more_info) or "")
+
+ res['errors'].update({
+ r"\"%s\"" % model_name_esc: msg,
+ r"\'%s\'" % model_name_esc: msg,
+ r"\"%s\"" % table_name: msg,
+ r"\'%s\'" % table_name: msg,
+ r"model_%s\"" % table_name: msg,
+ r"model_%s\'" % table_name: msg,
+ r"model_%s," % table_name: msg,
+ })
+ res['warnings'].update({
+ model_name_esc: msg,
+ table_name: msg,
+ })
+ return res
+
def _get_correct_manifest_path(self, manifest_path, file_renames):
current_manifest_file_name = manifest_path.as_posix().split('/')[-1]
if current_manifest_file_name in file_renames:
diff --git a/odoo_module_migrate/config.py b/odoo_module_migrate/config.py
index 6f04e64..061c82f 100644
--- a/odoo_module_migrate/config.py
+++ b/odoo_module_migrate/config.py
@@ -52,6 +52,6 @@
},
]
-_ALLOWED_EXTENSIONS = [".py", ".xml", ".js"]
+_ALLOWED_EXTENSIONS = [".py", ".xml", ".js", ".csv"]
_MANIFEST_NAMES = ["__openerp__.py", "__manifest__.py"]
diff --git a/odoo_module_migrate/migration_scripts/migrate_150_160.py b/odoo_module_migrate/migration_scripts/migrate_150_160.py
index c416779..25a41e0 100644
--- a/odoo_module_migrate/migration_scripts/migrate_150_160.py
+++ b/odoo_module_migrate/migration_scripts/migrate_150_160.py
@@ -2,13 +2,6 @@
from odoo_module_migrate.base_migration_script import BaseMigrationScript
-_TEXT_REPLACES = {
- ".py": {
- r"\.get_xml_id\(": ".get_external_id(",
- r"\.fields_get_keys\(\)": "._fields",
- },
-}
-
class MigrationScript(BaseMigrationScript):
- _TEXT_REPLACES = _TEXT_REPLACES
+ pass
diff --git a/odoo_module_migrate/migration_scripts/removed_models/migrate_150_160/removed_models.yaml b/odoo_module_migrate/migration_scripts/removed_models/migrate_150_160/removed_models.yaml
new file mode 100644
index 0000000..9161d71
--- /dev/null
+++ b/odoo_module_migrate/migration_scripts/removed_models/migrate_150_160/removed_models.yaml
@@ -0,0 +1 @@
+- ["account.account.type", "Commit https://github.com/odoo/odoo/commit/26b2472f4977ccedbb0b5ed5f"]
diff --git a/odoo_module_migrate/migration_scripts/renamed_models/migrate_150_160/renamed_models.yaml b/odoo_module_migrate/migration_scripts/renamed_models/migrate_150_160/renamed_models.yaml
new file mode 100644
index 0000000..eba0e19
--- /dev/null
+++ b/odoo_module_migrate/migration_scripts/renamed_models/migrate_150_160/renamed_models.yaml
@@ -0,0 +1 @@
+- ["stock.production.lot", "stock.lot", None]
diff --git a/odoo_module_migrate/migration_scripts/text_replaces/migrate_150_160/orm_methods.yaml b/odoo_module_migrate/migration_scripts/text_replaces/migrate_150_160/orm_methods.yaml
new file mode 100644
index 0000000..1911e48
--- /dev/null
+++ b/odoo_module_migrate/migration_scripts/text_replaces/migrate_150_160/orm_methods.yaml
@@ -0,0 +1,3 @@
+.py:
+ \.get_xml_id\(: ".get_external_id("
+ \.fields_get_keys\(\): "._fields"
diff --git a/tests/data_result/module_150_160/models/account_account_type.py b/tests/data_result/module_150_160/models/account_account_type.py
new file mode 100644
index 0000000..3d8ec51
--- /dev/null
+++ b/tests/data_result/module_150_160/models/account_account_type.py
@@ -0,0 +1,16 @@
+from odoo import fields, models
+
+
+class AccountAccountType(models.Model):
+ _inherit = "account.account.type"
+
+ analytic_account_required = fields.Boolean(
+ string='Analytic Account Required?',
+ help="If True, then an analytic account will be required when posting "
+ "journal entries with this type of account.",
+ )
+ analytic_tag_required = fields.Boolean(
+ string='Analytic Tag Required?',
+ help="If True, then analytic tags will be required when posting "
+ "journal entries with this type of account.",
+ )
diff --git a/tests/data_result/module_150_160/models/stock_production_lot.py b/tests/data_result/module_150_160/models/stock_production_lot.py
new file mode 100644
index 0000000..f4f54cb
--- /dev/null
+++ b/tests/data_result/module_150_160/models/stock_production_lot.py
@@ -0,0 +1,22 @@
+from odoo import models, _
+from odoo.exceptions import UserError
+
+
+class StockProductionLot(models.Model):
+ _inherit = 'stock.lot'
+ _barcode_field = 'name'
+
+ def _get_stock_barcode_specific_data(self):
+ products = self.product_id
+ return {
+ 'product.product': products.read(self.env['product.product']._get_fields_stock_barcode(), load=False),
+ 'uom.uom': products.uom_id.read(self.env['uom.uom']._get_fields_stock_barcode(), load=False)
+ }
+
+ def _check_create(self):
+ active_mo_id = self.env.context.get('active_mo_id')
+ if active_mo_id:
+ active_mo = self.env['mrp.production'].browse(active_mo_id)
+ if not active_mo.picking_type_id.use_create_components_lots:
+ raise UserError(_('You are not allowed to create or edit a lot or serial number for the components with the operation type "Manufacturing". To change this, go on the operation type and tick the box "Create New Lots/Serial Numbers for Components".'))
+ return super()._check_create()
diff --git a/tests/data_result/module_150_160/security/ir.model.access.csv b/tests/data_result/module_150_160/security/ir.model.access.csv
new file mode 100644
index 0000000..4022a97
--- /dev/null
+++ b/tests/data_result/module_150_160/security/ir.model.access.csv
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_stock_production_user,stock.production.lot,stock.model_stock_lot,quality.group_quality_user,1,0,0,0
diff --git a/tests/data_result/module_150_160/views/stock_report_views.xml b/tests/data_result/module_150_160/views/stock_report_views.xml
new file mode 100644
index 0000000..5162c7a
--- /dev/null
+++ b/tests/data_result/module_150_160/views/stock_report_views.xml
@@ -0,0 +1,33 @@
+
+
+
+
+ Lot/Serial Number (PDF)
+ stock.production.lot
+ qweb-pdf
+ stock.report_lot_label
+ stock.report_lot_label
+ 'Lot-Serial - %s' % object.name
+
+ report
+
+
+
+ Lot/Serial Number (PDF)
+ stock.production.lot
+ qweb-pdf
+ stock.report_lot_label
+ stock.report_lot_label
+ 'Lot-Serial - %s' % object.name
+
+ report
+
+
+
+ 0000000000003
+
+ 1
+
+
+
+
diff --git a/tests/data_template/module_150/models/account_account_type.py b/tests/data_template/module_150/models/account_account_type.py
new file mode 100644
index 0000000..3d8ec51
--- /dev/null
+++ b/tests/data_template/module_150/models/account_account_type.py
@@ -0,0 +1,16 @@
+from odoo import fields, models
+
+
+class AccountAccountType(models.Model):
+ _inherit = "account.account.type"
+
+ analytic_account_required = fields.Boolean(
+ string='Analytic Account Required?',
+ help="If True, then an analytic account will be required when posting "
+ "journal entries with this type of account.",
+ )
+ analytic_tag_required = fields.Boolean(
+ string='Analytic Tag Required?',
+ help="If True, then analytic tags will be required when posting "
+ "journal entries with this type of account.",
+ )
diff --git a/tests/data_template/module_150/models/stock_production_lot.py b/tests/data_template/module_150/models/stock_production_lot.py
new file mode 100644
index 0000000..15253ed
--- /dev/null
+++ b/tests/data_template/module_150/models/stock_production_lot.py
@@ -0,0 +1,22 @@
+from odoo import models, _
+from odoo.exceptions import UserError
+
+
+class StockProductionLot(models.Model):
+ _inherit = 'stock.production.lot'
+ _barcode_field = 'name'
+
+ def _get_stock_barcode_specific_data(self):
+ products = self.product_id
+ return {
+ 'product.product': products.read(self.env['product.product']._get_fields_stock_barcode(), load=False),
+ 'uom.uom': products.uom_id.read(self.env['uom.uom']._get_fields_stock_barcode(), load=False)
+ }
+
+ def _check_create(self):
+ active_mo_id = self.env.context.get('active_mo_id')
+ if active_mo_id:
+ active_mo = self.env['mrp.production'].browse(active_mo_id)
+ if not active_mo.picking_type_id.use_create_components_lots:
+ raise UserError(_('You are not allowed to create or edit a lot or serial number for the components with the operation type "Manufacturing". To change this, go on the operation type and tick the box "Create New Lots/Serial Numbers for Components".'))
+ return super()._check_create()
diff --git a/tests/data_template/module_150/security/ir.model.access.csv b/tests/data_template/module_150/security/ir.model.access.csv
new file mode 100644
index 0000000..9f8360d
--- /dev/null
+++ b/tests/data_template/module_150/security/ir.model.access.csv
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_stock_production_user,stock.production.lot,stock.model_stock_production_lot,quality.group_quality_user,1,0,0,0
diff --git a/tests/data_template/module_150/views/stock_report_views.xml b/tests/data_template/module_150/views/stock_report_views.xml
new file mode 100644
index 0000000..01c05f9
--- /dev/null
+++ b/tests/data_template/module_150/views/stock_report_views.xml
@@ -0,0 +1,33 @@
+
+
+
+
+ Lot/Serial Number (PDF)
+ stock.production.lot
+ qweb-pdf
+ stock.report_lot_label
+ stock.report_lot_label
+ 'Lot-Serial - %s' % object.name
+
+ report
+
+
+
+ Lot/Serial Number (PDF)
+ stock.production.lot
+ qweb-pdf
+ stock.report_lot_label
+ stock.report_lot_label
+ 'Lot-Serial - %s' % object.name
+
+ report
+
+
+
+ 0000000000003
+
+ 1
+
+
+
+