mirror of
https://github.com/OCA/intrastat-extrastat.git
synced 2025-02-16 17:13:41 +02:00
[14.0]Intrastat Brexit support
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
# Copyright 2011-2020 Akretion France (http://www.akretion.com)
|
# 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 Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
# @author Luc de Meyer <info@noviat.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):
|
class AccountMove(models.Model):
|
||||||
@@ -93,13 +94,17 @@ class AccountMove(models.Model):
|
|||||||
if not hs_code:
|
if not hs_code:
|
||||||
return vals
|
return vals
|
||||||
weight, qty = decl_model._get_weight_and_supplunits(line, hs_code, notedict)
|
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(
|
vals.update(
|
||||||
{
|
{
|
||||||
"invoice_line_id": line.id,
|
"invoice_line_id": line.id,
|
||||||
"hs_code_id": hs_code.id,
|
"hs_code_id": hs_code.id,
|
||||||
"transaction_weight": int(weight),
|
"transaction_weight": int(weight),
|
||||||
"transaction_suppl_unit_qty": qty,
|
"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
|
return vals
|
||||||
@@ -160,11 +165,22 @@ class AccountMoveIntrastatLine(models.Model):
|
|||||||
transaction_weight = fields.Integer(
|
transaction_weight = fields.Integer(
|
||||||
help="Transaction weight in Kg: Quantity x Product Weight"
|
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(
|
product_origin_country_id = fields.Many2one(
|
||||||
comodel_name="res.country",
|
comodel_name="res.country",
|
||||||
string="Country of Origin",
|
string="Country of Origin",
|
||||||
help="Country of origin of the product i.e. product " "'made in ____'.",
|
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")
|
@api.onchange("invoice_line_id")
|
||||||
def _onchange_move_id(self):
|
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),
|
("id", "not in", moves.mapped("intrastat_line_ids.invoice_line_id").ids),
|
||||||
]
|
]
|
||||||
return {"domain": {"invoice_line_id": dom}}
|
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."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright 2011-2020 Akretion France (http://www.akretion.com)
|
# 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 Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
# @author Luc de Meyer <info@noviat.com>
|
# @author Luc de Meyer <info@noviat.com>
|
||||||
|
|
||||||
@@ -489,8 +489,24 @@ class IntrastatProductDeclaration(models.Model):
|
|||||||
self._account_config_warning(msg)
|
self._account_config_warning(msg)
|
||||||
return incoterm
|
return incoterm
|
||||||
|
|
||||||
def _get_product_origin_country(self, inv_line, notedict):
|
def _get_product_origin_country_code(
|
||||||
return inv_line.product_id.origin_country_id
|
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):
|
def _get_vat(self, inv_line, notedict):
|
||||||
vat = False
|
vat = False
|
||||||
@@ -705,12 +721,13 @@ class IntrastatProductDeclaration(models.Model):
|
|||||||
total_inv_product_cc += amount_company_currency
|
total_inv_product_cc += amount_company_currency
|
||||||
|
|
||||||
if inv_intrastat_line:
|
if inv_intrastat_line:
|
||||||
product_origin_country = (
|
product_origin_country_code = (
|
||||||
inv_intrastat_line.product_origin_country_id
|
inv_intrastat_line.product_origin_country_code
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
product_origin_country = self._get_product_origin_country(
|
product_origin_country = inv_line.product_id.origin_country_id
|
||||||
inv_line, notedict
|
product_origin_country_code = self._get_product_origin_country_code(
|
||||||
|
inv_line, product_origin_country, notedict
|
||||||
)
|
)
|
||||||
|
|
||||||
region = self._get_region(inv_line, notedict)
|
region = self._get_region(inv_line, notedict)
|
||||||
@@ -728,7 +745,7 @@ class IntrastatProductDeclaration(models.Model):
|
|||||||
"amount_company_currency": amount_company_currency,
|
"amount_company_currency": amount_company_currency,
|
||||||
"amount_accessory_cost_company_currency": 0.0,
|
"amount_accessory_cost_company_currency": 0.0,
|
||||||
"transaction_id": intrastat_transaction.id,
|
"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,
|
"region_id": region and region.id or False,
|
||||||
"vat": vat,
|
"vat": vat,
|
||||||
}
|
}
|
||||||
@@ -832,9 +849,8 @@ class IntrastatProductDeclaration(models.Model):
|
|||||||
"transaction": computation_line.transaction_id.id or False,
|
"transaction": computation_line.transaction_id.id or False,
|
||||||
"transport": computation_line.transport_id.id or False,
|
"transport": computation_line.transport_id.id or False,
|
||||||
"region": computation_line.region_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,
|
"vat": computation_line.vat or False,
|
||||||
|
"product_origin_country_code": computation_line.product_origin_country_code,
|
||||||
}
|
}
|
||||||
|
|
||||||
def group_line_hashcode(self, computation_line):
|
def group_line_hashcode(self, computation_line):
|
||||||
@@ -852,7 +868,7 @@ class IntrastatProductDeclaration(models.Model):
|
|||||||
"transport_id": computation_line.transport_id.id,
|
"transport_id": computation_line.transport_id.id,
|
||||||
"region_id": computation_line.region_id.id,
|
"region_id": computation_line.region_id.id,
|
||||||
"parent_id": computation_line.parent_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,
|
"amount_company_currency": 0.0,
|
||||||
"vat": computation_line.vat,
|
"vat": computation_line.vat,
|
||||||
}
|
}
|
||||||
@@ -1086,16 +1102,28 @@ class IntrastatProductComputationLine(models.Model):
|
|||||||
"intrastat.transaction", string="Intrastat Transaction"
|
"intrastat.transaction", string="Intrastat Transaction"
|
||||||
)
|
)
|
||||||
region_id = fields.Many2one("intrastat.region", string="Intrastat Region")
|
region_id = fields.Many2one("intrastat.region", string="Intrastat Region")
|
||||||
# extended declaration
|
# product_origin_country_id is replaced by product_origin_country_code
|
||||||
incoterm_id = fields.Many2one("account.incoterms", string="Incoterm")
|
# this field should be dropped once the localisation modules have been
|
||||||
transport_id = fields.Many2one("intrastat.transport_mode", string="Transport Mode")
|
# adapted accordingly
|
||||||
product_origin_country_id = fields.Many2one(
|
product_origin_country_id = fields.Many2one(
|
||||||
"res.country",
|
"res.country",
|
||||||
string="Country of Origin of the Product",
|
string="Country of Origin of the Product",
|
||||||
help="Country of origin of the product i.e. product 'made in ____'",
|
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")
|
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")
|
@api.depends("transport_id")
|
||||||
def _compute_check_validity(self):
|
def _compute_check_validity(self):
|
||||||
"""TO DO: logic based upon fields"""
|
"""TO DO: logic based upon fields"""
|
||||||
@@ -1172,15 +1200,26 @@ class IntrastatProductDeclarationLine(models.Model):
|
|||||||
"intrastat.transaction", string="Intrastat Transaction"
|
"intrastat.transaction", string="Intrastat Transaction"
|
||||||
)
|
)
|
||||||
region_id = fields.Many2one("intrastat.region", string="Intrastat Region")
|
region_id = fields.Many2one("intrastat.region", string="Intrastat Region")
|
||||||
# extended declaration
|
# product_origin_country_id is replaced by product_origin_country_code
|
||||||
incoterm_id = fields.Many2one("account.incoterms", string="Incoterm")
|
# this field should be dropped once the localisation modules have been
|
||||||
transport_id = fields.Many2one("intrastat.transport_mode", string="Transport Mode")
|
# adapted accordingly
|
||||||
product_origin_country_id = fields.Many2one(
|
product_origin_country_id = fields.Many2one(
|
||||||
"res.country",
|
"res.country",
|
||||||
string="Country of Origin of the Product",
|
string="Country of Origin of the Product",
|
||||||
help="Country of origin of the product i.e. product 'made in ____'",
|
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")
|
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")
|
@api.constrains("vat")
|
||||||
def _check_vat(self):
|
def _check_vat(self):
|
||||||
|
|||||||
@@ -47,10 +47,7 @@
|
|||||||
<field name="transaction_suppl_unit_qty" />
|
<field name="transaction_suppl_unit_qty" />
|
||||||
<field name="hs_code_id" />
|
<field name="hs_code_id" />
|
||||||
<field name="transaction_weight" />
|
<field name="transaction_weight" />
|
||||||
<field
|
<field name="product_origin_country_code" />
|
||||||
name="product_origin_country_id"
|
|
||||||
options="{'no_create': True, 'no_open': True}"
|
|
||||||
/>
|
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</page>
|
</page>
|
||||||
|
|||||||
@@ -250,7 +250,12 @@
|
|||||||
/>
|
/>
|
||||||
<field name="incoterm_id" invisible="1" />
|
<field name="incoterm_id" invisible="1" />
|
||||||
<field name="region_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_id" invisible="1" />
|
||||||
|
<field
|
||||||
|
name="product_origin_country_code"
|
||||||
|
attrs="{'invisible': [('type', '!=', 'arrivals')]}"
|
||||||
|
/>
|
||||||
<field name="vat" />
|
<field name="vat" />
|
||||||
<field name="partner_id" />
|
<field name="partner_id" />
|
||||||
<field name="invoice_id" />
|
<field name="invoice_id" />
|
||||||
@@ -287,11 +292,17 @@
|
|||||||
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"
|
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"
|
||||||
/>
|
/>
|
||||||
<field name="region_id" invisible="1" />
|
<field name="region_id" invisible="1" />
|
||||||
|
<!-- TODO: remove product_origin_country_id after update of localization modules -->
|
||||||
<field
|
<field
|
||||||
name="product_origin_country_id"
|
name="product_origin_country_id"
|
||||||
invisible="1"
|
invisible="1"
|
||||||
string="Product C/O"
|
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="vat" />
|
||||||
<field name="invoice_id" />
|
<field name="invoice_id" />
|
||||||
<field name="declaration_type" invisible="1" />
|
<field name="declaration_type" invisible="1" />
|
||||||
@@ -332,7 +343,12 @@
|
|||||||
/>
|
/>
|
||||||
<field name="region_id" invisible="1" />
|
<field name="region_id" invisible="1" />
|
||||||
<field name="incoterm_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_id" invisible="1" />
|
||||||
|
<field
|
||||||
|
name="product_origin_country_code"
|
||||||
|
attrs="{'invisible': [('type', '!=', 'arrivals')]}"
|
||||||
|
/>
|
||||||
<field name="vat" />
|
<field name="vat" />
|
||||||
</group>
|
</group>
|
||||||
<group name="computation" string="Related Transactions">
|
<group name="computation" string="Related Transactions">
|
||||||
@@ -365,11 +381,17 @@
|
|||||||
/>
|
/>
|
||||||
<field name="region_id" invisible="1" />
|
<field name="region_id" invisible="1" />
|
||||||
<field name="incoterm_id" invisible="1" />
|
<field name="incoterm_id" invisible="1" />
|
||||||
|
<!-- TODO: remove product_origin_country_id after update of localization modules -->
|
||||||
<field
|
<field
|
||||||
name="product_origin_country_id"
|
name="product_origin_country_id"
|
||||||
invisible="1"
|
invisible="1"
|
||||||
string="Product C/O"
|
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="vat" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
|
|||||||
@@ -23,10 +23,20 @@ class ProductTemplate(models.Model):
|
|||||||
"and configure the H.S. code on the product category.",
|
"and configure the H.S. code on the product category.",
|
||||||
)
|
)
|
||||||
origin_country_id = fields.Many2one(
|
origin_country_id = fields.Many2one(
|
||||||
"res.country",
|
comodel_name="res.country",
|
||||||
string="Country of Origin",
|
string="Country of Origin",
|
||||||
help="Country of origin of the product i.e. product " "'made in ____'.",
|
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):
|
class ProductProduct(models.Model):
|
||||||
|
|||||||
@@ -20,6 +20,10 @@
|
|||||||
name="origin_country_id"
|
name="origin_country_id"
|
||||||
attrs="{'invisible': [('type', '=', 'service')]}"
|
attrs="{'invisible': [('type', '=', 'service')]}"
|
||||||
/>
|
/>
|
||||||
|
<field
|
||||||
|
name="origin_state_id"
|
||||||
|
attrs="{'invisible': [('type', '=', 'service')]}"
|
||||||
|
/>
|
||||||
</field>
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|||||||
Reference in New Issue
Block a user