[14.0]Intrastat Brexit support

This commit is contained in:
Luc De Meyer
2021-12-26 13:51:33 +01:00
parent dd85e76724
commit 47cbc65d0f
6 changed files with 135 additions and 25 deletions

View File

@@ -1,9 +1,10 @@
# Copyright 2011-2020 Akretion France (http://www.akretion.com)
# Copyright 2009-2020 Noviat (http://www.noviat.com)
# Copyright 2009-2021 Noviat (http://www.noviat.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Luc de Meyer <info@noviat.com>
from odoo import api, fields, models
from odoo import _, api, fields, models
from odoo.exceptions import UserError
class AccountMove(models.Model):
@@ -93,13 +94,17 @@ class AccountMove(models.Model):
if not hs_code:
return vals
weight, qty = decl_model._get_weight_and_supplunits(line, hs_code, notedict)
product_origin_country = line.product_id.origin_country_id
product_origin_country_code = decl_model._get_product_origin_country_code(
line, product_origin_country
)
vals.update(
{
"invoice_line_id": line.id,
"hs_code_id": hs_code.id,
"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 +165,22 @@ 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",
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 +192,25 @@ 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()
)
if len(vals["product_origin_country_code"]) != 2:
raise UserError(
_(
"Intrastat transaction details error:\n"
"Product Origin Country Code must be 2 characters."
)
)

View File

@@ -1,5 +1,5 @@
# Copyright 2011-2020 Akretion France (http://www.akretion.com)
# Copyright 2009-2020 Noviat (http://www.noviat.com)
# Copyright 2009-2021 Noviat (http://www.noviat.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Luc de Meyer <info@noviat.com>
@@ -489,8 +489,24 @@ class IntrastatProductDeclaration(models.Model):
self._account_config_warning(msg)
return incoterm
def _get_product_origin_country(self, inv_line, notedict):
return inv_line.product_id.origin_country_id
def _get_product_origin_country_code(
self, inv_line, product_origin_country, notedict
):
product_origin_country_code = "QU"
if product_origin_country.code:
product_origin_country_code = product_origin_country.code
year = self.year or str(inv_line.move_id.date.year)
if year >= "2021":
if (
hasattr(inv_line.product_id, "origin_state_id")
and inv_line.product_id.origin_state_id
and inv_line.product_id.origin_state_id.name.lower()
== "northern ireland"
):
product_origin_country_code = "XI"
elif inv_line.product_id.origin_country_id.code == "GB":
product_origin_country_code = "XU"
return product_origin_country_code
def _get_vat(self, inv_line, notedict):
vat = False
@@ -705,12 +721,13 @@ class IntrastatProductDeclaration(models.Model):
total_inv_product_cc += amount_company_currency
if inv_intrastat_line:
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)
@@ -728,7 +745,7 @@ class IntrastatProductDeclaration(models.Model):
"amount_company_currency": amount_company_currency,
"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,
}
@@ -832,9 +849,8 @@ class IntrastatProductDeclaration(models.Model):
"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,
"vat": computation_line.vat or False,
"product_origin_country_code": computation_line.product_origin_country_code,
}
def group_line_hashcode(self, computation_line):
@@ -852,7 +868,7 @@ class IntrastatProductDeclaration(models.Model):
"transport_id": computation_line.transport_id.id,
"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,
}
@@ -1086,16 +1102,28 @@ 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",
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.depends("transport_id")
def _compute_check_validity(self):
"""TO DO: logic based upon fields"""
@@ -1172,15 +1200,26 @@ 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",
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.constrains("vat")
def _check_vat(self):

View File

@@ -47,10 +47,7 @@
<field name="transaction_suppl_unit_qty" />
<field name="hs_code_id" />
<field name="transaction_weight" />
<field
name="product_origin_country_id"
options="{'no_create': True, 'no_open': True}"
/>
<field name="product_origin_country_code" />
</tree>
</field>
</page>

View File

@@ -250,7 +250,12 @@
/>
<field name="incoterm_id" invisible="1" />
<field name="region_id" invisible="1" />
<!-- TODO: remove product_origin_country_id after update of localization modules -->
<field name="product_origin_country_id" invisible="1" />
<field
name="product_origin_country_code"
attrs="{'invisible': [('type', '!=', 'arrivals')]}"
/>
<field name="vat" />
<field name="partner_id" />
<field name="invoice_id" />
@@ -287,11 +292,17 @@
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<field name="region_id" invisible="1" />
<!-- TODO: remove product_origin_country_id after update of localization modules -->
<field
name="product_origin_country_id"
invisible="1"
string="Product C/O"
/>
<field
name="product_origin_country_code"
attrs="{'column_invisible': [('parent.type', '=', 'arrivals')]}"
string="Product C/O"
/>
<field name="vat" />
<field name="invoice_id" />
<field name="declaration_type" invisible="1" />
@@ -332,7 +343,12 @@
/>
<field name="region_id" invisible="1" />
<field name="incoterm_id" invisible="1" />
<!-- TODO: remove product_origin_country_id after update of localization modules -->
<field name="product_origin_country_id" invisible="1" />
<field
name="product_origin_country_code"
attrs="{'invisible': [('type', '!=', 'arrivals')]}"
/>
<field name="vat" />
</group>
<group name="computation" string="Related Transactions">
@@ -365,11 +381,17 @@
/>
<field name="region_id" invisible="1" />
<field name="incoterm_id" invisible="1" />
<!-- TODO: remove product_origin_country_id after update of localization modules -->
<field
name="product_origin_country_id"
invisible="1"
string="Product C/O"
/>
<field
name="product_origin_country_code"
attrs="{'column_invisible': [('parent.type', '=', 'arrivals')]}"
string="Product C/O"
/>
<field name="vat" />
</tree>
</field>

View File

@@ -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 'Northern Ireland' will set the code 'XI' "
"for products from the United Kingdom whereas code 'XU' "
"will be used for the other UK states.",
)
class ProductProduct(models.Model):

View File

@@ -20,6 +20,10 @@
name="origin_country_id"
attrs="{'invisible': [('type', '=', 'service')]}"
/>
<field
name="origin_state_id"
attrs="{'invisible': [('type', '=', 'service')]}"
/>
</field>
</field>
</record>