From a4e5396dcd84e3342f043eeadf480f27e21e1592 Mon Sep 17 00:00:00 2001 From: GuillemCForgeFlow Date: Thu, 28 Sep 2023 15:50:21 +0200 Subject: [PATCH] [FIX]hs_code_link: properly declare OCA hs_code field on product.template Before the change, the field was not being updated after the value of the H.S. Code was changed on a Product Template. The related stored field was not working fine with the company dependent field. As the `hs_code_id` field is company dependent, the related `hs_code` value should also be like this and sync the value based on the previous one. --- hs_code_link/__manifest__.py | 3 +- .../migrations/13.0.2.0.0/post-migration.py | 72 +++++++++++++++++++ hs_code_link/models/__init__.py | 2 + hs_code_link/models/hs_code.py | 12 ++++ hs_code_link/models/ir_property.py | 51 +++++++++++++ hs_code_link/models/product.py | 5 +- hs_code_link/readme/CONTRIBUTORS.rst | 1 + 7 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 hs_code_link/migrations/13.0.2.0.0/post-migration.py create mode 100644 hs_code_link/models/hs_code.py create mode 100644 hs_code_link/models/ir_property.py diff --git a/hs_code_link/__manifest__.py b/hs_code_link/__manifest__.py index 6824b08e3..c1c0afa90 100644 --- a/hs_code_link/__manifest__.py +++ b/hs_code_link/__manifest__.py @@ -1,8 +1,9 @@ # Copyright 2017 Camptocamp SA +# Copyright 2023 ForgeFlow # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { "name": "HS Code Link", - "version": "13.0.1.0.1", + "version": "13.0.2.0.0", "depends": ["product_harmonized_system", "delivery"], "author": "Camptocamp SA, Odoo Community Association (OCA)", "website": "https://github.com/OCA/intrastat-extrastat", diff --git a/hs_code_link/migrations/13.0.2.0.0/post-migration.py b/hs_code_link/migrations/13.0.2.0.0/post-migration.py new file mode 100644 index 000000000..1b0cccb4b --- /dev/null +++ b/hs_code_link/migrations/13.0.2.0.0/post-migration.py @@ -0,0 +1,72 @@ +# Copyright 2023 ForgeFlow +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +import logging + +from openupgradelib import openupgrade + +from odoo import SUPERUSER_ID + +_logger = logging.getLogger(__name__) + + +def _fill_columns(env): + field_name = "hs_code" + _logger.info("Filling %s Company Property" % field_name) + template_model = env["ir.model"].search( + [("model", "=", "product.template")], limit=1 + ) + field = env["ir.model.fields"].search( + [("name", "=", field_name), ("model_id", "=", template_model.id)], limit=1 + ) + if not field: + _logger.info("Field %s not found." % (field_name)) + return False + insert_query = """ + WITH query AS ( + SELECT + ip.company_id AS company_id, + pt.id AS product_tmpl_id, + SUBSTRING(hc.local_code, 0, 7) AS value_text + FROM ir_property ip + JOIN product_template pt ON + CAST(SUBSTRING(ip.res_id, 18, 30) AS INTEGER) = pt.id + JOIN hs_code hc ON + CAST(SUBSTRING(ip.value_reference, 9, 20) AS INTEGER) = hc.id + WHERE + ip.name = 'hs_code_id' + AND ip.res_id ILIKE 'product.template,%' + ) + INSERT INTO ir_property ( + name, + res_id, + company_id, + fields_id, + value_text, + type, + create_date, + write_date, + create_uid, + write_uid + ) + SELECT + '{}', + 'product.template,' || CAST(product_tmpl_id AS VARCHAR), + company_id, + {}, + value_text, + 'char', + now(), + now(), + {}, + {} + FROM query + ON CONFLICT DO NOTHING; + """.format( + field_name, field.id, SUPERUSER_ID, SUPERUSER_ID + ) + env.cr.execute(insert_query) + + +@openupgrade.migrate() +def migrate(env, version): + _fill_columns(env) diff --git a/hs_code_link/models/__init__.py b/hs_code_link/models/__init__.py index 9649db77a..301ce2d34 100644 --- a/hs_code_link/models/__init__.py +++ b/hs_code_link/models/__init__.py @@ -1 +1,3 @@ from . import product +from . import ir_property +from . import hs_code diff --git a/hs_code_link/models/hs_code.py b/hs_code_link/models/hs_code.py new file mode 100644 index 000000000..4294506a4 --- /dev/null +++ b/hs_code_link/models/hs_code.py @@ -0,0 +1,12 @@ +# Copyright 2023 ForgeFlow +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import api, models + + +class HSCode(models.Model): + _inherit = "hs.code" + + @api.model + def _get_fields_to_sync_from_hs_code_id(self): + return ["hs_code"] diff --git a/hs_code_link/models/ir_property.py b/hs_code_link/models/ir_property.py new file mode 100644 index 000000000..5ece52867 --- /dev/null +++ b/hs_code_link/models/ir_property.py @@ -0,0 +1,51 @@ +# Copyright 2023 ForgeFlow +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import api, models + + +class IrProperty(models.Model): + _inherit = "ir.property" + + @api.model + def set_multi(self, name, model, values, default_value=None): + """ + When the H.S. Code instance is updated on the Product Template, we also update + the H.S. Code (6 digits code) value + """ + result = super().set_multi(name, model, values, default_value=default_value) + if name == "hs_code_id" and model == "product.template": + HSCode = self.env["hs.code"] + fields_to_sync = HSCode._get_fields_to_sync_from_hs_code_id() + values_to_sync = dict() + for field_name in fields_to_sync: + for rec_id, rec_val in values.items(): + val = False + if isinstance(rec_val, int): + val = ( + HSCode.browse(rec_val).exists() + and HSCode.browse(rec_val)[field_name] + ) + elif ( + isinstance(rec_val, models.BaseModel) + and rec_val._name == "hs.code" + ): + val = rec_val[field_name] + values_to_sync.update({rec_id: val}) + self.set_multi("hs_code", model, values_to_sync) + return result + + def unlink(self): + to_delete_ids = self.ids + for p_id in self.ids: + p = self.browse(p_id) + if p.exists() and p.name == "hs_code_id" and "product.template" in p.res_id: + HSCode = self.env["hs.code"] + fields_to_sync = HSCode._get_fields_to_sync_from_hs_code_id() + for field_name in fields_to_sync: + r_p = self.search( + [("res_id", "=", p.res_id), ("name", "=", field_name)], limit=1 + ) + to_delete_ids.append(r_p.id) + self = self.browse(to_delete_ids) + return super(IrProperty, self).unlink() diff --git a/hs_code_link/models/product.py b/hs_code_link/models/product.py index d00049580..513b76706 100644 --- a/hs_code_link/models/product.py +++ b/hs_code_link/models/product.py @@ -1,4 +1,5 @@ # Copyright 2017 Camptocamp SA +# Copyright 2023 ForgeFlow # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import fields, models @@ -7,4 +8,6 @@ class ProductTemplate(models.Model): _inherit = "product.template" - hs_code = fields.Char(related="hs_code_id.hs_code", readonly=True, store=True) + # Company Dependent field, as we want to have as a related field to the + # hs_code_id.hs_code value + hs_code = fields.Char(company_dependent=True) diff --git a/hs_code_link/readme/CONTRIBUTORS.rst b/hs_code_link/readme/CONTRIBUTORS.rst index fcb7aaa08..316ea709a 100644 --- a/hs_code_link/readme/CONTRIBUTORS.rst +++ b/hs_code_link/readme/CONTRIBUTORS.rst @@ -1 +1,2 @@ * Denis Leemann +* Guillem Casassas