diff --git a/README.md b/README.md
index 71e35be..fb6dd95 100644
--- a/README.md
+++ b/README.md
@@ -21,10 +21,10 @@ Available addons
----------------
addon | version | maintainers | summary
--- | --- | --- | ---
-[intrastat_base](intrastat_base/) | 14.0.2.1.0 | | Base module for Intrastat reporting
-[intrastat_product](intrastat_product/) | 14.0.1.5.3 | | Base module for Intrastat Product
+[intrastat_base](intrastat_base/) | 14.0.2.2.0 | | Base module for Intrastat reporting
+[intrastat_product](intrastat_product/) | 14.0.1.6.0 | | Base module for Intrastat Product
[intrastat_product_generic](intrastat_product_generic/) | 14.0.1.0.0 | | Generic Intrastat Product Declaration
-[product_harmonized_system](product_harmonized_system/) | 14.0.2.1.0 | [](https://github.com/alexis-via) [](https://github.com/luc-demeyer) | Base module for Product Import/Export reports
+[product_harmonized_system](product_harmonized_system/) | 14.0.2.2.0 | [](https://github.com/alexis-via) [](https://github.com/luc-demeyer) | Base module for Product Import/Export reports
[product_harmonized_system_delivery](product_harmonized_system_delivery/) | 14.0.1.2.0 | [](https://github.com/alexis-via) [](https://github.com/luc-demeyer) | Hide native hs_code field provided by the delivery module
[product_harmonized_system_stock](product_harmonized_system_stock/) | 14.0.1.0.0 | [](https://github.com/alexis-via) [](https://github.com/luc-demeyer) | Adds a menu entry for H.S. codes
diff --git a/intrastat_base/__manifest__.py b/intrastat_base/__manifest__.py
index ee90c53..b0a3e45 100644
--- a/intrastat_base/__manifest__.py
+++ b/intrastat_base/__manifest__.py
@@ -5,7 +5,7 @@
{
"name": "Intrastat Reporting Base",
- "version": "14.0.2.1.0",
+ "version": "14.0.2.2.0",
"category": "Intrastat",
"license": "AGPL-3",
"summary": "Base module for Intrastat reporting",
diff --git a/intrastat_base/i18n/fr.po b/intrastat_base/i18n/fr.po
index 2f7b070..91ae1c9 100644
--- a/intrastat_base/i18n/fr.po
+++ b/intrastat_base/i18n/fr.po
@@ -45,6 +45,11 @@ msgstr "Sociétés"
msgid "Config Settings"
msgstr "Configuration"
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_res_partner
+msgid "Contact"
+msgstr ""
+
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position__display_name
#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position_template__display_name
@@ -52,6 +57,7 @@ msgstr "Configuration"
#: model:ir.model.fields,field_description:intrastat_base.field_product_template__display_name
#: model:ir.model.fields,field_description:intrastat_base.field_res_company__display_name
#: model:ir.model.fields,field_description:intrastat_base.field_res_config_settings__display_name
+#: model:ir.model.fields,field_description:intrastat_base.field_res_partner__display_name
msgid "Display Name"
msgstr "Afficher le nom"
@@ -67,6 +73,7 @@ msgstr "Position fiscale"
#: model:ir.model.fields,field_description:intrastat_base.field_product_template__id
#: model:ir.model.fields,field_description:intrastat_base.field_res_company__id
#: model:ir.model.fields,field_description:intrastat_base.field_res_config_settings__id
+#: model:ir.model.fields,field_description:intrastat_base.field_res_partner__id
msgid "ID"
msgstr "ID"
@@ -105,6 +112,7 @@ msgstr "Pièce comptable"
#: model:ir.model.fields,field_description:intrastat_base.field_product_template____last_update
#: model:ir.model.fields,field_description:intrastat_base.field_res_company____last_update
#: model:ir.model.fields,field_description:intrastat_base.field_res_config_settings____last_update
+#: model:ir.model.fields,field_description:intrastat_base.field_res_partner____last_update
msgid "Last Modified on"
msgstr "Dernière modification le"
@@ -132,6 +140,12 @@ msgstr "Adresse e-mail manquante pour l'utilisateur '%s'."
msgid "Product Template"
msgstr "Modèle d'article"
+#. module: intrastat_base
+#: code:addons/intrastat_base/models/res_partner.py:0
+#, python-format
+msgid "Programming Error when calling '_get_intrastat_country_code()"
+msgstr ""
+
#. module: intrastat_base
#: model:ir.model.fields,help:intrastat_base.field_account_bank_statement_line__intrastat_fiscal_position
#: model:ir.model.fields,help:intrastat_base.field_account_fiscal_position__intrastat
diff --git a/intrastat_base/i18n/intrastat_base.pot b/intrastat_base/i18n/intrastat_base.pot
index 73102a2..1834d73 100644
--- a/intrastat_base/i18n/intrastat_base.pot
+++ b/intrastat_base/i18n/intrastat_base.pot
@@ -38,6 +38,11 @@ msgstr ""
msgid "Config Settings"
msgstr ""
+#. module: intrastat_base
+#: model:ir.model,name:intrastat_base.model_res_partner
+msgid "Contact"
+msgstr ""
+
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position__display_name
#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position_template__display_name
@@ -45,6 +50,7 @@ msgstr ""
#: model:ir.model.fields,field_description:intrastat_base.field_product_template__display_name
#: model:ir.model.fields,field_description:intrastat_base.field_res_company__display_name
#: model:ir.model.fields,field_description:intrastat_base.field_res_config_settings__display_name
+#: model:ir.model.fields,field_description:intrastat_base.field_res_partner__display_name
msgid "Display Name"
msgstr ""
@@ -60,6 +66,7 @@ msgstr ""
#: model:ir.model.fields,field_description:intrastat_base.field_product_template__id
#: model:ir.model.fields,field_description:intrastat_base.field_res_company__id
#: model:ir.model.fields,field_description:intrastat_base.field_res_config_settings__id
+#: model:ir.model.fields,field_description:intrastat_base.field_res_partner__id
msgid "ID"
msgstr ""
@@ -98,6 +105,7 @@ msgstr ""
#: model:ir.model.fields,field_description:intrastat_base.field_product_template____last_update
#: model:ir.model.fields,field_description:intrastat_base.field_res_company____last_update
#: model:ir.model.fields,field_description:intrastat_base.field_res_config_settings____last_update
+#: model:ir.model.fields,field_description:intrastat_base.field_res_partner____last_update
msgid "Last Modified on"
msgstr ""
@@ -125,6 +133,12 @@ msgstr ""
msgid "Product Template"
msgstr ""
+#. module: intrastat_base
+#: code:addons/intrastat_base/models/res_partner.py:0
+#, python-format
+msgid "Programming Error when calling '_get_intrastat_country_code()"
+msgstr ""
+
#. module: intrastat_base
#: model:ir.model.fields,help:intrastat_base.field_account_bank_statement_line__intrastat_fiscal_position
#: model:ir.model.fields,help:intrastat_base.field_account_fiscal_position__intrastat
diff --git a/intrastat_base/models/__init__.py b/intrastat_base/models/__init__.py
index cea19b9..cc10e08 100644
--- a/intrastat_base/models/__init__.py
+++ b/intrastat_base/models/__init__.py
@@ -3,3 +3,4 @@ from . import res_company
from . import account_fiscal_position
from . import account_fiscal_position_template
from . import account_move
+from . import res_partner
diff --git a/intrastat_base/models/res_partner.py b/intrastat_base/models/res_partner.py
new file mode 100644
index 0000000..ed692b8
--- /dev/null
+++ b/intrastat_base/models/res_partner.py
@@ -0,0 +1,67 @@
+# Copyright 2022 Noviat.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import _, api, models
+from odoo.exceptions import UserError
+
+XI_COUNTY_NAMES = [
+ "antrim",
+ "armagh",
+ "down",
+ "fermanagh",
+ "londonderry",
+ "tyrone",
+ "northern ireland",
+]
+
+XI_COUNTIES = [
+ "base.state_uk18", # County Antrim
+ "base.state_uk19", # County Armagh
+ "base.state_uk20", # County Down
+ "base.state_uk22", # County Fermanagh
+ "base.state_uk23", # County Londonderry
+ "base.state_uk24", # County Tyrone
+ "base.state_ie_27", # Antrim
+ "base.state_ie_28", # Armagh
+ "base.state_ie_29", # Down
+ "base.state_ie_30", # Fermanagh
+ "base.state_ie_31", # Londonderry
+ "base.state_ie_32", # Tyrone
+]
+
+
+class ResPartner(models.Model):
+ _inherit = "res.partner"
+
+ @api.model
+ def _get_xi_counties(self):
+ return [self.env.ref(x) for x in XI_COUNTIES]
+
+ @api.model
+ def _get_xu_counties(self):
+ uk_counties = self.env.ref("base.uk").state_ids
+ xu_counties = uk_counties.filtered(lambda r: r not in self._get_xi_counties())
+ return xu_counties
+
+ def _get_intrastat_country_code(self, country=None, state=None):
+ if self:
+ self.ensure_one()
+ country = self.country_id
+ state = self.state_id
+ else:
+ state = state or self.env["res.country.state"]
+ country = country or state.country_id
+ if not country:
+ raise UserError(
+ _("Programming Error when calling '_get_intrastat_country_code()")
+ )
+ cc = country.code
+ if cc == "GB":
+ cc = "XU"
+ if state and cc in ["XU", "IE"]:
+ if (
+ state in self._get_xi_counties()
+ or state.name.lower().strip() in XI_COUNTY_NAMES
+ ):
+ cc = "XI"
+ return cc
diff --git a/intrastat_product/__manifest__.py b/intrastat_product/__manifest__.py
index 3a65c59..6439abf 100644
--- a/intrastat_product/__manifest__.py
+++ b/intrastat_product/__manifest__.py
@@ -7,7 +7,7 @@
{
"name": "Intrastat Product",
- "version": "14.0.1.5.3",
+ "version": "14.0.1.6.0",
"category": "Intrastat",
"license": "AGPL-3",
"summary": "Base module for Intrastat Product",
diff --git a/intrastat_product/i18n/fr.po b/intrastat_product/i18n/fr.po
index dbc7d74..397273c 100644
--- a/intrastat_product/i18n/fr.po
+++ b/intrastat_product/i18n/fr.po
@@ -83,6 +83,24 @@ msgstr "11"
msgid "12"
msgstr "12"
+#. module: intrastat_product
+#: model:ir.model.fields,help:intrastat_product.field_account_move_intrastat_line__product_origin_country_code
+#: model:ir.model.fields,help:intrastat_product.field_intrastat_product_computation_line__product_origin_country_code
+#: model:ir.model.fields,help:intrastat_product.field_intrastat_product_declaration_line__product_origin_country_code
+msgid ""
+"2 digit code of country of origin of the product except for the UK.\n"
+"Specify 'XI' for UK Northern Ireland and 'XU' for rest of the UK.\n"
+"Specify 'QU' when the country is unknown.\n"
+msgstr ""
+
+#. module: intrastat_product
+#: model:ir.model.fields,help:intrastat_product.field_intrastat_product_computation_line__src_dest_country_code
+#: model:ir.model.fields,help:intrastat_product.field_intrastat_product_declaration_line__src_dest_country_code
+msgid ""
+"2 digit code of country of origin/destination.\n"
+"Specify 'XI' for UK Northern Ireland and 'XU' for rest of the UK."
+msgstr ""
+
#. module: intrastat_product
#: model_terms:ir.ui.view,arch_db:intrastat_product.intrastat_product_declaration_view_form
msgid "Intrastat Product Declaration "
@@ -327,13 +345,23 @@ msgstr ""
msgid "Country"
msgstr "Pays"
+#. module: intrastat_product
+#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__src_dest_country_code
+#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__src_dest_country_code
+#, fuzzy
+msgid "Country Code"
+msgstr "Code pays de la société"
+
#. module: intrastat_product
#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__product_origin_country_id
msgid "Country of Origin"
msgstr "Pays d'origine"
#. module: intrastat_product
+#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__product_origin_country_code
+#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__product_origin_country_code
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__product_origin_country_id
+#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__product_origin_country_code
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__product_origin_country_id
msgid "Country of Origin of the Product"
msgstr "Pays d'origine de l'article"
@@ -1736,11 +1764,6 @@ msgstr ""
#~ "Corrigez le paramétrage de l'unité de mesure et regénérez les lignes ou "
#~ "ajustez manuellement les lignes concernées"
-#, fuzzy
-#~| msgid "Company Country Code"
-#~ msgid "Country Code"
-#~ msgstr "Code pays de la société"
-
#~ msgid "Default Incoterm for Intrastat"
#~ msgstr "Incoterm par défaut pour la DEB"
diff --git a/intrastat_product/i18n/intrastat_product.pot b/intrastat_product/i18n/intrastat_product.pot
index 31ec071..fc551df 100644
--- a/intrastat_product/i18n/intrastat_product.pot
+++ b/intrastat_product/i18n/intrastat_product.pot
@@ -79,6 +79,24 @@ msgstr ""
msgid "12"
msgstr ""
+#. module: intrastat_product
+#: model:ir.model.fields,help:intrastat_product.field_account_move_intrastat_line__product_origin_country_code
+#: model:ir.model.fields,help:intrastat_product.field_intrastat_product_computation_line__product_origin_country_code
+#: model:ir.model.fields,help:intrastat_product.field_intrastat_product_declaration_line__product_origin_country_code
+msgid ""
+"2 digit code of country of origin of the product except for the UK.\n"
+"Specify 'XI' for UK Northern Ireland and 'XU' for rest of the UK.\n"
+"Specify 'QU' when the country is unknown.\n"
+msgstr ""
+
+#. module: intrastat_product
+#: model:ir.model.fields,help:intrastat_product.field_intrastat_product_computation_line__src_dest_country_code
+#: model:ir.model.fields,help:intrastat_product.field_intrastat_product_declaration_line__src_dest_country_code
+msgid ""
+"2 digit code of country of origin/destination.\n"
+"Specify 'XI' for UK Northern Ireland and 'XU' for rest of the UK."
+msgstr ""
+
#. module: intrastat_product
#: model_terms:ir.ui.view,arch_db:intrastat_product.intrastat_product_declaration_view_form
msgid "Intrastat Product Declaration "
@@ -308,13 +326,22 @@ msgstr ""
msgid "Country"
msgstr ""
+#. module: intrastat_product
+#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__src_dest_country_code
+#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__src_dest_country_code
+msgid "Country Code"
+msgstr ""
+
#. module: intrastat_product
#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__product_origin_country_id
msgid "Country of Origin"
msgstr ""
#. module: intrastat_product
+#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__product_origin_country_code
+#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__product_origin_country_code
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__product_origin_country_id
+#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__product_origin_country_code
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__product_origin_country_id
msgid "Country of Origin of the Product"
msgstr ""
diff --git a/intrastat_product/models/account_move.py b/intrastat_product/models/account_move.py
index f916aa4..6c7e143 100644
--- a/intrastat_product/models/account_move.py
+++ b/intrastat_product/models/account_move.py
@@ -1,5 +1,5 @@
# Copyright 2011-2020 Akretion France (http://www.akretion.com)
-# Copyright 2009-2020 Noviat (http://www.noviat.com)
+# Copyright 2009-2022 Noviat (http://www.noviat.com)
# @author Alexis de Lattre
# @author Luc de Meyer
@@ -93,6 +93,14 @@ class AccountMove(models.Model):
if not hs_code:
return vals
weight, qty = decl_model._get_weight_and_supplunits(line, hs_code, notedict)
+ product_country = line.product_id.origin_country_id
+ product_state = line.product_id.origin_state_id
+ country = product_country or product_state.country_id
+ product_origin_country_code = "QU"
+ if country:
+ product_origin_country_code = self.env[
+ "res.partner"
+ ]._get_intrastat_country_code(product_country, product_state)
vals.update(
{
"invoice_line_id": line.id,
@@ -100,6 +108,7 @@ class AccountMove(models.Model):
"transaction_weight": int(weight),
"transaction_suppl_unit_qty": qty,
"product_origin_country_id": line.product_id.origin_country_id.id,
+ "product_origin_country_code": product_origin_country_code,
}
)
return vals
@@ -160,11 +169,23 @@ class AccountMoveIntrastatLine(models.Model):
transaction_weight = fields.Integer(
help="Transaction weight in Kg: Quantity x Product Weight"
)
+ # product_origin_country_id is replaced by product_origin_country_code
+ # this field should be dropped once the localisation modules have been
+ # adapted accordingly
product_origin_country_id = fields.Many2one(
comodel_name="res.country",
string="Country of Origin",
help="Country of origin of the product i.e. product " "'made in ____'.",
)
+ product_origin_country_code = fields.Char(
+ string="Country of Origin of the Product",
+ size=2,
+ required=True,
+ default="QU",
+ help="2 digit code of country of origin of the product except for the UK.\n"
+ "Specify 'XI' for UK Northern Ireland and 'XU' for rest of the UK.\n"
+ "Specify 'QU' when the country is unknown.\n",
+ )
@api.onchange("invoice_line_id")
def _onchange_move_id(self):
@@ -176,3 +197,18 @@ class AccountMoveIntrastatLine(models.Model):
("id", "not in", moves.mapped("intrastat_line_ids.invoice_line_id").ids),
]
return {"domain": {"invoice_line_id": dom}}
+
+ @api.model
+ def create(self, vals):
+ self._format_vals(vals)
+ return super().create(vals)
+
+ def write(self, vals):
+ self._format_vals(vals)
+ return super().write(vals)
+
+ def _format_vals(self, vals):
+ if "product_origin_country_code" in vals:
+ vals["product_origin_country_code"] = (
+ vals["product_origin_country_code"].upper().strip()
+ )
diff --git a/intrastat_product/models/intrastat_product_declaration.py b/intrastat_product/models/intrastat_product_declaration.py
index 91cc15d..ca066ec 100644
--- a/intrastat_product/models/intrastat_product_declaration.py
+++ b/intrastat_product/models/intrastat_product_declaration.py
@@ -1,9 +1,10 @@
# Copyright 2011-2020 Akretion France (http://www.akretion.com)
-# Copyright 2009-2020 Noviat (http://www.noviat.com)
+# Copyright 2009-2022 Noviat (http://www.noviat.com)
# @author Alexis de Lattre
# @author Luc de Meyer
import logging
+import warnings
from datetime import date
from dateutil.relativedelta import relativedelta
@@ -490,8 +491,31 @@ class IntrastatProductDeclaration(models.Model):
return incoterm
def _get_product_origin_country(self, inv_line, notedict):
+ warnings.warn(
+ "Method '_get_product_origin_country' is deprecated, "
+ "please use '_get_product_origin_country_code'.",
+ DeprecationWarning,
+ )
return inv_line.product_id.origin_country_id
+ def _get_product_origin_country_code(
+ self, inv_line, product_origin_country, notedict
+ ):
+ cc = "QU"
+ if product_origin_country.code:
+ cc = product_origin_country.code
+ year = self.year or str(inv_line.move_id.date.year)
+ if year >= "2021":
+ product_origin_state = getattr(
+ inv_line.product_id,
+ "origin_state_id",
+ self.env["res.country.state"],
+ )
+ cc = self.env["res.partner"]._get_intrastat_country_code(
+ product_origin_country, product_origin_state
+ )
+ return cc
+
def _get_vat(self, inv_line, notedict):
vat = False
inv = inv_line.move_id
@@ -667,6 +691,9 @@ class IntrastatProductDeclaration(models.Model):
partner_country = self._get_partner_country(
inv_line, notedict, eu_countries
)
+ partner_country_code = (
+ invoice.commercial_partner_id._get_intrastat_country_code()
+ )
if inv_intrastat_line:
hs_code = inv_intrastat_line.hs_code_id
@@ -708,9 +735,13 @@ class IntrastatProductDeclaration(models.Model):
product_origin_country = (
inv_intrastat_line.product_origin_country_id
)
+ product_origin_country_code = (
+ inv_intrastat_line.product_origin_country_code
+ )
else:
- product_origin_country = self._get_product_origin_country(
- inv_line, notedict
+ product_origin_country = inv_line.product_id.origin_country_id
+ product_origin_country_code = self._get_product_origin_country_code(
+ inv_line, product_origin_country, notedict
)
region = self._get_region(inv_line, notedict)
@@ -721,6 +752,7 @@ class IntrastatProductDeclaration(models.Model):
"parent_id": self.id,
"invoice_line_id": inv_line.id,
"src_dest_country_id": partner_country.id,
+ "src_dest_country_code": partner_country_code,
"product_id": inv_line.product_id.id,
"hs_code_id": hs_code.id,
"weight": weight,
@@ -729,6 +761,7 @@ class IntrastatProductDeclaration(models.Model):
"amount_accessory_cost_company_currency": 0.0,
"transaction_id": intrastat_transaction.id,
"product_origin_country_id": product_origin_country.id or False,
+ "product_origin_country_code": product_origin_country_code,
"region_id": region and region.id or False,
"vat": vat,
}
@@ -826,14 +859,13 @@ class IntrastatProductDeclaration(models.Model):
@api.model
def _group_line_hashcode_fields(self, computation_line):
return {
- "country": computation_line.src_dest_country_id.id or False,
+ "country": computation_line.src_dest_country_code,
"hs_code_id": computation_line.hs_code_id.id or False,
"intrastat_unit": computation_line.intrastat_unit_id.id or False,
"transaction": computation_line.transaction_id.id or False,
"transport": computation_line.transport_id.id or False,
"region": computation_line.region_id.id or False,
- "product_origin_country": computation_line.product_origin_country_id.id
- or False,
+ "product_origin_country": computation_line.product_origin_country_code,
"vat": computation_line.vat or False,
}
@@ -846,6 +878,7 @@ class IntrastatProductDeclaration(models.Model):
def _prepare_grouped_fields(self, computation_line, fields_to_sum):
vals = {
"src_dest_country_id": computation_line.src_dest_country_id.id,
+ "src_dest_country_code": computation_line.src_dest_country_code,
"intrastat_unit_id": computation_line.intrastat_unit_id.id,
"hs_code_id": computation_line.hs_code_id.id,
"transaction_id": computation_line.transaction_id.id,
@@ -853,6 +886,7 @@ class IntrastatProductDeclaration(models.Model):
"region_id": computation_line.region_id.id,
"parent_id": computation_line.parent_id.id,
"product_origin_country_id": computation_line.product_origin_country_id.id,
+ "product_origin_country_code": computation_line.product_origin_country_code,
"amount_company_currency": 0.0,
"vat": computation_line.vat,
}
@@ -1049,6 +1083,15 @@ class IntrastatProductComputationLine(models.Model):
string="Country",
help="Country of Origin/Destination",
)
+ src_dest_country_code = fields.Char(
+ string="Country Code",
+ compute="_compute_src_dest_country_code",
+ store=True,
+ required=True,
+ readonly=False,
+ help="2 digit code of country of origin/destination.\n"
+ "Specify 'XI' for UK Northern Ireland and 'XU' for rest of the UK.",
+ )
product_id = fields.Many2one(
"product.product", related="invoice_line_id.product_id"
)
@@ -1086,16 +1129,37 @@ class IntrastatProductComputationLine(models.Model):
"intrastat.transaction", string="Intrastat Transaction"
)
region_id = fields.Many2one("intrastat.region", string="Intrastat Region")
- # extended declaration
- incoterm_id = fields.Many2one("account.incoterms", string="Incoterm")
- transport_id = fields.Many2one("intrastat.transport_mode", string="Transport Mode")
+ # product_origin_country_id is replaced by product_origin_country_code
+ # this field should be dropped once the localisation modules have been
+ # adapted accordingly
product_origin_country_id = fields.Many2one(
"res.country",
string="Country of Origin of the Product",
help="Country of origin of the product i.e. product 'made in ____'",
)
+ product_origin_country_code = fields.Char(
+ string="Country of Origin of the Product",
+ size=2,
+ required=True,
+ default="QU",
+ help="2 digit code of country of origin of the product except for the UK.\n"
+ "Specify 'XI' for UK Northern Ireland and 'XU' for rest of the UK.\n"
+ "Specify 'QU' when the country is unknown.\n",
+ )
vat = fields.Char(string="VAT Number")
+ # extended declaration
+ incoterm_id = fields.Many2one("account.incoterms", string="Incoterm")
+ transport_id = fields.Many2one("intrastat.transport_mode", string="Transport Mode")
+
+ @api.onchange("src_dest_country_id")
+ def _onchange_src_dest_country_id(self):
+ self.src_dest_country_code = self.src_dest_country_id.code
+ if self.parent_id.year >= "2021":
+ self.src_dest_country_code = self.env[
+ "res.partner"
+ ]._get_intrastat_country_code(country=self.src_dest_country_id)
+
@api.depends("transport_id")
def _compute_check_validity(self):
"""TO DO: logic based upon fields"""
@@ -1151,6 +1215,12 @@ class IntrastatProductDeclarationLine(models.Model):
string="Country",
help="Country of Origin/Destination",
)
+ src_dest_country_code = fields.Char(
+ string="Country Code",
+ required=True,
+ help="2 digit code of country of origin/destination.\n"
+ "Specify 'XI' for UK Northern Ireland and 'XU' for rest of the UK.",
+ )
hs_code_id = fields.Many2one("hs.code", string="Intrastat Code")
intrastat_unit_id = fields.Many2one(
"intrastat.unit",
@@ -1172,15 +1242,35 @@ class IntrastatProductDeclarationLine(models.Model):
"intrastat.transaction", string="Intrastat Transaction"
)
region_id = fields.Many2one("intrastat.region", string="Intrastat Region")
- # extended declaration
- incoterm_id = fields.Many2one("account.incoterms", string="Incoterm")
- transport_id = fields.Many2one("intrastat.transport_mode", string="Transport Mode")
+ # product_origin_country_id is replaced by product_origin_country_code
+ # this field should be dropped once the localisation modules have been
+ # adapted accordingly
product_origin_country_id = fields.Many2one(
"res.country",
string="Country of Origin of the Product",
help="Country of origin of the product i.e. product 'made in ____'",
)
+ product_origin_country_code = fields.Char(
+ string="Country of Origin of the Product",
+ size=2,
+ required=True,
+ default="QU",
+ help="2 digit code of country of origin of the product except for the UK.\n"
+ "Specify 'XI' for UK Northern Ireland and 'XU' for rest of the UK.\n"
+ "Specify 'QU' when the country is unknown.\n",
+ )
vat = fields.Char(string="VAT Number")
+ # extended declaration
+ incoterm_id = fields.Many2one("account.incoterms", string="Incoterm")
+ transport_id = fields.Many2one("intrastat.transport_mode", string="Transport Mode")
+
+ @api.onchange("src_dest_country_id")
+ def _onchange_src_dest_country_id(self):
+ self.src_dest_country_code = self.src_dest_country_id.code
+ if self.parent_id.year >= "2021":
+ self.src_dest_country_code = self.env[
+ "res.partner"
+ ]._get_intrastat_country_code(country=self.src_dest_country_id)
@api.constrains("vat")
def _check_vat(self):
diff --git a/intrastat_product/report/intrastat_product_report_xls.py b/intrastat_product/report/intrastat_product_report_xls.py
index 48ccb26..54968fb 100644
--- a/intrastat_product/report/intrastat_product_report_xls.py
+++ b/intrastat_product/report/intrastat_product_report_xls.py
@@ -1,4 +1,4 @@
-# Copyright 2009-2020 Noviat
+# Copyright 2009-2022 Noviat
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
@@ -60,7 +60,7 @@ class IntrastatProductDeclarationXlsx(models.AbstractModel):
},
"line": {
"type": "string",
- "value": self._render("line.src_dest_country_id.name"),
+ "value": self._render("line.src_dest_country_code"),
},
"width": 28,
},
diff --git a/intrastat_product/security/ir.model.access.csv b/intrastat_product/security/ir.model.access.csv
index 65141ca..0fc2a99 100644
--- a/intrastat_product/security/ir.model.access.csv
+++ b/intrastat_product/security/ir.model.access.csv
@@ -8,6 +8,9 @@ access_intrastat_transport_mode_full,Full access on Intrastat Transport Modes to
access_intrastat_region_read,Read access on Intrastat Regions,model_intrastat_region,,1,0,0,0
access_intrastat_region_full,Full access on Intrastat Regions,model_intrastat_region,account.group_account_manager,1,1,1,1
access_hs_code_financial_mgr_full,Full access on H.S. Code to financial mgr,product_harmonized_system.model_hs_code,account.group_account_manager,1,1,1,1
+access_read_sale_move_intrastat_line,Read access to Sale User on Invoice Intrastat Lines,model_account_move_intrastat_line,sales_team.group_sale_salesman,1,0,0,0
+access_read_purchase_move_intrastat_line,Read access to Purchase User on Invoice Intrastat Lines,model_account_move_intrastat_line,purchase.group_purchase_user,1,0,0,0
+access_read_account_move_intrastat_line,Read access on Invoice Intrastat Lines,model_account_move_intrastat_line,account.group_account_readonly,1,0,0,0
access_account_move_intrastat_line,Full access on Invoice Intrastat Lines,model_account_move_intrastat_line,account.group_account_invoice,1,1,1,1
access_intrastat_product_declaration,Full access on Intrastat Product Declarations to Accountant,model_intrastat_product_declaration,account.group_account_user,1,1,1,1
access_intrastat_product_computation_line,Full access on Intrastat Product Computation Lines to Accountant,model_intrastat_product_computation_line,account.group_account_user,1,1,1,1
diff --git a/intrastat_product/tests/__init__.py b/intrastat_product/tests/__init__.py
index 804b5f7..a7ccefc 100644
--- a/intrastat_product/tests/__init__.py
+++ b/intrastat_product/tests/__init__.py
@@ -2,6 +2,7 @@ from . import common
from . import common_purchase
from . import common_sale
from . import test_intrastat_product
+from . import test_brexit
from . import test_company
from . import test_purchase_order
from . import test_sale_order
diff --git a/intrastat_product/tests/common.py b/intrastat_product/tests/common.py
index 6efb68b..ae84988 100644
--- a/intrastat_product/tests/common.py
+++ b/intrastat_product/tests/common.py
@@ -39,7 +39,7 @@ class IntrastatProductCommon(IntrastatCommon):
@classmethod
def _init_regions(cls):
- # Create Belgium Region
+ # Create Region
cls._create_region()
vals = {
@@ -75,7 +75,7 @@ class IntrastatProductCommon(IntrastatCommon):
@classmethod
def _create_region(cls, vals=None):
values = {
- "code": "BE_w",
+ "code": "2",
"country_id": cls.env.ref("base.be").id,
"company_id": cls.env.company.id,
"description": "Belgium Walloon Region",
diff --git a/intrastat_product/tests/test_brexit.py b/intrastat_product/tests/test_brexit.py
new file mode 100644
index 0000000..5001c5a
--- /dev/null
+++ b/intrastat_product/tests/test_brexit.py
@@ -0,0 +1,126 @@
+# Copyright 2022 Noviat.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo.tests import Form, SavepointCase
+
+from .common import IntrastatProductCommon
+
+
+class TestIntrastatBrexit(IntrastatProductCommon, SavepointCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ cls.inv_obj = cls.env["account.move"]
+ cls.hs_code_whiskey = cls.env["hs.code"].create(
+ {
+ "description": "Whiskey",
+ "local_code": "22083000",
+ }
+ )
+ cls.product_xi = cls.env["product.product"].create(
+ {
+ "name": "Bushmills Original",
+ "weight": 1.4,
+ "list_price": 30.0,
+ "standard_price": 15.0,
+ "origin_country_id": cls.env.ref("base.uk").id,
+ "origin_state_id": cls.env.ref("base.state_uk18").id,
+ "hs_code_id": cls.hs_code_whiskey.id,
+ }
+ )
+ cls.product_xu = cls.env["product.product"].create(
+ {
+ "name": "Glenfiddich",
+ "weight": 1.4,
+ "list_price": 50.0,
+ "standard_price": 25.0,
+ "origin_country_id": cls.env.ref("base.uk").id,
+ "origin_state_id": cls.env.ref("base.state_uk6").id,
+ "hs_code_id": cls.hs_code_whiskey.id,
+ }
+ )
+ cls.partner_xi = cls.env["res.partner"].create(
+ {
+ "name": "Bushmills Distillery",
+ "country_id": cls.env.ref("base.uk").id,
+ "state_id": cls.env.ref("base.state_uk18").id,
+ "vat": "XI123456782",
+ "property_account_position_id": cls.position.id,
+ }
+ )
+
+ def test_brexit_sale(self):
+ inv_out_xi = self.inv_obj.with_context(default_move_type="out_invoice").create(
+ {
+ "partner_id": self.partner_xi.id,
+ "fiscal_position_id": self.position.id,
+ }
+ )
+ with Form(inv_out_xi) as inv_form:
+ with inv_form.invoice_line_ids.new() as ail:
+ ail.product_id = self.product_c3po.product_variant_ids[0]
+ inv_out_xi.action_post()
+
+ self._create_declaration(
+ {
+ "declaration_type": "dispatches",
+ "year": str(inv_out_xi.date.year),
+ "month": str(inv_out_xi.date.month).zfill(2),
+ }
+ )
+ self.declaration.action_gather()
+ self.declaration.generate_declaration()
+ cline = self.declaration.computation_line_ids
+ dline = self.declaration.declaration_line_ids
+ self.assertEqual(cline.src_dest_country_code, "XI")
+ self.assertEqual(dline.src_dest_country_code, "XI")
+
+ def test_brexit_purchase(self):
+ inv_in_xi = self.inv_obj.with_context(default_move_type="in_invoice").create(
+ {
+ "partner_id": self.partner_xi.id,
+ "fiscal_position_id": self.position.id,
+ }
+ )
+ with Form(inv_in_xi) as inv_form:
+ with inv_form.invoice_line_ids.new() as ail:
+ ail.product_id = self.product_xi
+ with inv_form.invoice_line_ids.new() as ail:
+ ail.product_id = self.product_xu
+ inv_in_xi.invoice_date = inv_in_xi.date
+ inv_in_xi.action_post()
+
+ self._create_declaration(
+ {
+ "declaration_type": "arrivals",
+ "year": str(inv_in_xi.date.year),
+ "month": str(inv_in_xi.date.month).zfill(2),
+ }
+ )
+ self.declaration.action_gather()
+ self.declaration.generate_declaration()
+ clines = self.declaration.computation_line_ids
+ cl_xi = clines.filtered(lambda r: r.product_id == self.product_xi)
+ cl_xu = clines.filtered(lambda r: r.product_id == self.product_xu)
+ dlines = self.declaration.declaration_line_ids
+ dl_xi = dlines.filtered(lambda r: r.computation_line_ids == cl_xi)
+ dl_xu = dlines.filtered(lambda r: r.computation_line_ids == cl_xu)
+ self.assertEqual(cl_xi.product_origin_country_code, "XI")
+ self.assertEqual(cl_xu.product_origin_country_code, "XU")
+ self.assertEqual(dl_xi.product_origin_country_code, "XI")
+ self.assertEqual(dl_xu.product_origin_country_code, "XU")
+
+ def test_brexit_invoice_intrastat_details(self):
+ inv_in_xi = self.inv_obj.with_context(default_move_type="in_invoice").create(
+ {
+ "partner_id": self.partner_xi.id,
+ "fiscal_position_id": self.position.id,
+ }
+ )
+ with Form(inv_in_xi) as inv_form:
+ with inv_form.invoice_line_ids.new() as ail:
+ ail.product_id = self.product_xi
+ inv_in_xi.invoice_date = inv_in_xi.date
+ inv_in_xi.compute_intrastat_lines()
+ ilines = inv_in_xi.intrastat_line_ids
+ self.assertEqual(ilines.product_origin_country_code, "XI")
diff --git a/intrastat_product/views/account_move.xml b/intrastat_product/views/account_move.xml
index 6d0ad07..654faf8 100644
--- a/intrastat_product/views/account_move.xml
+++ b/intrastat_product/views/account_move.xml
@@ -47,10 +47,7 @@
-
+
diff --git a/intrastat_product/views/intrastat_product_declaration.xml b/intrastat_product/views/intrastat_product_declaration.xml
index ce21b8d..aee1eee 100644
--- a/intrastat_product/views/intrastat_product_declaration.xml
+++ b/intrastat_product/views/intrastat_product_declaration.xml
@@ -224,6 +224,7 @@
+
+
+
@@ -273,6 +279,7 @@
+
@@ -287,11 +294,17 @@
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"
/>
+
+
@@ -311,6 +324,7 @@
/>
+
+
+
@@ -351,7 +370,8 @@
invisible="not context.get('intrastat_product_declaration_line_main_view')"
/>
-
+
+
@@ -365,11 +385,17 @@
/>
+
+
diff --git a/product_harmonized_system/__manifest__.py b/product_harmonized_system/__manifest__.py
index 5730795..2eddfb0 100644
--- a/product_harmonized_system/__manifest__.py
+++ b/product_harmonized_system/__manifest__.py
@@ -9,7 +9,7 @@
{
"name": "Product Harmonized System Codes",
- "version": "14.0.2.1.0",
+ "version": "14.0.2.2.0",
"category": "Reporting",
"license": "AGPL-3",
"summary": "Base module for Product Import/Export reports",
diff --git a/product_harmonized_system/i18n/es.po b/product_harmonized_system/i18n/es.po
index 14f926c..edb4875 100644
--- a/product_harmonized_system/i18n/es.po
+++ b/product_harmonized_system/i18n/es.po
@@ -57,6 +57,22 @@ msgstr ""
msgid "Company"
msgstr "Compañía"
+#. module: product_harmonized_system
+#: model:ir.model.fields,field_description:product_harmonized_system.field_product_product__origin_state_id
+#: model:ir.model.fields,field_description:product_harmonized_system.field_product_template__origin_state_id
+msgid "Country State of Origin"
+msgstr ""
+
+#. module: product_harmonized_system
+#: model:ir.model.fields,help:product_harmonized_system.field_product_product__origin_state_id
+#: model:ir.model.fields,help:product_harmonized_system.field_product_template__origin_state_id
+msgid ""
+"Country State of origin of the product.\n"
+"This field is used for the Intrastat declaration, selecting one of the "
+"Northern Ireland counties will set the code 'XI' for products from the "
+"United Kingdom whereas code 'XU' will be used for the other UK counties."
+msgstr ""
+
#. module: product_harmonized_system
#: model:ir.model.fields,field_description:product_harmonized_system.field_product_product__origin_country_id
#: model:ir.model.fields,field_description:product_harmonized_system.field_product_template__origin_country_id
diff --git a/product_harmonized_system/i18n/fr.po b/product_harmonized_system/i18n/fr.po
index 8802d3d..44015c2 100644
--- a/product_harmonized_system/i18n/fr.po
+++ b/product_harmonized_system/i18n/fr.po
@@ -58,6 +58,22 @@ msgstr ""
msgid "Company"
msgstr "Société"
+#. module: product_harmonized_system
+#: model:ir.model.fields,field_description:product_harmonized_system.field_product_product__origin_state_id
+#: model:ir.model.fields,field_description:product_harmonized_system.field_product_template__origin_state_id
+msgid "Country State of Origin"
+msgstr ""
+
+#. module: product_harmonized_system
+#: model:ir.model.fields,help:product_harmonized_system.field_product_product__origin_state_id
+#: model:ir.model.fields,help:product_harmonized_system.field_product_template__origin_state_id
+msgid ""
+"Country State of origin of the product.\n"
+"This field is used for the Intrastat declaration, selecting one of the "
+"Northern Ireland counties will set the code 'XI' for products from the "
+"United Kingdom whereas code 'XU' will be used for the other UK counties."
+msgstr ""
+
#. module: product_harmonized_system
#: model:ir.model.fields,field_description:product_harmonized_system.field_product_product__origin_country_id
#: model:ir.model.fields,field_description:product_harmonized_system.field_product_template__origin_country_id
diff --git a/product_harmonized_system/i18n/product_harmonized_system.pot b/product_harmonized_system/i18n/product_harmonized_system.pot
index 700b400..43ddf64 100644
--- a/product_harmonized_system/i18n/product_harmonized_system.pot
+++ b/product_harmonized_system/i18n/product_harmonized_system.pot
@@ -51,6 +51,20 @@ msgstr ""
msgid "Company"
msgstr ""
+#. module: product_harmonized_system
+#: model:ir.model.fields,field_description:product_harmonized_system.field_product_product__origin_state_id
+#: model:ir.model.fields,field_description:product_harmonized_system.field_product_template__origin_state_id
+msgid "Country State of Origin"
+msgstr ""
+
+#. module: product_harmonized_system
+#: model:ir.model.fields,help:product_harmonized_system.field_product_product__origin_state_id
+#: model:ir.model.fields,help:product_harmonized_system.field_product_template__origin_state_id
+msgid ""
+"Country State of origin of the product.\n"
+"This field is used for the Intrastat declaration, selecting one of the Northern Ireland counties will set the code 'XI' for products from the United Kingdom whereas code 'XU' will be used for the other UK counties."
+msgstr ""
+
#. module: product_harmonized_system
#: model:ir.model.fields,field_description:product_harmonized_system.field_product_product__origin_country_id
#: model:ir.model.fields,field_description:product_harmonized_system.field_product_template__origin_country_id
diff --git a/product_harmonized_system/models/product_template.py b/product_harmonized_system/models/product_template.py
index 4670cfc..902deea 100644
--- a/product_harmonized_system/models/product_template.py
+++ b/product_harmonized_system/models/product_template.py
@@ -23,10 +23,20 @@ class ProductTemplate(models.Model):
"and configure the H.S. code on the product category.",
)
origin_country_id = fields.Many2one(
- "res.country",
+ comodel_name="res.country",
string="Country of Origin",
help="Country of origin of the product i.e. product " "'made in ____'.",
)
+ origin_state_id = fields.Many2one(
+ comodel_name="res.country.state",
+ string="Country State of Origin",
+ domain="[('country_id', '=?', origin_country_id)]",
+ help="Country State of origin of the product.\n"
+ "This field is used for the Intrastat declaration, "
+ "selecting one of the Northern Ireland counties will set the code 'XI' "
+ "for products from the United Kingdom whereas code 'XU' "
+ "will be used for the other UK counties.",
+ )
class ProductProduct(models.Model):
diff --git a/product_harmonized_system/views/product_template.xml b/product_harmonized_system/views/product_template.xml
index 59fa83e..79d2b27 100644
--- a/product_harmonized_system/views/product_template.xml
+++ b/product_harmonized_system/views/product_template.xml
@@ -20,6 +20,10 @@
name="origin_country_id"
attrs="{'invisible': [('type', '=', 'service')]}"
/>
+