Skip to content

Commit

Permalink
Merge PR #70 into master
Browse files Browse the repository at this point in the history
Signed-off-by jjscarafia
  • Loading branch information
OCA-git-bot committed Apr 25, 2023
2 parents 5ec5ce1 + 7346d0c commit d6e732d
Show file tree
Hide file tree
Showing 15 changed files with 260 additions and 18 deletions.
16 changes: 16 additions & 0 deletions DEVELOP.rst
Expand Up @@ -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
==========================

Expand Down
100 changes: 91 additions & 9 deletions odoo_module_migrate/base_migration_script.py
Expand Up @@ -20,6 +20,8 @@ class BaseMigrationScript(object):
_FILE_RENAMES = {}
_REMOVED_FIELDS = []
_RENAMED_FIELDS = []
_RENAMED_MODELS = []
_REMOVED_MODELS = []
_GLOBAL_FUNCTIONS = [] # [function_object]
_module_path = ''

Expand Down Expand Up @@ -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": [],
},
Expand Down Expand Up @@ -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,
Expand All @@ -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(
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion odoo_module_migrate/config.py
Expand Up @@ -52,6 +52,6 @@
},
]

_ALLOWED_EXTENSIONS = [".py", ".xml", ".js"]
_ALLOWED_EXTENSIONS = [".py", ".xml", ".js", ".csv"]

_MANIFEST_NAMES = ["__openerp__.py", "__manifest__.py"]
9 changes: 1 addition & 8 deletions odoo_module_migrate/migration_scripts/migrate_150_160.py
Expand Up @@ -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
@@ -0,0 +1 @@
- ["account.account.type", "Commit https://github.com/odoo/odoo/commit/26b2472f4977ccedbb0b5ed5f"]
@@ -0,0 +1 @@
- ["stock.production.lot", "stock.lot", None]
@@ -0,0 +1,3 @@
.py:
\.get_xml_id\(: ".get_external_id("
\.fields_get_keys\(\): "._fields"
16 changes: 16 additions & 0 deletions 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.",
)
22 changes: 22 additions & 0 deletions 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()
2 changes: 2 additions & 0 deletions 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
33 changes: 33 additions & 0 deletions tests/data_result/module_150_160/views/stock_report_views.xml
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="action_report_lot_label" model="ir.actions.report">
<field name="name">Lot/Serial Number (PDF)</field>
<field name="model">stock.production.lot</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">stock.report_lot_label</field>
<field name="report_file">stock.report_lot_label</field>
<field name="print_report_name">'Lot-Serial - %s' % object.name</field>
<field name="binding_model_id" ref="model_stock_lot"/>
<field name="binding_type">report</field>
</record>

<record id="action_report_lot_label" model="ir.actions.report">
<field name="name">Lot/Serial Number (PDF)</field>
<field name="model">stock.production.lot</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">stock.report_lot_label</field>
<field name="report_file">stock.report_lot_label</field>
<field name="print_report_name">'Lot-Serial - %s' % object.name</field>
<field name="binding_model_id" ref='model_stock_lot'/>
<field name="binding_type">report</field>
</record>

<record id="stock_lot" model="stock.lot">
<field name="name">0000000000003</field>
<field name="product_id" ref="mrp.product_product_computer_desk"/>
<field name="product_qty">1</field>
<field name="company_id" ref="base.main_company"/>
</record>
</data>
</odoo>
16 changes: 16 additions & 0 deletions 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.",
)
22 changes: 22 additions & 0 deletions 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()
2 changes: 2 additions & 0 deletions 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
33 changes: 33 additions & 0 deletions tests/data_template/module_150/views/stock_report_views.xml
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="action_report_lot_label" model="ir.actions.report">
<field name="name">Lot/Serial Number (PDF)</field>
<field name="model">stock.production.lot</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">stock.report_lot_label</field>
<field name="report_file">stock.report_lot_label</field>
<field name="print_report_name">'Lot-Serial - %s' % object.name</field>
<field name="binding_model_id" ref="model_stock_production_lot"/>
<field name="binding_type">report</field>
</record>

<record id="action_report_lot_label" model="ir.actions.report">
<field name="name">Lot/Serial Number (PDF)</field>
<field name="model">stock.production.lot</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">stock.report_lot_label</field>
<field name="report_file">stock.report_lot_label</field>
<field name="print_report_name">'Lot-Serial - %s' % object.name</field>
<field name="binding_model_id" ref='model_stock_production_lot'/>
<field name="binding_type">report</field>
</record>

<record id="stock_production_lot" model="stock.production.lot">
<field name="name">0000000000003</field>
<field name="product_id" ref="mrp.product_product_computer_desk"/>
<field name="product_qty">1</field>
<field name="company_id" ref="base.main_company"/>
</record>
</data>
</odoo>

0 comments on commit d6e732d

Please sign in to comment.