[IMP] Big simplification, update and cleanup

This commit aims at removing the over-complexity of intrastat modules
while increasing simplicity/usability for users.

- Move default intrastat transaction from res.company to account.fiscal.position to add su
pport for B2C (and not just B2B)
- improve usability: auto-generate declaration lines and XML export when
going from draft to done. Auto-delete declaration lines and XML export
when going from done to draft (and add confirmation pop-up).
- declaration lines are now readonly. Only computation lines can be created/edited manuall
y
- add field region_code on computation lines and declaration lines.
Remove region_id on declaration lines. This change allows big
simplification in some localization modules such as
l10n_fr_intrastat_product.
- simplify Brexit implementation. Northern Ireland is important, but we
can't afford to have so many lines of code and add a field on
product.template (origin_state_id) for a territory of 1.9 million
inhabitants! This is too costly to maintain and too complex for users.
- improve default visibility of fields when reporting_level = 'standard'
- add support for weight calculation from uom categories other than
units and weight, supposing that the 'weight' field on product.template
is the weight per uom of the product
- add EU companies from several different countries in demo data with valid VAT numbers
This commit is contained in:
Alexis de Lattre
2022-11-04 18:04:09 +01:00
parent 970601ed4b
commit 8be97de8d0
16 changed files with 461 additions and 477 deletions

View File

@@ -33,6 +33,7 @@
"views/intrastat_product_declaration.xml",
"views/res_config_settings.xml",
"views/res_partner_view.xml",
"views/account_fiscal_position.xml",
"views/account_move.xml",
"views/sale_order.xml",
"views/stock_warehouse.xml",

View File

@@ -10,3 +10,4 @@ from . import intrastat_transport_mode
from . import intrastat_unit
from . import sale_order
from . import stock_warehouse
from . import account_fiscal_position

View File

@@ -0,0 +1,28 @@
# Copyright 2022 Akretion France (http://www.akretion.com/)
# @author: <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class AccountFiscalPosition(models.Model):
_inherit = "account.fiscal.position"
intrastat_out_invoice_transaction_id = fields.Many2one(
comodel_name="intrastat.transaction",
string="Default Intrastat Transaction For Customer Invoice",
)
intrastat_out_refund_transaction_id = fields.Many2one(
comodel_name="intrastat.transaction",
string="Default Intrastat Transaction for Customer Refunds",
)
intrastat_in_invoice_transaction_id = fields.Many2one(
comodel_name="intrastat.transaction",
string="Default Intrastat Transaction For Supplier Invoices",
)
intrastat_in_refund_transaction_id = fields.Many2one(
comodel_name="intrastat.transaction",
string="Default Intrastat Transaction For Supplier Refunds",
)
# field used to show/hide fields in country-specific modules
company_country_code = fields.Char(related="company_id.country_id.code")

View File

@@ -93,14 +93,6 @@ 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,
@@ -108,7 +100,6 @@ class AccountMove(models.Model):
"transaction_weight": 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
@@ -208,22 +199,10 @@ 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",
help="Country of origin of the product i.e. product " "'made in ____'.",
)
@api.onchange("invoice_line_id")

View File

@@ -4,7 +4,6 @@
# @author Luc de Meyer <info@noviat.com>
import logging
import warnings
from datetime import date
from dateutil.relativedelta import relativedelta
@@ -50,9 +49,8 @@ class IntrastatProductDeclaration(models.Model):
default=lambda self: self.env.company,
)
company_country_code = fields.Char(
compute="_compute_company_country_code",
related="company_id.country_id.code",
string="Company Country Code",
readonly=True,
store=True,
)
state = fields.Selection(
@@ -129,7 +127,7 @@ class IntrastatProductDeclaration(models.Model):
comodel_name="intrastat.product.declaration.line",
inverse_name="parent_id",
string="Intrastat Product Declaration Lines",
states={"done": [("readonly", True)]},
readonly=True,
)
num_decl_lines = fields.Integer(
compute="_compute_numbers",
@@ -148,10 +146,11 @@ class IntrastatProductDeclaration(models.Model):
)
reporting_level = fields.Selection(
selection="_get_reporting_level",
compute="_compute_reporting_level",
readonly=False,
string="Reporting Level",
states={"done": [("readonly", True)]},
)
valid = fields.Boolean(compute="_compute_check_validity", string="Valid")
xml_attachment_id = fields.Many2one("ir.attachment", string="XML Attachment")
xml_attachment_datas = fields.Binary(
related="xml_attachment_id.datas", string="XML Export"
@@ -184,36 +183,33 @@ class IntrastatProductDeclaration(models.Model):
("nihil", _("Nihil")),
]
@api.depends("company_id")
def _compute_company_country_code(self):
for this in self:
if this.company_id:
if not this.company_id.country_id:
raise ValidationError(_("You must set company's country !"))
this.company_country_code = this.company_id.country_id.code.lower()
@api.depends("year", "month")
def _compute_year_month(self):
for this in self:
if this.year and this.month:
this.year_month = "-".join([this.year, this.month])
@api.depends("month")
def _compute_check_validity(self):
"""TO DO: logic based upon computation lines"""
@api.constrains("company_id")
def _check_company_country(self):
for this in self:
this.valid = True
if not this.company_id.country_id:
raise ValidationError(
_("You must set the country on company '%s'.")
% this.company_id.display_name
)
@api.depends("declaration_line_ids.amount_company_currency")
def _compute_numbers(self):
rg_res = self.env['intrastat.product.declaration.line'].read_group(
[('parent_id', 'in', self.ids)],
['parent_id', 'amount_company_currency:sum'],
['parent_id'])
mapped_data = dict(
[(x['parent_id'][0],
{'num_decl_lines': x['parent_id_count'], 'total_amount': x['amount_company_currency']}) for x in rg_res])
for this in self:
total_amount = 0 # it is an integer
num_lines = 0
for line in this.declaration_line_ids:
total_amount += line.amount_company_currency
num_lines += 1
this.num_decl_lines = num_lines
this.total_amount = total_amount
this.num_decl_lines = mapped_data.get(this.id, {}).get('num_decl_lines', 0)
this.total_amount = mapped_data.get(this.id, {}).get('total_amount', 0)
@api.constrains("year")
def _check_year(self):
@@ -221,20 +217,23 @@ class IntrastatProductDeclaration(models.Model):
if len(this.year) != 4 or this.year[0] != "2":
raise ValidationError(_("Invalid Year!"))
@api.onchange("declaration_type")
def _onchange_declaration_type(self):
if self.declaration_type == "arrivals":
self.reporting_level = (
self.company_id.intrastat_arrivals == "extended"
and "extended"
or "standard"
)
if self.declaration_type == "dispatches":
self.reporting_level = (
self.company_id.intrastat_dispatches == "extended"
and "extended"
or "standard"
)
@api.depends("declaration_type", "company_id")
def _compute_reporting_level(self):
for this in self:
reporting_level = False
if this.declaration_type == "arrivals":
reporting_level = (
this.company_id.intrastat_arrivals == "extended"
and "extended"
or "standard"
)
elif this.declaration_type == "dispatches":
reporting_level = (
this.company_id.intrastat_dispatches == "extended"
and "extended"
or "standard"
)
this.reporting_level = reporting_level
def copy(self, default=None):
self.ensure_one()
@@ -263,12 +262,6 @@ class IntrastatProductDeclaration(models.Model):
)
return attach.id
def _unlink_attachments(self):
atts = self.env["ir.attachment"].search(
[("res_model", "=", self._name), ("res_id", "=", self.id)]
)
atts.unlink()
def unlink(self):
for this in self:
if this.state == "done":
@@ -280,7 +273,7 @@ class IntrastatProductDeclaration(models.Model):
def _get_partner_country(self, inv_line, notedict, eu_countries):
inv = inv_line.move_id
country = inv.src_dest_country_id or inv.partner_id.country_id
country = inv.src_dest_country_id
if not country:
line_notes = [
_(
@@ -305,70 +298,42 @@ class IntrastatProductDeclaration(models.Model):
% (inv.name, country.name)
]
self._format_line_note(inv_line, notedict, line_notes)
if country and country.code == "GB" and self.year >= "2021":
vat = inv.commercial_partner_id.vat
if not vat:
line_notes = [
_(
"On invoice '%s', the source/destination country "
"is United-Kingdom and the fiscal position is '%s'. "
"Make sure that the fiscal position is right. If "
"the origin/destination is Northern Ireland, please "
"set the VAT number of the partner '%s' in Odoo with "
"its new VAT number starting with 'XI' following Brexit."
)
% (
inv.name,
inv.fiscal_position_id.display_name,
inv.commercial_partner_id.display_name,
)
]
self._format_line_note(inv_line, notedict, line_notes)
elif not vat.startswith("XI"):
line_notes = [
_(
"On invoice '%s', the source/destination country "
"is United-Kingdom, the fiscal position is '%s' and "
"the partner's VAT number is '%s'. "
"Make sure that the fiscal position is right. If "
"the origin/destination is Northern Ireland, please "
"update the VAT number of the partner '%s' in Odoo with "
"its new VAT number starting with 'XI' following Brexit."
)
% (
inv.name,
inv.fiscal_position_id.display_name,
vat,
inv.commercial_partner_id.display_name,
)
]
self._format_line_note(inv_line, notedict, line_notes)
return country
def _get_intrastat_transaction(self, inv_line, notedict):
invoice = inv_line.move_id
if invoice.intrastat_transaction_id:
return invoice.intrastat_transaction_id
else:
company = invoice.company_id
transaction = invoice.intrastat_transaction_id
if not transaction:
# as we have searched with intrastat_fiscal_position = True
# we should always have a fiscal position on the invoice
fp = invoice.fiscal_position_id
if invoice.move_type == "out_invoice":
return company.intrastat_transaction_out_invoice
transaction = fp.intrastat_out_invoice_transaction_id
elif invoice.move_type == "out_refund":
return company.intrastat_transaction_out_refund
transaction = fp.intrastat_out_refund_transaction_id
elif invoice.move_type == "in_invoice":
return company.intrastat_transaction_in_invoice
transaction = fp.intrastat_in_invoice_transaction_id
elif invoice.move_type == "in_refund":
return company.intrastat_transaction_in_refund
transaction = fp.intrastat_in_refund_transaction_id
if not transaction:
line_notes = [
_(
"No Intrastat Transaction Type on invoice '%s', "
"nor on the fiscal position of the invoice (%s)."
)
% (invoice.name, invoice.fiscal_position_id.display_name)
]
self._format_line_note(inv_line, notedict, line_notes)
return transaction
def _get_weight_and_supplunits(self, inv_line, hs_code, notedict):
line_qty = inv_line.quantity
product = inv_line.product_id
intrastat_unit_id = hs_code.intrastat_unit_id
source_uom = inv_line.product_uom_id
weight_uom_categ = self._get_uom_refs("weight_uom_categ")
kg_uom = self._get_uom_refs("kg_uom")
pce_uom_categ = self._get_uom_refs("pce_uom_categ")
pce_uom = self._get_uom_refs("pce_uom")
weight_uom_categ = self.env.ref("uom.product_uom_categ_kgm")
kg_uom = self.env.ref("uom.product_uom_kgm")
self.env["decimal.precision"].precision_get("Stock Weight")
weight = suppl_unit_qty = 0.0
if not source_uom:
@@ -402,40 +367,35 @@ class IntrastatProductDeclaration(models.Model):
self._format_line_note(inv_line, notedict, line_notes)
return weight, suppl_unit_qty
if weight:
return weight, suppl_unit_qty
if source_uom == kg_uom:
weight = line_qty
elif source_uom.category_id == weight_uom_categ:
weight = source_uom._compute_quantity(line_qty, kg_uom)
elif source_uom.category_id == pce_uom_categ:
if not product.weight: # re-create weight_net ?
line_notes = [_("Missing weight on product %s.") % product.display_name]
self._format_line_note(inv_line, notedict, line_notes)
return weight, suppl_unit_qty
if source_uom == pce_uom:
weight = product.weight * line_qty # product.weight_net
else:
# Here, I suppose that, on the product, the
# weight is per PCE and not per uom_id
# product.weight_net
weight = product.weight * source_uom._compute_quantity(
line_qty, pce_uom
)
elif source_uom.category_id == product.uom_id.category_id:
# We suppose that, on product.template,
# the 'weight' field is per uom_id
weight = product.weight * source_uom._compute_quantity(
line_qty, product.uom_id
)
else:
line_notes = [
_(
"Conversion from unit of measure '%s' to 'Kg' "
"is not implemented yet. It is needed for product '%s'."
"cannot be done automatically. It is needed for product "
"'%s' whose unit of measure is %s."
)
% (source_uom.name, product.display_name)
% (source_uom.name, product.display_name, product.uom_id.display_name)
]
self._format_line_note(inv_line, notedict, line_notes)
return weight, suppl_unit_qty
return weight, suppl_unit_qty
def _get_region_code(self, inv_line, notedict):
"""May be inherited by localisation modules
If set, Odoo will use the region code returned by this method
and will not call _get_region() and leave region_id empty
"""
return False
def _get_region(self, inv_line, notedict):
"""
For supplier invoices/refunds: if the invoice line is linked
@@ -502,35 +462,22 @@ 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
origin_country = inv_line.product_id.origin_country_id
if not origin_country:
line_notes = [
_("The country of origin is missing on product '%s'.")
% inv_line.product_id.display_name
]
self._format_line_note(inv_line, notedict, line_notes)
return origin_country
def _get_vat(self, inv_line, notedict):
vat = False
inv = inv_line.move_id
if self.declaration_type == "dispatches":
if (
self.declaration_type == "dispatches"
and inv_line.move_id.fiscal_position_id.vat_required
):
vat = inv.commercial_partner_id.vat
if vat:
if vat.startswith("GB"):
@@ -619,12 +566,11 @@ class IntrastatProductDeclaration(models.Model):
("state", "=", "posted"),
("intrastat_fiscal_position", "=", True),
("company_id", "=", self.company_id.id),
(
"move_type",
"in",
("out_invoice", "out_refund", "in_invoice", "in_refund"),
),
]
if self.declaration_type == "arrivals":
domain.append(("move_type", "in", ("in_invoice", "in_refund")))
elif self.declaration_type == "dispatches":
domain.append(("move_type", "in", ("out_invoice", "out_refund")))
return domain
def _is_product(self, invoice_line):
@@ -649,7 +595,6 @@ class IntrastatProductDeclaration(models.Model):
notedict["note"] += note
def _gather_invoices(self, notedict):
lines = []
qty_prec = self.env["decimal.precision"].precision_get(
"Product Unit of Measure"
@@ -704,10 +649,13 @@ class IntrastatProductDeclaration(models.Model):
)
# When the country is the same as the company's country must be skipped.
if partner_country == self.company_id.country_id:
_logger.info(
"Skipping invoice line %s qty %s "
"of invoice %s. Reason: partner_country = "
"company country"
% (inv_line.name, inv_line.quantity, invoice.name)
)
continue
partner_country_code = (
invoice.commercial_partner_id._get_intrastat_country_code()
)
if inv_intrastat_line:
hs_code = inv_intrastat_line.hs_code_id
@@ -749,16 +697,15 @@ 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 = inv_line.product_id.origin_country_id
product_origin_country_code = self._get_product_origin_country_code(
inv_line, product_origin_country, notedict
product_origin_country = self._get_product_origin_country(
inv_line, notedict
)
region = self._get_region(inv_line, notedict)
region_code = self._get_region_code(inv_line, notedict)
region = False
if not region_code:
region = self._get_region(inv_line, notedict)
vat = self._get_vat(inv_line, notedict)
@@ -766,7 +713,6 @@ 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,
@@ -775,7 +721,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_code": region_code,
"region_id": region and region.id or False,
"vat": vat,
}
@@ -809,23 +755,16 @@ class IntrastatProductDeclaration(models.Model):
_logger.info(
"Skipping invoice line %s qty %s "
"of invoice %s. Reason: price_subtotal = 0 "
"and accessory costs = 0"
% (inv_line.name, inv_line.quantity, inv_line.move_id.name)
"and accessory costs = 0",
inv_line.name,
inv_line.quantity,
inv_line.move_id.name,
)
continue
lines.append(line_vals)
return lines
def _get_uom_refs(self, ref):
uom_refs = {
"weight_uom_categ": self.env.ref("uom.product_uom_categ_kgm"),
"kg_uom": self.env.ref("uom.product_uom_kgm"),
"pce_uom_categ": self.env.ref("uom.product_uom_categ_unit"),
"pce_uom": self.env.ref("uom.product_uom_unit"),
}
return uom_refs[ref]
def action_gather(self):
self.ensure_one()
self.message_post(body=_("Generate Lines from Invoices"))
@@ -868,8 +807,6 @@ class IntrastatProductDeclaration(models.Model):
"type": "ir.actions.act_window",
}
return True
@api.model
def _group_line_hashcode_fields(self, computation_line):
return {
@@ -878,7 +815,7 @@ class IntrastatProductDeclaration(models.Model):
"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,
"region": computation_line.region_code or False,
"product_origin_country": computation_line.product_origin_country_code,
"vat": computation_line.vat or False,
}
@@ -891,15 +828,13 @@ class IntrastatProductDeclaration(models.Model):
@api.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,
"transport_id": computation_line.transport_id.id,
"region_id": computation_line.region_id.id,
"region_code": computation_line.region_code,
"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,
@@ -932,27 +867,21 @@ class IntrastatProductDeclaration(models.Model):
return vals
def generate_declaration(self):
"""generate declaration lines"""
"""generate declaration lines from computation lines"""
self.ensure_one()
assert self.valid, "Computation lines are not valid"
self.message_post(body=_("Generate Declaration Lines"))
# Delete existing declaration lines
self.declaration_line_ids.unlink()
# Regenerate declaration lines from computation lines
assert not self.declaration_line_ids
dl_group = {}
for cl in self.computation_line_ids:
hashcode = self.group_line_hashcode(cl)
if hashcode in dl_group:
dl_group[hashcode].append(cl)
if hashcode not in dl_group:
dl_group[hashcode] = cl
else:
dl_group[hashcode] = [cl]
dl_group[hashcode] |= cl
ipdl = self.declaration_line_ids
for cl_lines in list(dl_group.values()):
for cl_lines in dl_group.values():
vals = self._prepare_declaration_line(cl_lines)
declaration_line = ipdl.create(vals)
for cl in cl_lines:
cl.write({"declaration_line_id": declaration_line.id})
return True
cl_lines.write({"declaration_line_id": declaration_line.id})
def _check_generate_xml(self):
self.ensure_one()
@@ -975,7 +904,6 @@ class IntrastatProductDeclaration(models.Model):
)
self.message_post(body=_("Generate XML Declaration File"))
self._check_generate_xml()
self._unlink_attachments()
xml_bytes = self._generate_xml()
if xml_bytes:
attach_id = self._attach_xml_file(
@@ -1010,9 +938,9 @@ class IntrastatProductDeclaration(models.Model):
"""
return [
"product",
"product_origin_country",
"hs_code",
"src_dest_country",
"src_dest_country_code",
"amount_company_currency",
"accessory_cost",
"transaction",
@@ -1020,6 +948,10 @@ class IntrastatProductDeclaration(models.Model):
"suppl_unit_qty",
"suppl_unit",
"transport",
"region",
"region_code",
"product_origin_country",
"product_origin_country_code",
"vat",
"partner_id",
"invoice",
@@ -1029,13 +961,11 @@ class IntrastatProductDeclaration(models.Model):
def _xls_declaration_line_fields(self):
"""
Update list in custom module to add/drop columns or change order
Use same order as tree view by default
"""
return [
"hs_code",
"product_origin_country_code",
"product_origin_country",
"src_dest_country_code",
"src_dest_country",
"amount_company_currency",
"transaction_code",
"transaction",
@@ -1044,6 +974,8 @@ class IntrastatProductDeclaration(models.Model):
"suppl_unit",
"transport_code",
"transport",
"region_code",
"product_origin_country_code",
"vat",
]
@@ -1056,14 +988,15 @@ class IntrastatProductDeclaration(models.Model):
return {}
def done(self):
for decl in self:
decl.generate_declaration()
decl.generate_xml()
self.write({"state": "done"})
def back2draft(self):
for decl in self:
if decl.xml_attachment_id:
raise UserError(
_("Before going back to draft, you must delete the XML export.")
)
decl.delete_xml()
decl.declaration_line_ids.unlink()
self.write({"state": "draft"})
@@ -1081,9 +1014,11 @@ class IntrastatProductComputationLine(models.Model):
company_currency_id = fields.Many2one(
related="company_id.currency_id", string="Company currency"
)
company_country_code = fields.Char(
related="parent_id.company_id.country_id.code", string="Company Country Code"
)
declaration_type = fields.Selection(related="parent_id.declaration_type")
reporting_level = fields.Selection(related="parent_id.reporting_level")
valid = fields.Boolean(compute="_compute_check_validity", string="Valid")
invoice_line_id = fields.Many2one(
"account.move.line", string="Invoice Line", readonly=True
)
@@ -1102,6 +1037,7 @@ class IntrastatProductComputationLine(models.Model):
help="Country of Origin/Destination",
)
src_dest_country_code = fields.Char(
compute="_compute_src_dest_country_code",
string="Country Code",
required=True,
readonly=False,
@@ -1142,25 +1078,26 @@ class IntrastatProductComputationLine(models.Model):
"at the pro-rata of the amount of each invoice line.",
)
transaction_id = fields.Many2one(
"intrastat.transaction", string="Intrastat Transaction"
"intrastat.transaction",
string="Intrastat Transaction",
)
region_id = fields.Many2one("intrastat.region", string="Intrastat Region")
# product_origin_country_id is replaced by product_origin_country_code
# this field should be dropped once the localisation modules have been
# adapted accordingly
# Note that, in l10n_fr_intrastat_product and maybe in other localization modules
# region_id is left empty and Odoo writes directly in region_code
region_code = fields.Char()
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",
compute="_compute_product_origin_country_code",
string="Country Code 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",
readonly=False,
help="2 digit ISO code of the country of origin of the product.\n"
"Specify 'QU' when the country of origin is unknown.\n",
)
vat = fields.Char(string="VAT Number")
@@ -1168,19 +1105,32 @@ class IntrastatProductComputationLine(models.Model):
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" and self.src_dest_country_id:
self.src_dest_country_code = self.env[
"res.partner"
]._get_intrastat_country_code(country=self.src_dest_country_id)
@api.onchange("region_id")
def _region_id_change(self):
if self.region_id:
self.region_code = self.region_id.code
@api.depends("transport_id")
def _compute_check_validity(self):
"""TO DO: logic based upon fields"""
@api.depends("src_dest_country_id")
def _compute_src_dest_country_code(self):
for this in self:
this.valid = True
code = this.src_dest_country_id and this.src_dest_country_id.code or False
if code == "GB":
code = "XI" # Northern Ireland
this.src_dest_country_code = code
@api.depends("product_origin_country_id")
def _compute_product_origin_country_code(self):
for this in self:
code = (
this.product_origin_country_id
and this.product_origin_country_id.code
or False
)
if code == "GB":
code = "XU"
# XU can be used when you don't know if the product
# originate from Great-Britain or from Northern Ireland
this.product_origin_country_code = code
@api.constrains("vat")
def _check_vat(self):
@@ -1188,19 +1138,6 @@ class IntrastatProductComputationLine(models.Model):
if this.vat and not is_valid(this.vat):
raise ValidationError(_("The VAT number '%s' is invalid.") % this.vat)
# TODO: product_id is a readonly related field 'invoice_line_id.product_id'
# so the onchange is non-sense. Either we convert product_id to a regular
# field or we keep it a related field and we remove this onchange
@api.onchange("product_id")
def _onchange_product(self):
self.weight = 0.0
self.suppl_unit_qty = 0.0
if self.product_id:
self.intrastat_code_id = self.product_id.intrastat_id
self.intrastat_unit_id = self.product_id.intrastat_id.intrastat_unit_id
if not self.intrastat_unit_id:
self.weight = self.product_id.weight
class IntrastatProductDeclarationLine(models.Model):
_name = "intrastat.product.declaration.line"
@@ -1216,6 +1153,9 @@ class IntrastatProductDeclarationLine(models.Model):
company_currency_id = fields.Many2one(
related="company_id.currency_id", string="Company currency"
)
company_country_code = fields.Char(
related="parent_id.company_id.country_id.code", string="Company Country Code"
)
declaration_type = fields.Selection(related="parent_id.declaration_type")
reporting_level = fields.Selection(related="parent_id.reporting_level")
computation_line_ids = fields.One2many(
@@ -1224,11 +1164,6 @@ class IntrastatProductDeclarationLine(models.Model):
string="Computation Lines",
readonly=True,
)
src_dest_country_id = fields.Many2one(
"res.country",
string="Country",
help="Country of Origin/Destination",
)
src_dest_country_code = fields.Char(
string="Country Code",
required=True,
@@ -1255,15 +1190,7 @@ class IntrastatProductDeclarationLine(models.Model):
transaction_id = fields.Many2one(
"intrastat.transaction", string="Intrastat Transaction"
)
region_id = fields.Many2one("intrastat.region", string="Intrastat Region")
# 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 ____'",
)
region_code = fields.Char()
product_origin_country_code = fields.Char(
string="Country of Origin of the Product",
size=2,
@@ -1277,17 +1204,3 @@ class IntrastatProductDeclarationLine(models.Model):
# 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" and self.src_dest_country_id:
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):
for this in self:
if this.vat and not is_valid(this.vat):
raise ValidationError(_("The VAT number '%s' is invalid.") % this.vat)

View File

@@ -9,6 +9,7 @@ from odoo import api, fields, models
class IntrastatTransaction(models.Model):
_name = "intrastat.transaction"
_description = "Intrastat Transaction"
_rec_name = "code"
_order = "code"
_sql_constraints = [
(

View File

@@ -35,22 +35,6 @@ class ResCompany(models.Model):
intrastat_region_id = fields.Many2one(
comodel_name="intrastat.region", string="Default Intrastat Region"
)
intrastat_transaction_out_invoice = fields.Many2one(
comodel_name="intrastat.transaction",
string="Default Intrastat Transaction For Customer Invoice",
)
intrastat_transaction_out_refund = fields.Many2one(
comodel_name="intrastat.transaction",
string="Default Intrastat Transaction for Customer Refunds",
)
intrastat_transaction_in_invoice = fields.Many2one(
comodel_name="intrastat.transaction",
string="Default Intrastat Transaction For Supplier Invoices",
)
intrastat_transaction_in_refund = fields.Many2one(
comodel_name="intrastat.transaction",
string="Default Intrastat Transaction For Supplier Refunds",
)
intrastat_accessory_costs = fields.Boolean(
string="Include Accessory Costs in Fiscal Value of Product"
)

View File

@@ -21,18 +21,6 @@ class ResConfigSettings(models.TransientModel):
intrastat_region_id = fields.Many2one(
related="company_id.intrastat_region_id", readonly=False
)
intrastat_transaction_out_invoice = fields.Many2one(
related="company_id.intrastat_transaction_out_invoice", readonly=False
)
intrastat_transaction_out_refund = fields.Many2one(
related="company_id.intrastat_transaction_out_refund", readonly=False
)
intrastat_transaction_in_invoice = fields.Many2one(
related="company_id.intrastat_transaction_in_invoice", readonly=False
)
intrastat_transaction_in_refund = fields.Many2one(
related="company_id.intrastat_transaction_in_refund", readonly=False
)
intrastat_accessory_costs = fields.Boolean(
related="company_id.intrastat_accessory_costs", readonly=False
)

View File

@@ -45,9 +45,9 @@ class IntrastatProductDeclarationXlsx(models.AbstractModel):
"header": {"type": "string", "value": self._("Product C/O Code")},
"line": {
"type": "string",
"value": self._render("line.product_origin_country_code"),
"value": self._render("line.product_origin_country_code or ''"),
},
"width": 28,
"width": 10,
},
"product_origin_country": {
"header": {"type": "string", "value": self._("Product C/O")},
@@ -68,13 +68,13 @@ class IntrastatProductDeclarationXlsx(models.AbstractModel):
"src_dest_country_code": {
"header": {
"type": "string",
"value": self._("Country of Origin/Destination"),
"value": self._("Country Code of Origin/Destination"),
},
"line": {
"type": "string",
"value": self._render("line.src_dest_country_code"),
},
"width": 28,
"width": 10,
},
"src_dest_country": {
"header": {
@@ -83,7 +83,7 @@ class IntrastatProductDeclarationXlsx(models.AbstractModel):
},
"line": {
"type": "string",
"value": self._render("line.src_dest_country_id.name or ''"),
"value": self._render("line.src_dest_country_id.name"),
},
"width": 28,
},
@@ -121,7 +121,7 @@ class IntrastatProductDeclarationXlsx(models.AbstractModel):
"value": self._("Intrastat Transaction code"),
},
"line": {"value": self._render("line.transaction_id.code")},
"width": 36,
"width": 10,
},
"transaction": {
"header": {"type": "string", "value": self._("Intrastat Transaction")},
@@ -169,7 +169,7 @@ class IntrastatProductDeclarationXlsx(models.AbstractModel):
"transport_code": {
"header": {"type": "string", "value": self._("Transport Mode Code")},
"line": {"value": self._render("line.transport_id.code or ''")},
"width": 14,
"width": 10,
},
"transport": {
"header": {"type": "string", "value": self._("Transport Mode")},
@@ -181,6 +181,11 @@ class IntrastatProductDeclarationXlsx(models.AbstractModel):
"line": {"value": self._render("line.region_id.name or ''")},
"width": 28,
},
"region_code": {
"header": {"type": "string", "value": self._("Intrastat Region Code")},
"line": {"value": self._render("line.region_code or ''")},
"width": 10,
},
"vat": {
"header": {"type": "string", "value": self._("VAT")},
"line": {"value": self._render("line.vat or ''")},

View File

@@ -16,9 +16,9 @@ class IntrastatPurchaseCommon(IntrastatProductCommon):
"declaration_type": "arrivals",
"suppl_unit_qty": line.qty_received,
"hs_code_id": line.product_id.hs_code_id,
"product_origin_country_id": line.product_id.origin_country_id,
"product_origin_country_code": line.product_id.origin_country_id.code,
"amount_company_currency": line.price_subtotal,
"src_dest_country_id": line.partner_id.country_id,
"src_dest_country_code": line.partner_id.country_id.code,
}
def _check_line_values(self, final=False, declaration=None, purchase=None):

View File

@@ -16,7 +16,7 @@ class IntrastatSaleCommon(IntrastatProductCommon):
"declaration_type": "dispatches",
"suppl_unit_qty": line.qty_delivered,
"hs_code_id": line.product_id.hs_code_id,
"product_origin_country_id": line.product_id.origin_country_id,
"product_origin_country_code": line.product_id.origin_country_id.code,
}
def _check_line_values(self, final=False, declaration=None, sale=None):

View File

@@ -17,25 +17,13 @@ class TestIntrastatBrexit(IntrastatProductCommon, SavepointCase):
"local_code": "22083000",
}
)
cls.product_xi = cls.env["product.product"].create(
cls.product_uk = 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,
}
)
@@ -84,9 +72,7 @@ class TestIntrastatBrexit(IntrastatProductCommon, SavepointCase):
)
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
ail.product_id = self.product_uk
inv_in_xi.invoice_date = inv_in_xi.date
inv_in_xi.action_post()
@@ -100,15 +86,11 @@ class TestIntrastatBrexit(IntrastatProductCommon, SavepointCase):
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)
cl_uk = clines.filtered(lambda r: r.product_id == self.product_uk)
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")
dl_uk = dlines.filtered(lambda r: r.computation_line_ids == cl_uk)
self.assertEqual(cl_uk.product_origin_country_code, "XU")
self.assertEqual(dl_uk.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(
@@ -119,8 +101,8 @@ class TestIntrastatBrexit(IntrastatProductCommon, SavepointCase):
)
with Form(inv_in_xi) as inv_form:
with inv_form.invoice_line_ids.new() as ail:
ail.product_id = self.product_xi
ail.product_id = self.product_uk
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")
self.assertEqual(ilines.product_origin_country_id, self.env.ref("base.uk"))

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
Copyright 2022 Akretion France (https://akretion.com/)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<record id="view_account_position_form" model="ir.ui.view">
<field name="name">intrastat_product.account.fiscal.position.form</field>
<field name="model">account.fiscal.position</field>
<field name="inherit_id" ref="intrastat_base.view_account_position_form" />
<field name="arch" type="xml">
<notebook position="inside">
<page
name="intrastat"
string="Intrastat"
attrs="{'invisible': [('intrastat', '=', False)]}"
>
<group
name="intrastat_transactions"
string="Default Intrastat Transactions"
>
<field
name="intrastat_out_invoice_transaction_id"
string="For Customer Invoices"
/>
<field
name="intrastat_out_refund_transaction_id"
string="For Customer Refunds"
/>
<field
name="intrastat_in_invoice_transaction_id"
string="For Supplier Invoices"
/>
<field
name="intrastat_in_refund_transaction_id"
string="For Supplier Refunds"
/>
<field name="company_country_code" invisible="1" />
</group>
</page>
</notebook>
</field>
</record>
</odoo>

View File

@@ -47,7 +47,7 @@
<field name="transaction_suppl_unit_qty" />
<field name="hs_code_id" />
<field name="transaction_weight" />
<field name="product_origin_country_code" />
<field name="product_origin_country_id" />
</tree>
</field>
</page>

View File

@@ -4,7 +4,7 @@
<field name="name">intrastat.product.declaration.form</field>
<field name="model">intrastat.product.declaration</field>
<field name="arch" type="xml">
<form string="Intrastat Product Declaration">
<form>
<header>
<button
name="action_gather"
@@ -13,41 +13,24 @@
string="Generate Lines from Invoices"
class="btn-primary"
/>
<button
name="generate_declaration"
type="object"
attrs="{'invisible': ['|', ('state', '!=', 'draft'), ('action', '=', 'nihil')]}"
string="Generate Declaration Lines"
/>
<button
name="generate_xml"
string="Generate XML Declaration File"
type="object"
attrs="{'invisible': [('xml_attachment_id', '!=', False)]}"
invisible="context.get('generic_intrastat_product_declaration')"
/>
<button
name="delete_xml"
string="Delete XML Export"
type="object"
attrs="{'invisible': [('xml_attachment_id', '=', False)]}"
/>
<button
name="done"
string="Done"
string="Confirm"
type="object"
class="btn-primary"
states="draft"
help="Generate declaration lines, generate XML export and set declaration to 'Done'"
/>
<button
name="back2draft"
string="Back to Draft"
type="object"
states="done"
confirm="Are you sure you want to go back to draft?"
/>
<field name="state" widget="statusbar" />
</header>
<sheet string="Intrastat Product Declaration">
<sheet>
<div class="oe_title">
<h1>
<span>Intrastat Product Declaration </span>
@@ -59,6 +42,7 @@
<field name="year" />
<field name="month" />
<field name="declaration_type" />
<field name="reporting_level" />
<field
name="xml_attachment_datas"
filename="xml_attachment_name"
@@ -66,7 +50,6 @@
/>
<field name="xml_attachment_name" invisible="1" />
<field name="xml_attachment_id" invisible="1" />
<field name="reporting_level" invisible="1" />
</group>
<group name="properties-2">
<field name="action" />
@@ -86,7 +69,7 @@
</group>
</group>
<notebook>
<page string="Transactions">
<page string="Transactions" name="computation_lines">
<button
name="create_xls"
type="object"
@@ -99,7 +82,7 @@
nolabel="1"
/>
</page>
<page string="Declaration Lines">
<page string="Declaration Lines" name="declaration_lines">
<button
name="create_xls"
type="object"
@@ -112,7 +95,7 @@
nolabel="1"
/>
</page>
<page string="Notes">
<page string="Notes" name="note">
<field name="note" />
</page>
</notebook>
@@ -129,18 +112,20 @@
<field name="name">intrastat.product.declaration.tree</field>
<field name="model">intrastat.product.declaration</field>
<field name="arch" type="xml">
<tree string="Intrastat Product Declarations">
<tree>
<field name="year_month" decoration-bf="1" />
<field name="revision" />
<field
name="declaration_type"
widget="badge"
decoration-danger="declaration_type == 'arrivals'"
decoration-warning="declaration_type == 'dispatches'"
/>
<field name="num_decl_lines" />
<field name="total_amount" sum="Total amount" />
<field name="currency_id" />
<field name="reporting_level" optional="hide" />
<field name="action" optional="hide" />
<field name="revision" optional="hide" />
<field name="num_decl_lines" optional="show" />
<field name="total_amount" sum="1" optional="show" />
<field name="currency_id" optional="show" />
<field
name="state"
decoration-success="state == 'done'"
@@ -154,7 +139,7 @@
<field name="name">intrastat.product.declaration.search</field>
<field name="model">intrastat.product.declaration</field>
<field name="arch" type="xml">
<search string="Search Intrastat Product Declarations">
<search>
<field name="year_month" />
<filter
name="arrivals"
@@ -192,7 +177,7 @@
<field name="name">intrastat.product.declaration.graph</field>
<field name="model">intrastat.product.declaration</field>
<field name="arch" type="xml">
<graph string="Intrastat Product" type="bar" stacked="False">
<graph type="bar" stacked="False">
<field name="year_month" type="row" />
<field name="declaration_type" type="row" />
<field name="total_amount" type="measure" />
@@ -203,7 +188,7 @@
<field name="name">intrastat.product.declaration.pivot</field>
<field name="model">intrastat.product.declaration</field>
<field name="arch" type="xml">
<pivot string="Intrastat Product">
<pivot>
<field name="year_month" type="row" />
<field name="declaration_type" type="col" />
<field name="total_amount" type="measure" />
@@ -215,16 +200,28 @@
<field name="name">intrastat.product.computation.line.form</field>
<field name="model">intrastat.product.computation.line</field>
<field name="arch" type="xml">
<form string="Intrastat Transaction">
<form>
<group string="Transaction" name="transaction">
<field
name="parent_id"
invisible="not context.get('intrastat_product_computation_line_main_view')"
/>
<field name="declaration_type" invisible="1" />
<field name="reporting_level" invisible="1" />
<field name="company_country_code" invisible="1" />
<field name="product_id" />
<field name="hs_code_id" />
<field name="src_dest_country_id" />
<field name="src_dest_country_code" />
<field
name="hs_code_id"
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<field
name="src_dest_country_id"
attrs="{'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<field
name="src_dest_country_code"
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<field
name="amount_company_currency"
widget="monetary"
@@ -236,26 +233,45 @@
options="{'currency_field': 'company_currency_id'}"
/>
<field name="company_currency_id" invisible="1" />
<field name="transaction_id" />
<label for="weight" />
<div name="weight">
<field name="transaction_id" required="1" />
<label
for="weight"
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<div
name="weight"
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"
>
<field name="weight" class="oe_inline" /> Kg
</div>
<field name="suppl_unit_qty" />
<field name="intrastat_unit_id" />
<field name="declaration_type" invisible="1" />
<field name="reporting_level" invisible="1" />
<field
name="suppl_unit_qty"
attrs="{'required': [('reporting_level', '=', 'extended'), ('intrastat_unit_id', '!=', False)], 'invisible': ['|', ('reporting_level', '!=', 'extended'), ('intrastat_unit_id', '=', False)]}"
/>
<field
name="intrastat_unit_id"
attrs="{'invisible': ['|', ('reporting_level', '!=', 'extended'), ('intrastat_unit_id', '=', False)]}"
/>
<field
name="transport_id"
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<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="region_id"
attrs="{'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<field
name="region_code"
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<field
name="product_origin_country_id"
attrs="{'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<field
name="product_origin_country_code"
attrs="{'invisible': [('declaration_type', '!=', 'arrivals')]}"
attrs="{'invisible': [('reporting_level', '!=', 'extended')], 'required': [('reporting_level', '=', 'extended')]}"
/>
<field name="vat" />
<field name="partner_id" />
@@ -271,44 +287,77 @@
<field name="name">intrastat.product.computation.line.tree</field>
<field name="model">intrastat.product.computation.line</field>
<field name="arch" type="xml">
<tree string="Transactions">
<tree>
<field
name="parent_id"
invisible="not context.get('intrastat_product_computation_line_main_view')"
/>
<field name="product_id" />
<field name="hs_code_id" />
<field name="src_dest_country_id" />
<field name="src_dest_country_code" />
<field name="declaration_type" invisible="1" />
<field name="reporting_level" invisible="1" />
<field name="company_country_code" invisible="1" />
<field name="product_id" optional="show" />
<field
name="hs_code_id"
optional="show"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
/>
<field
name="src_dest_country_id"
optional="hide"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
/>
<field
name="src_dest_country_code"
optional="show"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
/>
<field name="amount_company_currency" />
<field name="amount_accessory_cost_company_currency" />
<field name="amount_accessory_cost_company_currency" optional="show" />
<field name="transaction_id" />
<field name="weight" />
<field
name="weight"
optional="show"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
/>
<field
name="suppl_unit_qty"
attrs="{'invisible': [('intrastat_unit_id', '=', False)], 'required': [('intrastat_unit_id', '!=', False)]}"
optional="show"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')], 'invisible': [('intrastat_unit_id', '=', False)]}"
/>
<field
name="intrastat_unit_id"
optional="show"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
/>
<field name="intrastat_unit_id" />
<field
name="transport_id"
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"
optional="show"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
/>
<field
name="region_id"
optional="hide"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
/>
<field
name="region_code"
optional="show"
attrs="{'column_invisible': [('parent.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"
optional="hide"
string="Product C/O"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
/>
<field
name="product_origin_country_code"
attrs="{'column_invisible': [('parent.declaration_type', '=', 'arrivals')]}"
optional="show"
string="Product C/O"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
/>
<field name="vat" />
<field name="invoice_id" />
<field name="declaration_type" invisible="1" />
<field name="reporting_level" invisible="1" />
<field name="vat" optional="show" />
<field name="invoice_id" optional="show" />
</tree>
</field>
</record>
@@ -316,15 +365,23 @@
<field name="name">intrastat.product.declaration.line.form</field>
<field name="model">intrastat.product.declaration.line</field>
<field name="arch" type="xml">
<form string="Intrastat Declaration Line">
<form>
<group name="declaration">
<field
name="parent_id"
invisible="not context.get('intrastat_product_declaration_line_main_view')"
/>
<field name="hs_code_id" />
<field name="src_dest_country_id" />
<field name="src_dest_country_code" />
<field name="declaration_type" invisible="1" />
<field name="reporting_level" invisible="1" />
<field name="company_country_code" invisible="1" />
<field
name="hs_code_id"
attrs="{'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<field
name="src_dest_country_code"
attrs="{'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<field
name="amount_company_currency"
widget="monetary"
@@ -332,25 +389,36 @@
/>
<field name="company_currency_id" invisible="1" />
<field name="transaction_id" />
<label for="weight" />
<div name="weight">
<label
for="weight"
attrs="{'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<div
name="weight"
attrs="{'invisible': [('reporting_level', '!=', 'extended')]}"
>
<field name="weight" class="oe_inline" /> Kg
</div>
<field name="suppl_unit_qty" />
<field name="intrastat_unit_id" />
<field name="declaration_type" invisible="1" />
<field name="reporting_level" invisible="1" />
<field
name="suppl_unit_qty"
attrs="{'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<field
name="intrastat_unit_id"
attrs="{'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<field
name="transport_id"
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"
attrs="{'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<field
name="region_code"
attrs="{'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<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': [('declaration_type', '!=', 'arrivals')]}"
attrs="{'invisible': [('reporting_level', '!=', 'extended')]}"
/>
<field name="vat" />
</group>
@@ -364,37 +432,57 @@
<field name="name">intrastat.product.declaration.line.tree</field>
<field name="model">intrastat.product.declaration.line</field>
<field name="arch" type="xml">
<tree string="Intrastat Declaration Lines">
<tree>
<field
name="parent_id"
invisible="not context.get('intrastat_product_declaration_line_main_view')"
/>
<field name="hs_code_id" />
<field name="src_dest_country_id" invisible="1" />
<field name="src_dest_country_code" />
<field name="amount_company_currency" />
<field name="transaction_id" />
<field name="weight" />
<field name="suppl_unit_qty" />
<field name="intrastat_unit_id" />
<field name="declaration_type" invisible="1" />
<field name="reporting_level" invisible="1" />
<field name="company_country_code" invisible="1" />
<field
name="hs_code_id"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
optional="show"
/>
<field
name="src_dest_country_code"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
optional="show"
/>
<field name="amount_company_currency" />
<field name="transaction_id" />
<field
name="weight"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
optional="show"
/>
<field
name="suppl_unit_qty"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
optional="show"
/>
<field
name="intrastat_unit_id"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
optional="show"
/>
<field
name="transport_id"
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
optional="show"
/>
<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"
name="region_code"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
optional="show"
/>
<field name="incoterm_id" invisible="1" />
<field
name="product_origin_country_code"
attrs="{'column_invisible': [('parent.declaration_type', '=', 'arrivals')]}"
attrs="{'column_invisible': [('parent.reporting_level', '!=', 'extended')]}"
string="Product C/O"
optional="show"
/>
<field name="vat" />
</tree>

View File

@@ -32,37 +32,6 @@
<label for="intrastat_transport_id" class="col-md-5" />
<field name="intrastat_transport_id" />
</div>
<div class="row">
<label
for="intrastat_transaction_out_invoice"
class="col-md-5"
/>
<field name="intrastat_transaction_out_invoice" />
</div>
<div class="row">
<label
for="intrastat_transaction_out_refund"
class="col-md-5"
/>
<field name="intrastat_transaction_out_refund" />
</div>
<div class="row">
<label
for="intrastat_transaction_in_invoice"
class="col-md-5"
/>
<field name="intrastat_transaction_in_invoice" />
</div>
<div
class="row"
attrs="{'invisible': [('country_code', 'in', ['FR'])]}"
>
<label
for="intrastat_transaction_in_refund"
class="col-md-5"
/>
<field name="intrastat_transaction_in_refund" />
</div>
<div
class="row"
attrs="{'invisible': [('country_code', 'not in', ['BE'])]}"