diff --git a/product_harmonized_system_per_country/README.rst b/product_harmonized_system_per_country/README.rst index 5441b2c4..066dd400 100644 --- a/product_harmonized_system_per_country/README.rst +++ b/product_harmonized_system_per_country/README.rst @@ -44,9 +44,9 @@ This module is NOT compatible with the *account_intrastat* module from Odoo Ente Usage ===== -This module only depends on the *intrastat_product* module, whiwh depends on *product_harmonized_systems* module. +This module depends on the *delivery* module and the *intrastat_product* module, which depends on the *product_harmonized_systems* module. -This module adds the applicable country field to HS Codes, and provides a list of HS Codes by product and/or category, in order to dynamically find the code corresponding to the destination country. +This module adds the 'applicable country' field to the HS Code model, and enables HS Codes to be linked together as parent/child, so that the code corresponding to the destination country can be dynamically found from a single HS Code. Bug Tracker =========== diff --git a/product_harmonized_system_per_country/__manifest__.py b/product_harmonized_system_per_country/__manifest__.py index 4dd8e7ae..57fee0c9 100644 --- a/product_harmonized_system_per_country/__manifest__.py +++ b/product_harmonized_system_per_country/__manifest__.py @@ -10,11 +10,10 @@ "author": "Emilie SOUTIRAS, Groupe Voltaire, Odoo Community Association (OCA)", "maintainers": ["emiliesoutiras"], "website": "https://github.com/OCA/intrastat-extrastat", - "depends": ["intrastat_product"], + "depends": ["delivery", "intrastat_product"], "data": [ - "views/product_category.xml", - "views/product_template.xml", "views/hs_code.xml", + "report/deliveryslip_report.xml", ], "installable": True, } diff --git a/product_harmonized_system_per_country/models/hs_code.py b/product_harmonized_system_per_country/models/hs_code.py index b22c422d..2ce978ee 100644 --- a/product_harmonized_system_per_country/models/hs_code.py +++ b/product_harmonized_system_per_country/models/hs_code.py @@ -1,8 +1,7 @@ # Copyright (c) 2024 Groupe Voltaire # @author Emilie SOUTIRAS # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). - -from odoo import api, fields, models +from odoo import fields, models class HSCode(models.Model): @@ -11,36 +10,29 @@ class HSCode(models.Model): country_id = fields.Many2one( comodel_name="res.country", string="Applicable country" ) - pdt_categ_ids = fields.Many2many( - comodel_name="product.category", - relation="hs_code_pdt_category_rel", - column1="pdt_categ_id", - column2="hs_code_id", - string="Product Categories on H.S. Codes list", - readonly=True, + parent_id = fields.Many2one( + comodel_name="hs.code", + string="Parent H.S. Code", + ondelete="set null", ) - pdt_tmpl_ids = fields.Many2many( - comodel_name="product.template", - relation="hs_code_pdt_tmpl_rel", - column1="pdt_tmpl_id", - column2="hs_code_id", - string="Products on H.S. Codes list", - readonly=True, + child_ids = fields.One2many( + comodel_name="hs.code", + inverse_name="parent_id", + string="Child H.S. Codes related for other countries", + copy=False, + ) + related_hs_code_ids = fields.Many2many( + comodel_name="hs.code", + compute="_compute_related_hs_code", + string="All related H.S. Codes", ) - @api.depends("product_categ_ids", "pdt_categ_ids") - def _compute_product_categ_count(self): - for code in self: - code.product_categ_count = len( - set(code.product_categ_ids.ids).union(set(code.pdt_categ_ids.ids)) - ) - - @api.depends("product_tmpl_ids", "pdt_tmpl_ids") - def _compute_product_tmpl_count(self): + def _compute_related_hs_code(self): for code in self: - code.product_tmpl_count = len( - set(code.product_tmpl_ids.ids).union(set(code.pdt_tmpl_ids.ids)) - ) + res = code | code.parent_id | code.child_ids + if code.parent_id: + res |= code.parent_id.child_ids + code.related_hs_code_ids = res def filter_per_country(self): country_id = self.env.context.get("hs_code_for_country", False) @@ -48,7 +40,8 @@ def filter_per_country(self): company_ids = [active_companies[0]] if active_companies else [] company_ids += [False] if country_id: - res = self.filtered( + self._compute_related_hs_code() + res = self.related_hs_code_ids.filtered( lambda hs: (not hs.country_id or hs.country_id.id == country_id) and (hs.company_id.id in company_ids) ) @@ -58,7 +51,9 @@ def filter_per_country(self): .sorted(key="country_id", reverse=True) ) else: - res = self.filtered(lambda hs: (hs.company_id.id in company_ids)) + res = self.related_hs_code_ids.filtered( + lambda hs: (hs.company_id.id in company_ids) + ) res = res.sorted(key="company_id", reverse=True) if res: res = res[0] diff --git a/product_harmonized_system_per_country/models/product_category.py b/product_harmonized_system_per_country/models/product_category.py index 81870c8d..5ca54039 100644 --- a/product_harmonized_system_per_country/models/product_category.py +++ b/product_harmonized_system_per_country/models/product_category.py @@ -3,7 +3,7 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). import logging -from odoo import fields, models +from odoo import models _logger = logging.getLogger(__name__) @@ -11,21 +11,10 @@ class ProductCategory(models.Model): _inherit = "product.category" - hs_code_ids = fields.Many2many( - comodel_name="hs.code", - relation="hs_code_pdt_category_rel", - column1="hs_code_id", - column2="pdt_categ_id", - string="H.S. Codes", - help="Harmonised System Codes. This list is used to filter by " - "destination country. If no code is set, the simple H.S. Code " - "is used.", - ) - def get_hs_code_recursively(self): self.ensure_one() - if self.hs_code_ids: - res = self.hs_code_ids.filter_per_country() + if self.hs_code_id: + res = self.hs_code_id.filter_per_country() else: res = super().get_hs_code_recursively() return res diff --git a/product_harmonized_system_per_country/models/product_product.py b/product_harmonized_system_per_country/models/product_product.py index 48a4d0bb..e8390c04 100644 --- a/product_harmonized_system_per_country/models/product_product.py +++ b/product_harmonized_system_per_country/models/product_product.py @@ -2,22 +2,27 @@ # @author Emilie SOUTIRAS # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import fields, models +from odoo import api, fields, models class ProductTemplate(models.Model): _inherit = "product.template" - hs_code_ids = fields.Many2many( - comodel_name="hs.code", - relation="hs_code_pdt_tmpl_rel", - column1="hs_code_id", - column2="pdt_tmpl_id", - string="H.S. Codes", - help="Harmonised System Codes. This list is used to filter by " - "destination country. If no code is set, the simple H.S. Code " - "is used, otherwise those of the related product category.", + hs_code = fields.Char(compute="_compute_hs_code", store=False) + + @api.depends( + "hs_code_id", "hs_code_id.parent_id", "hs_code_id.child_ids", "categ_id" ) + def _compute_hs_code(self): + for pdt_tmpl in self: + if pdt_tmpl.hs_code_id: + pdt_tmpl.hs_code = ( + pdt_tmpl.hs_code_id.filter_per_country().hs_code or "" + ) + else: + pdt_tmpl.hs_code = ( + pdt_tmpl.categ_id.get_hs_code_recursively().hs_code or "" + ) class ProductProduct(models.Model): @@ -27,8 +32,8 @@ def get_hs_code_recursively(self): res = self.env["hs.code"] if self: self.ensure_one() - if self.hs_code_ids: - res = self.hs_code_ids.filter_per_country() + if self.hs_code_id: + res = self.hs_code_id.filter_per_country() else: res = super().get_hs_code_recursively() return res diff --git a/product_harmonized_system_per_country/readme/USAGE.rst b/product_harmonized_system_per_country/readme/USAGE.rst index f8aa8124..9dbd117c 100644 --- a/product_harmonized_system_per_country/readme/USAGE.rst +++ b/product_harmonized_system_per_country/readme/USAGE.rst @@ -1,3 +1,3 @@ -This module only depends on the *intrastat_product* module, whiwh depends on *product_harmonized_systems* module. +This module depends on the *delivery* module and the *intrastat_product* module, which depends on the *product_harmonized_systems* module. -This module adds the applicable country field to HS Codes, and provides a list of HS Codes by product and/or category, in order to dynamically find the code corresponding to the destination country. +This module adds the 'applicable country' field to the HS Code model, and enables HS Codes to be linked together as parent/child, so that the code corresponding to the destination country can be dynamically found from a single HS Code. \ No newline at end of file diff --git a/product_harmonized_system_per_country/report/deliveryslip_report.xml b/product_harmonized_system_per_country/report/deliveryslip_report.xml new file mode 100644 index 00000000..3c45f12e --- /dev/null +++ b/product_harmonized_system_per_country/report/deliveryslip_report.xml @@ -0,0 +1,26 @@ + + + + + + stock.picking.report.delivery.inherit + + + + + + o.move_ids.filtered(lambda l: l.product_id.hs_code) + + + + + + + diff --git a/product_harmonized_system_per_country/static/description/index.html b/product_harmonized_system_per_country/static/description/index.html index 3f13be2a..24623d89 100644 --- a/product_harmonized_system_per_country/static/description/index.html +++ b/product_harmonized_system_per_country/static/description/index.html @@ -391,8 +391,8 @@

Installation

Usage

-

This module only depends on the intrastat_product module, whiwh depends on product_harmonized_systems module.

-

This module adds the applicable country field to HS Codes, and provides a list of HS Codes by product and/or category, in order to dynamically find the code corresponding to the destination country.

+

This module depends on the delivery module and the intrastat_product module, which depends on the product_harmonized_systems module.

+

This module adds the ‘applicable country’ field to the HS Code model, and enables HS Codes to be linked together as parent/child, so that the code corresponding to the destination country can be dynamically found from a single HS Code.

Bug Tracker

diff --git a/product_harmonized_system_per_country/tests/test_hs_code.py b/product_harmonized_system_per_country/tests/test_hs_code.py index 6cf107f5..1332cae3 100644 --- a/product_harmonized_system_per_country/tests/test_hs_code.py +++ b/product_harmonized_system_per_country/tests/test_hs_code.py @@ -14,17 +14,14 @@ def setUpClass(cls): def test_hs_code_ids_product(self): hs_code_7050 = self.env.ref("product_harmonized_system.84717050") - self.categ_robots.hs_code_ids = [(4, hs_code_7050.id)] + self.categ_robots.hs_code_id = hs_code_7050.id self.assertEqual( self.pdt_c3po.get_hs_code_recursively(), self.hs_code_computer, ) country_fr = self.env.ref("base.fr") hs_code_7050.country_id = country_fr - self.pdt_c3po.hs_code_ids = [ - (4, self.hs_code_computer.id, 0), - (4, hs_code_7050.id, 0), - ] + hs_code_7050.parent_id = self.hs_code_computer self.assertEqual( self.pdt_c3po.get_hs_code_recursively(), self.hs_code_computer, @@ -39,15 +36,13 @@ def test_hs_code_ids_product(self): def test_hs_code_ids_category(self): self.pdt_c3po.hs_code_id = False country_fr = self.env.ref("base.fr") + self.categ_robots.hs_code_id = self.hs_code_computer hs_code_7050 = self.env.ref("product_harmonized_system.84717050") hs_code_7050.country_id = country_fr hs_code_7049 = hs_code_7050.copy({"local_code": "84717049"}) self.assertFalse(self.hs_code_computer.country_id) - self.categ_robots.hs_code_ids = [ - (4, self.hs_code_computer.id, 0), - (4, hs_code_7050.id, 0), - (4, hs_code_7049.id, 0), - ] + hs_code_7050.parent_id = self.hs_code_computer + hs_code_7049.parent_id = self.hs_code_computer self.assertEqual( self.pdt_c3po.categ_id, self.categ_robots, diff --git a/product_harmonized_system_per_country/views/hs_code.xml b/product_harmonized_system_per_country/views/hs_code.xml index 99895d69..4316b1f1 100644 --- a/product_harmonized_system_per_country/views/hs_code.xml +++ b/product_harmonized_system_per_country/views/hs_code.xml @@ -25,22 +25,17 @@ - - - - - ['|', ('hs_code_id', '=', active_id),('hs_code_ids', '=', active_id)] - - - - - ['|', ('hs_code_id', '=', active_id),('hs_code_ids', '=', active_id)] + + + + + + + + + + +