Skip to content

Commit

Permalink
[IMP] restructuring to link hs codes together instead of listing hs c…
Browse files Browse the repository at this point in the history
…odes on products
  • Loading branch information
emiliesoutiras committed Sep 18, 2024
1 parent 667c8fb commit 7ff590f
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 91 deletions.
4 changes: 2 additions & 2 deletions product_harmonized_system_per_country/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
===========
Expand Down
5 changes: 2 additions & 3 deletions product_harmonized_system_per_country/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
55 changes: 25 additions & 30 deletions product_harmonized_system_per_country/models/hs_code.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# Copyright (c) 2024 Groupe Voltaire
# @author Emilie SOUTIRAS <[email protected]>
# 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):
Expand All @@ -11,44 +10,38 @@ 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

Check warning on line 34 in product_harmonized_system_per_country/models/hs_code.py

View check run for this annotation

Codecov / codecov/patch

product_harmonized_system_per_country/models/hs_code.py#L34

Added line #L34 was not covered by tests
code.related_hs_code_ids = res

def filter_per_country(self):
country_id = self.env.context.get("hs_code_for_country", False)
active_companies = self.env.context.get("allowed_company_ids")
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)
)
Expand All @@ -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]
Expand Down
17 changes: 3 additions & 14 deletions product_harmonized_system_per_country/models/product_category.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,18 @@
# 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__)


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()

Check warning on line 19 in product_harmonized_system_per_country/models/product_category.py

View check run for this annotation

Codecov / codecov/patch

product_harmonized_system_per_country/models/product_category.py#L19

Added line #L19 was not covered by tests
return res
29 changes: 17 additions & 12 deletions product_harmonized_system_per_country/models/product_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,27 @@
# @author Emilie SOUTIRAS <[email protected]>
# 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 = (

Check warning on line 19 in product_harmonized_system_per_country/models/product_product.py

View check run for this annotation

Codecov / codecov/patch

product_harmonized_system_per_country/models/product_product.py#L19

Added line #L19 was not covered by tests
pdt_tmpl.hs_code_id.filter_per_country().hs_code or ""
)
else:
pdt_tmpl.hs_code = (

Check warning on line 23 in product_harmonized_system_per_country/models/product_product.py

View check run for this annotation

Codecov / codecov/patch

product_harmonized_system_per_country/models/product_product.py#L23

Added line #L23 was not covered by tests
pdt_tmpl.categ_id.get_hs_code_recursively().hs_code or ""
)


class ProductProduct(models.Model):
Expand All @@ -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
4 changes: 2 additions & 2 deletions product_harmonized_system_per_country/readme/USAGE.rst
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<!-- Delivery slip -->
<template id="report_deliveryslip" inherit_id="stock.report_deliveryslip">
<xpath expr="//t[@t-call]" position="before">
<t
t-set="o"
t-value="o.with_context(hs_code_for_country=o.sudo().sale_id.partner_id.country_id.id or False)"
/>
</xpath>
</template>
<record id="report_delivery_document2" model="ir.ui.view">
<field name="name">stock.picking.report.delivery.inherit</field>
<field name="inherit_id" ref="delivery.report_delivery_document2" />
<field name="priority" eval="1000" />
<field name="arch" type="xml">
<xpath expr="//t[@t-set='has_hs_code']" position="attributes">
<attribute name="t-value">
o.move_ids.filtered(lambda l: l.product_id.hs_code)
</attribute>
</xpath>
<!-- <xpath expr="//span[@t-field='']" position="replace">-->
<!-- </xpath>-->
</field>
</record>
</odoo>
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,8 @@ <h1><a class="toc-backref" href="#toc-entry-1">Installation</a></h1>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
<p>This module only depends on the <em>intrastat_product</em> module, whiwh depends on <em>product_harmonized_systems</em> module.</p>
<p>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.</p>
<p>This module depends on the <em>delivery</em> module and the <em>intrastat_product</em> module, which depends on the <em>product_harmonized_systems</em> module.</p>
<p>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.</p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
Expand Down
15 changes: 5 additions & 10 deletions product_harmonized_system_per_country/tests/test_hs_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down
27 changes: 11 additions & 16 deletions product_harmonized_system_per_country/views/hs_code.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,17 @@
<field name="local_code" position="after">
<field name="country_id" />
</field>
</field>
</record>
<record
id="product_harmonized_system.product_categ_hs_code_action"
model="ir.actions.act_window"
>
<field name="domain">
['|', ('hs_code_id', '=', active_id),('hs_code_ids', '=', active_id)]
</field>
</record>
<record
id="product_harmonized_system.product_template_hs_code_action"
model="ir.actions.act_window"
>
<field name="domain">
['|', ('hs_code_id', '=', active_id),('hs_code_ids', '=', active_id)]
<group name="main" position="inside">
<field name="parent_id" />
<field name="related_hs_code_ids">
<tree>

<field name="local_code" />
<field name="hs_code" />
<field name="country_id" />
</tree>
</field>
</group>
</field>
</record>
</odoo>

0 comments on commit 7ff590f

Please sign in to comment.