Merge branch '14.0' of github.com:OCA/intrastat-extrastat into 14-intrastat-decl-fix-amount

This commit is contained in:
Luc De Meyer
2021-12-27 19:12:40 +01:00
40 changed files with 882 additions and 356 deletions

View File

@@ -19,8 +19,8 @@ Available addons
----------------
addon | version | maintainers | summary
--- | --- | --- | ---
[intrastat_base](intrastat_base/) | 14.0.2.0.0 | | Base module for Intrastat reporting
[intrastat_product](intrastat_product/) | 14.0.1.4.1 | | Base module for Intrastat Product
[intrastat_base](intrastat_base/) | 14.0.2.1.0 | | Base module for Intrastat reporting
[intrastat_product](intrastat_product/) | 14.0.1.5.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.0.0 | [![alexis-via](https://github.com/alexis-via.png?size=30px)](https://github.com/alexis-via) [![luc-demeyer](https://github.com/luc-demeyer.png?size=30px)](https://github.com/luc-demeyer) | Base module for Product Import/Export reports
[product_harmonized_system_delivery](product_harmonized_system_delivery/) | 14.0.1.1.0 | [![alexis-via](https://github.com/alexis-via.png?size=30px)](https://github.com/alexis-via) [![luc-demeyer](https://github.com/luc-demeyer.png?size=30px)](https://github.com/luc-demeyer) | Hide native hs_code field provided by the delivery module

View File

@@ -76,6 +76,7 @@ Credits
Authors
~~~~~~~
* ACSONE SA/NV
* Akretion
* Noviat
@@ -86,6 +87,7 @@ Contributors
* Luc De Meyer, Noviat <info@noviat.com>
* Kumar Aberer, brain-tec AG <kumar.aberer@braintec-group.com>
* Andrea Stirpe <a.stirpe@onestein.nl>
* Denis Roussel <denis.roussel@acsone.eu>
Maintainers
~~~~~~~~~~~

View File

@@ -5,16 +5,15 @@
{
"name": "Intrastat Reporting Base",
"version": "14.0.2.0.0",
"version": "14.0.2.1.0",
"category": "Intrastat",
"license": "AGPL-3",
"summary": "Base module for Intrastat reporting",
"author": "Akretion,Noviat,Odoo Community Association (OCA)",
"author": "ACSONE SA/NV, Akretion,Noviat,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/intrastat-extrastat",
"depends": ["base_vat", "account"],
"excludes": ["account_intrastat"],
"data": [
"security/ir.model.access.csv",
"views/product_template.xml",
"views/res_partner.xml",
"views/res_config_settings.xml",

View File

@@ -17,11 +17,6 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.3.2\n"
#. module: intrastat_base
#: model:ir.model,name:intrastat_base.model_account_chart_template
msgid "Account Chart Template"
msgstr "Modèle de plan comptable"
#. module: intrastat_base
#: model:ir.model.fields,help:intrastat_base.field_product_product__is_accessory_cost
#: model:ir.model.fields,help:intrastat_base.field_product_template__is_accessory_cost
@@ -34,17 +29,11 @@ msgstr ""
"la DEB et la DES."
#. module: intrastat_base
#: code:addons/intrastat_base/models/intrastat_common.py:0
#, python-format
msgid "Cannot delete the declaration %s because it is in Done state"
#: model:ir.model.fields,help:intrastat_base.field_account_fiscal_position_template__intrastat
msgid ""
"Check this if you want to generate intrastat declarations withthe created "
"fiscal position"
msgstr ""
"Impossible de supprimer la déclaration %s parce qu'elle est à l'état "
"'Terminé'."
#. module: intrastat_base
#: model:ir.model,name:intrastat_base.model_intrastat_common
msgid "Common functions for intrastat reports for products "
msgstr "Fonctions communes pour les rapports intrastat des produits "
#. module: intrastat_base
#: model:ir.model,name:intrastat_base.model_res_company
@@ -57,22 +46,9 @@ msgid "Config Settings"
msgstr "Configuration"
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view__create_uid
msgid "Created by"
msgstr "Créé par"
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view__create_date
msgid "Created on"
msgstr "Créé le"
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_account_chart_template__display_name
#: 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
#: model:ir.model.fields,field_description:intrastat_base.field_account_move__display_name
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_common__display_name
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view__display_name
#: 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
@@ -85,12 +61,9 @@ msgid "Fiscal Position"
msgstr "Position fiscale"
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_account_chart_template__id
#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position__id
#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position_template__id
#: model:ir.model.fields,field_description:intrastat_base.field_account_move__id
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_common__id
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view__id
#: 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
@@ -114,11 +87,6 @@ msgstr "DEB/DES"
msgid "Intrastat Fiscal Position"
msgstr "Position fiscale intrastat"
#. module: intrastat_base
#: model_terms:ir.ui.view,arch_db:intrastat_base.intrastat_result_view_form
msgid "Intrastat Result View"
msgstr "Résultat DEB"
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_product_product__is_accessory_cost
#: model:ir.model.fields,field_description:intrastat_base.field_product_template__is_accessory_cost
@@ -131,28 +99,15 @@ msgid "Journal Entry"
msgstr "Pièce comptable"
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_account_chart_template____last_update
#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position____last_update
#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position_template____last_update
#: model:ir.model.fields,field_description:intrastat_base.field_account_move____last_update
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_common____last_update
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view____last_update
#: 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
msgid "Last Modified on"
msgstr "Dernière modification le"
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view__write_uid
msgid "Last Updated by"
msgstr "Dernière modification par"
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view__write_date
msgid "Last Updated on"
msgstr "Dernière modification le"
#. module: intrastat_base
#: model:ir.model.fields,help:intrastat_base.field_res_company__intrastat_remind_user_ids
#: model:ir.model.fields,help:intrastat_base.field_res_config_settings__intrastat_remind_user_ids
@@ -172,22 +127,6 @@ msgstr "Liste des emails des utilisateurs qui reçoivent le rappel DEB/DES"
msgid "Missing e-mail address on user '%s'."
msgstr "Adresse e-mail manquante pour l'utilisateur '%s'."
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view__note
msgid "Notes"
msgstr "Notes"
#. module: intrastat_base
#: model_terms:ir.ui.view,arch_db:intrastat_base.intrastat_result_view_form
msgid "Ok"
msgstr "Ok"
#. module: intrastat_base
#: model:ir.model,name:intrastat_base.model_intrastat_result_view
msgid "Pop-up to show errors on intrastat report generation"
msgstr ""
"Pop-up qui affiche les erreurs lors de la génération du rapport intrastat"
#. module: intrastat_base
#: model:ir.model,name:intrastat_base.model_product_template
msgid "Product Template"
@@ -216,12 +155,6 @@ msgstr "Frais de port"
msgid "Template for Fiscal Position"
msgstr "Modèle de position fiscale"
#. module: intrastat_base
#: code:addons/intrastat_base/models/intrastat_common.py:0
#, python-format
msgid "The VAT number is not set for the partner '%s'."
msgstr "Numéro de TVA non renseigné sur le partenaire '%s'."
#. module: intrastat_base
#: code:addons/intrastat_base/models/product_template.py:0
#, python-format
@@ -241,7 +174,7 @@ msgid "Units"
msgstr "Unités"
#. module: intrastat_base
#: code:addons/intrastat_base/models/intrastat_common.py:0
#: code:addons/intrastat_base/models/res_company.py:0
#, python-format
msgid "Unknown Error"
msgstr "Erreur inconnue"
@@ -252,6 +185,45 @@ msgstr "Erreur inconnue"
msgid "Users Receiving the Intrastat Reminder"
msgstr "Utilisateurs qui reçoivent le rappel DEB/DES"
#~ msgid "Account Chart Template"
#~ msgstr "Modèle de plan comptable"
#~ msgid "Cannot delete the declaration %s because it is in Done state"
#~ msgstr ""
#~ "Impossible de supprimer la déclaration %s parce qu'elle est à l'état "
#~ "'Terminé'."
#~ msgid "Common functions for intrastat reports for products "
#~ msgstr "Fonctions communes pour les rapports intrastat des produits "
#~ msgid "Created by"
#~ msgstr "Créé par"
#~ msgid "Created on"
#~ msgstr "Créé le"
#~ msgid "Intrastat Result View"
#~ msgstr "Résultat DEB"
#~ msgid "Last Updated by"
#~ msgstr "Dernière modification par"
#~ msgid "Last Updated on"
#~ msgstr "Dernière modification le"
#~ msgid "Notes"
#~ msgstr "Notes"
#~ msgid "Ok"
#~ msgstr "Ok"
#~ msgid "Pop-up to show errors on intrastat report generation"
#~ msgstr ""
#~ "Pop-up qui affiche les erreurs lors de la génération du rapport intrastat"
#~ msgid "The VAT number is not set for the partner '%s'."
#~ msgstr "Numéro de TVA non renseigné sur le partenaire '%s'."
#~ msgid "Company not yet set on intrastat report."
#~ msgstr "Société non configurée sur le rapport DEB/DES."

View File

@@ -13,11 +13,6 @@ msgstr ""
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: intrastat_base
#: model:ir.model,name:intrastat_base.model_account_chart_template
msgid "Account Chart Template"
msgstr ""
#. module: intrastat_base
#: model:ir.model.fields,help:intrastat_base.field_product_product__is_accessory_cost
#: model:ir.model.fields,help:intrastat_base.field_product_template__is_accessory_cost
@@ -27,14 +22,10 @@ msgid ""
msgstr ""
#. module: intrastat_base
#: code:addons/intrastat_base/models/intrastat_common.py:0
#, python-format
msgid "Cannot delete the declaration %s because it is in Done state"
msgstr ""
#. module: intrastat_base
#: model:ir.model,name:intrastat_base.model_intrastat_common
msgid "Common functions for intrastat reports for products "
#: model:ir.model.fields,help:intrastat_base.field_account_fiscal_position_template__intrastat
msgid ""
"Check this if you want to generate intrastat declarations withthe created "
"fiscal position"
msgstr ""
#. module: intrastat_base
@@ -48,22 +39,9 @@ msgid "Config Settings"
msgstr ""
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view__create_uid
msgid "Created by"
msgstr ""
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view__create_date
msgid "Created on"
msgstr ""
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_account_chart_template__display_name
#: 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
#: model:ir.model.fields,field_description:intrastat_base.field_account_move__display_name
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_common__display_name
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view__display_name
#: 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
@@ -76,12 +54,9 @@ msgid "Fiscal Position"
msgstr ""
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_account_chart_template__id
#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position__id
#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position_template__id
#: model:ir.model.fields,field_description:intrastat_base.field_account_move__id
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_common__id
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view__id
#: 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
@@ -105,11 +80,6 @@ msgstr ""
msgid "Intrastat Fiscal Position"
msgstr ""
#. module: intrastat_base
#: model_terms:ir.ui.view,arch_db:intrastat_base.intrastat_result_view_form
msgid "Intrastat Result View"
msgstr ""
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_product_product__is_accessory_cost
#: model:ir.model.fields,field_description:intrastat_base.field_product_template__is_accessory_cost
@@ -122,28 +92,15 @@ msgid "Journal Entry"
msgstr ""
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_account_chart_template____last_update
#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position____last_update
#: model:ir.model.fields,field_description:intrastat_base.field_account_fiscal_position_template____last_update
#: model:ir.model.fields,field_description:intrastat_base.field_account_move____last_update
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_common____last_update
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view____last_update
#: 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
msgid "Last Modified on"
msgstr ""
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view__write_uid
msgid "Last Updated by"
msgstr ""
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view__write_date
msgid "Last Updated on"
msgstr ""
#. module: intrastat_base
#: model:ir.model.fields,help:intrastat_base.field_res_company__intrastat_remind_user_ids
#: model:ir.model.fields,help:intrastat_base.field_res_config_settings__intrastat_remind_user_ids
@@ -163,21 +120,6 @@ msgstr ""
msgid "Missing e-mail address on user '%s'."
msgstr ""
#. module: intrastat_base
#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view__note
msgid "Notes"
msgstr ""
#. module: intrastat_base
#: model_terms:ir.ui.view,arch_db:intrastat_base.intrastat_result_view_form
msgid "Ok"
msgstr ""
#. module: intrastat_base
#: model:ir.model,name:intrastat_base.model_intrastat_result_view
msgid "Pop-up to show errors on intrastat report generation"
msgstr ""
#. module: intrastat_base
#: model:ir.model,name:intrastat_base.model_product_template
msgid "Product Template"
@@ -204,12 +146,6 @@ msgstr ""
msgid "Template for Fiscal Position"
msgstr ""
#. module: intrastat_base
#: code:addons/intrastat_base/models/intrastat_common.py:0
#, python-format
msgid "The VAT number is not set for the partner '%s'."
msgstr ""
#. module: intrastat_base
#: code:addons/intrastat_base/models/product_template.py:0
#, python-format
@@ -226,7 +162,7 @@ msgid "Units"
msgstr ""
#. module: intrastat_base
#: code:addons/intrastat_base/models/intrastat_common.py:0
#: code:addons/intrastat_base/models/res_company.py:0
#, python-format
msgid "Unknown Error"
msgstr ""

View File

@@ -1,5 +1,5 @@
from . import product_template
from . import res_company
from . import intrastat_common
from . import account_fiscal_position
from . import account_fiscal_position_template
from . import account_move

View File

@@ -0,0 +1,17 @@
# Copyright 2020 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 models
class AccountChartTemplate(models.Model):
_inherit = "account.chart.template"
def _get_fp_vals(self, company, position):
"""
Get fiscal position chart template instrastat value
to create fiscal position
"""
vals = super()._get_fp_vals(company, position)
vals["intrastat"] = position.intrastat
return vals

View File

@@ -13,18 +13,3 @@ class AccountFiscalPosition(models.Model):
help="Set to True if the invoices with this fiscal position should "
"be taken into account for the generation of the intrastat reports.",
)
class AccountFiscalPositionTemplate(models.Model):
_inherit = "account.fiscal.position.template"
intrastat = fields.Boolean(string="Intrastat")
class AccountChartTemplate(models.Model):
_inherit = "account.chart.template"
def _get_fp_vals(self, company, position):
vals = super()._get_fp_vals(company, position)
vals["intrastat"] = position.intrastat
return vals

View File

@@ -0,0 +1,14 @@
# Copyright 2020 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 AccountFiscalPositionTemplate(models.Model):
_inherit = "account.fiscal.position.template"
intrastat = fields.Boolean(
string="Intrastat",
help="Check this if you want to generate intrastat declarations with"
"the created fiscal position",
)

View File

@@ -1,132 +0,0 @@
# Copyright 2010-2020 Akretion (<alexis.delattre@akretion.com>)
# Copyright 2009-2020 Noviat (http://www.noviat.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from io import BytesIO
from sys import exc_info
from traceback import format_exception
from lxml import etree
from odoo import _, api, fields, models, tools
from odoo.exceptions import UserError
logger = logging.getLogger(__name__)
class IntrastatCommon(models.AbstractModel):
_name = "intrastat.common"
_description = "Common functions for intrastat reports for products "
"and services"
# The method _compute_numbers has been removed
# because it was using a loop on lines, which is slow -> we should
# use read_group() instead, but then the code depends on
# the line object, so it can't be factorized here
def _check_generate_xml(self):
for this in self:
if not this.company_id.partner_id.vat:
raise UserError(
_("The VAT number is not set for the partner '%s'.")
% this.company_id.partner_id.name
)
@api.model
def _check_xml_schema(self, xml_bytes, xsd_file):
"""Validate the XML file against the XSD"""
xsd_etree_obj = etree.parse(tools.file_open(xsd_file, mode="rb"))
official_schema = etree.XMLSchema(xsd_etree_obj)
try:
t = etree.parse(BytesIO(xml_bytes))
official_schema.assertValid(t)
except (etree.XMLSchemaParseError, etree.DocumentInvalid) as e:
logger.warning("The XML file is invalid against the XML Schema Definition")
logger.warning(xml_bytes)
logger.warning(e)
usererror = "{}\n\n{}".format(e.__class__.__name__, str(e))
raise UserError(usererror)
except Exception:
error = _("Unknown Error")
tb = "".join(format_exception(*exc_info()))
error += "\n%s" % tb
logger.warning(error)
raise UserError(error)
def _attach_xml_file(self, xml_bytes, declaration_name):
"""Attach the XML file to the report_intrastat_product/service
object"""
self.ensure_one()
filename = "{}_{}.xml".format(self.year_month, declaration_name)
attach = self.env["ir.attachment"].create(
{
"name": filename,
"res_id": self.id,
"res_model": self._name,
"raw": xml_bytes,
}
)
return attach.id
def _unlink_attachments(self):
atts = self.env["ir.attachment"].search(
[("res_model", "=", self._name), ("res_id", "=", self.id)]
)
atts.unlink()
# Method _open_attach_view() removed
# Let's handle attachments like in l10n_fr_intrastat_service v14
# with the field attachment_id on the declaration and the download
# link directly on the form view of the declaration.
def _generate_xml(self):
"""
Inherit this method in the localization module
to generate the INTRASTAT Declaration XML file
Returns:
string with XML data
Call the _check_xml_schema() method
before returning the XML string.
"""
return False
def send_reminder_email(self, mail_template_xmlid):
mail_template = self.env.ref(mail_template_xmlid)
for this in self:
if this.company_id.intrastat_remind_user_ids:
mail_template.send_mail(this.id)
logger.info(
"Intrastat Reminder email has been sent (XMLID: %s)."
% mail_template_xmlid
)
else:
logger.warning(
"The list of users receiving the Intrastat Reminder is "
"empty on company %s" % this.company_id.name
)
return True
def unlink(self):
for intrastat in self:
if intrastat.state == "done":
raise UserError(
_("Cannot delete the declaration %s " "because it is in Done state")
% self.year_month
)
return super().unlink()
class IntrastatResultView(models.TransientModel):
"""
Transient Model to display Intrastat Report results
"""
_name = "intrastat.result.view"
_description = "Pop-up to show errors on intrastat report generation"
note = fields.Text(
string="Notes", readonly=True, default=lambda self: self._context.get("note")
)

View File

@@ -2,8 +2,17 @@
# @author: <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
import logging
from io import BytesIO
from sys import exc_info
from traceback import format_exception
from lxml import etree
from odoo import _, api, fields, models, tools
from odoo.exceptions import UserError, ValidationError
logger = logging.getLogger(__name__)
class ResCompany(models.Model):
@@ -40,3 +49,24 @@ class ResCompany(models.Model):
raise ValidationError(
_("Missing e-mail address on user '%s'.") % (user.name)
)
@api.model
def _intrastat_check_xml_schema(self, xml_bytes, xsd_file):
"""Validate the XML file against the XSD"""
xsd_etree_obj = etree.parse(tools.file_open(xsd_file, mode="rb"))
official_schema = etree.XMLSchema(xsd_etree_obj)
try:
t = etree.parse(BytesIO(xml_bytes))
official_schema.assertValid(t)
except (etree.XMLSchemaParseError, etree.DocumentInvalid) as e:
logger.warning("The XML file is invalid against the XML Schema Definition")
logger.warning(xml_bytes)
logger.warning(e)
usererror = "{}\n\n{}".format(e.__class__.__name__, str(e))
raise UserError(usererror)
except Exception:
error = _("Unknown Error")
tb = "".join(format_exception(*exc_info()))
error += "\n%s" % tb
logger.warning(error)
raise UserError(error)

View File

@@ -2,3 +2,4 @@
* Luc De Meyer, Noviat <info@noviat.com>
* Kumar Aberer, brain-tec AG <kumar.aberer@braintec-group.com>
* Andrea Stirpe <a.stirpe@onestein.nl>
* Denis Roussel <denis.roussel@acsone.eu>

View File

@@ -1,2 +0,0 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_intrastat_result_view,Access on intrastat.result.view,model_intrastat_result_view,account.group_account_user,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_intrastat_result_view Access on intrastat.result.view model_intrastat_result_view account.group_account_user 1 1 1 0

View File

@@ -420,6 +420,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id5">Authors</a></h2>
<ul class="simple">
<li>ACSONE SA/NV</li>
<li>Akretion</li>
<li>Noviat</li>
</ul>
@@ -431,6 +432,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<li>Luc De Meyer, Noviat &lt;<a class="reference external" href="mailto:info&#64;noviat.com">info&#64;noviat.com</a>&gt;</li>
<li>Kumar Aberer, brain-tec AG &lt;<a class="reference external" href="mailto:kumar.aberer&#64;braintec-group.com">kumar.aberer&#64;braintec-group.com</a>&gt;</li>
<li>Andrea Stirpe &lt;<a class="reference external" href="mailto:a.stirpe&#64;onestein.nl">a.stirpe&#64;onestein.nl</a>&gt;</li>
<li>Denis Roussel &lt;<a class="reference external" href="mailto:denis.roussel&#64;acsone.eu">denis.roussel&#64;acsone.eu</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">

View File

@@ -1 +1,2 @@
from . import common
from . import test_all

View File

@@ -0,0 +1,16 @@
# Copyright 2021 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
class IntrastatCommon(object):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
cls.chart_template_obj = cls.env["account.chart.template"]
cls.mail_obj = cls.env["mail.mail"]
cls.demo_user = cls.env.ref("base.user_demo")
cls.demo_company = cls.env.ref("base.main_company")
cls.shipping_cost = cls.env.ref("intrastat_base.shipping_costs_exclude")

View File

@@ -0,0 +1,10 @@
# Copyright 2021 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models
class IntrastatDeclarationTest(models.Model):
_inherit = ["mail.thread", "mail.activity.mixin", "intrastat.common"]
_name = "intrastat.declaration.test"
_description = "Intrastat Declaration Test"

View File

@@ -1,13 +1,30 @@
from odoo.tests.common import TransactionCase
from odoo.exceptions import ValidationError
from .common import IntrastatCommon
class TestIntrastatBase(TransactionCase):
class TestIntrastatBase(IntrastatCommon):
"""Tests for this module"""
@classmethod
def setUpClass(cls):
super().setUpClass()
def test_company(self):
# add 'Demo user' to intrastat_remind_user_ids
demo_user = self.env.ref("base.user_demo")
demo_company = self.env.ref("base.main_company")
demo_company.write({"intrastat_remind_user_ids": [(6, False, [demo_user.id])]})
self.demo_company.write(
{"intrastat_remind_user_ids": [(6, False, [self.demo_user.id])]}
)
# then check if intrastat_email_list contains the email of the user
self.assertEqual(demo_company.intrastat_email_list, demo_user.email)
self.assertEqual(self.demo_company.intrastat_email_list, self.demo_user.email)
def test_no_email(self):
self.demo_user.email = False
with self.assertRaises(ValidationError):
self.demo_company.write(
{"intrastat_remind_user_ids": [(6, False, [self.demo_user.id])]}
)
def test_accessory(self):
with self.assertRaises(ValidationError):
self.shipping_cost.type = "consu"

View File

@@ -18,18 +18,4 @@
parent="account.menu_finance_configuration"
sequence="50"
/>
<record id="intrastat_result_view_form" model="ir.ui.view">
<field name="name">intrastat.result_view_form</field>
<field name="model">intrastat.result.view</field>
<field name="arch" type="xml">
<form string="Intrastat Result View">
<group name="main">
<field name="note" nolabel="1" />
</group>
<footer>
<button string="Ok" class="btn-primary" special="cancel" />
</footer>
</form>
</field>
</record>
</odoo>

View File

@@ -131,6 +131,7 @@ Credits
Authors
~~~~~~~
* ACSONE SA/NV
* brain-tec AG
* Akretion
* Noviat
@@ -140,6 +141,7 @@ Contributors
* Alexis de Lattre, Akretion <alexis.delattre@akretion.com>
* Luc De Meyer, Noviat <info@noviat.com>
* Denis Roussel <denis.roussel@acsone.eu>
* Tecnativa <www.tecnativa.com>:
* João Marques

View File

@@ -1,2 +1,3 @@
from . import models
from . import report
from . import wizards

View File

@@ -7,11 +7,11 @@
{
"name": "Intrastat Product",
"version": "14.0.1.4.1",
"version": "14.0.1.5.0",
"category": "Intrastat",
"license": "AGPL-3",
"summary": "Base module for Intrastat Product",
"author": "brain-tec AG, Akretion, Noviat, Odoo Community Association (OCA)",
"author": "ACSONE SA/NV, brain-tec AG, Akretion, Noviat, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/intrastat-extrastat",
"depends": [
"intrastat_base",
@@ -35,6 +35,7 @@
"views/account_move.xml",
"views/sale_order.xml",
"views/stock_warehouse.xml",
"wizards/intrastat_result_view.xml",
"data/intrastat_transport_mode.xml",
"data/intrastat_unit.xml",
],

View File

@@ -224,6 +224,12 @@ msgstr "Remettre en brouillon"
msgid "Before going back to draft, you must delete the XML export."
msgstr ""
#. module: intrastat_product
#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0
#, python-format
msgid "Cannot delete the declaration %s because it is in Done state."
msgstr ""
#. module: intrastat_product
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region__code
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction__code
@@ -357,6 +363,7 @@ msgstr "Pays d'origine de l'article i.e. article 'made in ____'."
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__create_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__create_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region__create_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view__create_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction__create_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transport_mode__create_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_unit__create_uid
@@ -369,6 +376,7 @@ msgstr "Créé par"
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__create_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__create_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region__create_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view__create_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction__create_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transport_mode__create_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_unit__create_date
@@ -493,6 +501,7 @@ msgstr "Expéditions"
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__display_name
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__display_name
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region__display_name
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view__display_name
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction__display_name
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transport_mode__display_name
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_unit__display_name
@@ -626,6 +635,7 @@ msgstr "Codes S.H."
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__id
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__id
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region__id
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view__id
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction__id
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transport_mode__id
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_unit__id
@@ -777,6 +787,11 @@ msgstr "Région pour la DEB"
msgid "Intrastat Regions"
msgstr "Régions pour la DEB"
#. module: intrastat_product
#: model_terms:ir.ui.view,arch_db:intrastat_product.intrastat_result_view_form
msgid "Intrastat Result View"
msgstr ""
#. module: intrastat_product
#: model:ir.model.fields,field_description:intrastat_product.field_hs_code__intrastat_unit_id
#: model:ir.model.fields,help:intrastat_product.field_intrastat_product_computation_line__intrastat_unit_id
@@ -858,7 +873,7 @@ msgstr "Transactions pour la DEB"
#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0
#, python-format
msgid "Invalid Year!"
msgstr "Année invalide !"
msgstr ""
#. module: intrastat_product
#: model:ir.model,name:intrastat_product.model_stock_location
@@ -920,6 +935,7 @@ msgstr "Kg"
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration____last_update
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line____last_update
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region____last_update
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view____last_update
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction____last_update
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transport_mode____last_update
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_unit____last_update
@@ -938,6 +954,7 @@ msgstr "Dernière Modification le"
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__write_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__write_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region__write_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view__write_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction__write_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transport_mode__write_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_unit__write_uid
@@ -950,6 +967,7 @@ msgstr "Dernière modification par"
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__write_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__write_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region__write_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view__write_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction__write_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transport_mode__write_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_unit__write_date
@@ -1072,6 +1090,7 @@ msgstr "Aucun enregistrement trouvé pour la période sélectionnée !"
#. module: intrastat_product
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__note
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view__note
#: model_terms:ir.ui.view,arch_db:intrastat_product.intrastat_product_declaration_view_form
msgid "Notes"
msgstr "Notes"
@@ -1106,6 +1125,11 @@ msgstr ""
msgid "Number of unread messages"
msgstr "Nombre de messages non plus"
#. module: intrastat_product
#: model_terms:ir.ui.view,arch_db:intrastat_product.intrastat_result_view_form
msgid "Ok"
msgstr ""
#. module: intrastat_product
#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0
#, python-format
@@ -1193,6 +1217,11 @@ msgstr ""
msgid "Period"
msgstr "Période"
#. module: intrastat_product
#: model:ir.model,name:intrastat_product.model_intrastat_result_view
msgid "Pop-up to show errors on intrastat report generation"
msgstr ""
#. module: intrastat_product
#: model:intrastat.transport_mode,name:intrastat_product.intrastat_transport_5
msgid "Post"
@@ -1403,6 +1432,12 @@ msgstr "L'action de la déclaration a été mise à 'néant'."
msgid "The VAT number '%s' is invalid."
msgstr ""
#. module: intrastat_product
#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0
#, python-format
msgid "The VAT number is not set for the partner '%s'."
msgstr ""
#. module: intrastat_product
#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0
#, python-format
@@ -1532,11 +1567,6 @@ msgstr ""
msgid "Unread Messages Counter"
msgstr "Pays pour la DEB"
#. module: intrastat_product
#: model:ir.model.fields,help:intrastat_product.field_intrastat_product_declaration__company_country_code
msgid "Used in views and methods of localization modules."
msgstr "Used in views and methods of localization modules."
#. module: intrastat_product
#: model:ir.model.fields,help:intrastat_product.field_intrastat_product_declaration__revision
msgid "Used to keep track of changes"
@@ -1635,6 +1665,12 @@ msgstr "Vous devez configurer le pays de la société !"
msgid "for period %s"
msgstr ""
#~ msgid "Invalid Year !"
#~ msgstr "Année invalide !"
#~ msgid "Used in views and methods of localization modules."
#~ msgstr "Used in views and methods of localization modules."
#, fuzzy
#~ msgid "Company Country code"
#~ msgstr "Code pays de la société"

View File

@@ -209,6 +209,12 @@ msgstr ""
msgid "Before going back to draft, you must delete the XML export."
msgstr ""
#. module: intrastat_product
#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0
#, python-format
msgid "Cannot delete the declaration %s because it is in Done state."
msgstr ""
#. module: intrastat_product
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region__code
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction__code
@@ -338,6 +344,7 @@ msgstr ""
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__create_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__create_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region__create_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view__create_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction__create_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transport_mode__create_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_unit__create_uid
@@ -350,6 +357,7 @@ msgstr ""
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__create_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__create_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region__create_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view__create_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction__create_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transport_mode__create_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_unit__create_date
@@ -473,6 +481,7 @@ msgstr ""
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__display_name
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__display_name
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region__display_name
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view__display_name
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction__display_name
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transport_mode__display_name
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_unit__display_name
@@ -606,6 +615,7 @@ msgstr ""
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__id
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__id
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region__id
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view__id
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction__id
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transport_mode__id
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_unit__id
@@ -757,6 +767,11 @@ msgstr ""
msgid "Intrastat Regions"
msgstr ""
#. module: intrastat_product
#: model_terms:ir.ui.view,arch_db:intrastat_product.intrastat_result_view_form
msgid "Intrastat Result View"
msgstr ""
#. module: intrastat_product
#: model:ir.model.fields,field_description:intrastat_product.field_hs_code__intrastat_unit_id
#: model:ir.model.fields,help:intrastat_product.field_intrastat_product_computation_line__intrastat_unit_id
@@ -899,6 +914,7 @@ msgstr ""
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration____last_update
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line____last_update
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region____last_update
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view____last_update
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction____last_update
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transport_mode____last_update
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_unit____last_update
@@ -917,6 +933,7 @@ msgstr ""
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__write_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__write_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region__write_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view__write_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction__write_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transport_mode__write_uid
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_unit__write_uid
@@ -929,6 +946,7 @@ msgstr ""
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__write_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__write_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_region__write_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view__write_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transaction__write_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_transport_mode__write_date
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_unit__write_date
@@ -1051,6 +1069,7 @@ msgstr ""
#. module: intrastat_product
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__note
#: model:ir.model.fields,field_description:intrastat_product.field_intrastat_result_view__note
#: model_terms:ir.ui.view,arch_db:intrastat_product.intrastat_product_declaration_view_form
msgid "Notes"
msgstr ""
@@ -1085,6 +1104,11 @@ msgstr ""
msgid "Number of unread messages"
msgstr ""
#. module: intrastat_product
#: model_terms:ir.ui.view,arch_db:intrastat_product.intrastat_result_view_form
msgid "Ok"
msgstr ""
#. module: intrastat_product
#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0
#, python-format
@@ -1167,6 +1191,11 @@ msgstr ""
msgid "Period"
msgstr ""
#. module: intrastat_product
#: model:ir.model,name:intrastat_product.model_intrastat_result_view
msgid "Pop-up to show errors on intrastat report generation"
msgstr ""
#. module: intrastat_product
#: model:intrastat.transport_mode,name:intrastat_product.intrastat_transport_5
msgid "Post"
@@ -1374,6 +1403,12 @@ msgstr ""
msgid "The VAT number '%s' is invalid."
msgstr ""
#. module: intrastat_product
#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0
#, python-format
msgid "The VAT number is not set for the partner '%s'."
msgstr ""
#. module: intrastat_product
#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0
#, python-format
@@ -1496,11 +1531,6 @@ msgstr ""
msgid "Unread Messages Counter"
msgstr ""
#. module: intrastat_product
#: model:ir.model.fields,help:intrastat_product.field_intrastat_product_declaration__company_country_code
msgid "Used in views and methods of localization modules."
msgstr ""
#. module: intrastat_product
#: model:ir.model.fields,help:intrastat_product.field_intrastat_product_declaration__revision
msgid "Used to keep track of changes"

View File

@@ -20,7 +20,7 @@ class IntrastatProductDeclaration(models.Model):
_name = "intrastat.product.declaration"
_description = "Intrastat Product Report Base Object"
_rec_name = "year_month"
_inherit = ["mail.thread", "mail.activity.mixin", "intrastat.common"]
_inherit = ["mail.thread", "mail.activity.mixin"]
_order = "year_month desc, declaration_type, revision"
_sql_constraints = [
(
@@ -46,14 +46,26 @@ class IntrastatProductDeclaration(models.Model):
string="Company",
required=True,
states={"done": [("readonly", True)]},
default=lambda self: self._default_company_id(),
default=lambda self: self.env.company,
)
company_country_code = fields.Char(
compute="_compute_company_country_code",
string="Company Country Code",
readonly=True,
store=True,
help="Used in views and methods of localization modules.",
)
state = fields.Selection(
selection=[("draft", "Draft"), ("done", "Done")],
string="State",
readonly=True,
tracking=True,
copy=False,
default="draft",
help="State of the declaration. When the state is set to 'Done', "
"the parameters become read-only.",
)
note = fields.Text(
string="Notes", help="You can add some comments here if you want."
)
year = fields.Char(
string="Year", required=True, states={"done": [("readonly", True)]}
@@ -133,19 +145,6 @@ class IntrastatProductDeclaration(models.Model):
currency_id = fields.Many2one(
"res.currency", related="company_id.currency_id", string="Currency"
)
state = fields.Selection(
selection=[("draft", "Draft"), ("done", "Done")],
string="State",
readonly=True,
tracking=True,
copy=False,
default="draft",
help="State of the declaration. When the state is set to 'Done', "
"the parameters become read-only.",
)
note = fields.Text(
string="Notes", help="You can add some comments here if you want."
)
reporting_level = fields.Selection(
selection="_get_reporting_level",
string="Reporting Level",
@@ -160,10 +159,6 @@ class IntrastatProductDeclaration(models.Model):
related="xml_attachment_id.name", string="XML Filename"
)
@api.model
def _default_company_id(self):
return self.env.company
@api.model
def _get_declaration_type(self):
res = []
@@ -208,7 +203,6 @@ class IntrastatProductDeclaration(models.Model):
for this in self:
this.valid = True
@api.model
@api.constrains("year")
def _check_year(self):
for this in self:
@@ -242,6 +236,36 @@ class IntrastatProductDeclaration(models.Model):
msg, action.id, _("Go to Accounting Configuration Settings screen")
)
def _attach_xml_file(self, xml_bytes, declaration_name):
"""Attach the XML file to the report_intrastat_product/service
object"""
self.ensure_one()
filename = "{}_{}.xml".format(self.year_month, declaration_name)
attach = self.env["ir.attachment"].create(
{
"name": filename,
"res_id": self.id,
"res_model": self._name,
"raw": xml_bytes,
}
)
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":
raise UserError(
_("Cannot delete the declaration %s because it is in Done state.")
% this.display_name
)
return super().unlink()
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
@@ -784,7 +808,7 @@ class IntrastatProductDeclaration(models.Model):
self.write(vals)
if vals["note"]:
result_view = self.env.ref("intrastat_base.intrastat_result_view_form")
result_view = self.env.ref("intrastat_product.intrastat_result_view_form")
return {
"name": _("Generate lines from invoices: results"),
"view_type": "form",
@@ -881,6 +905,14 @@ class IntrastatProductDeclaration(models.Model):
cl.write({"declaration_line_id": declaration_line.id})
return True
def _check_generate_xml(self):
self.ensure_one()
if not self.company_id.partner_id.vat:
raise UserError(
_("The VAT number is not set for the partner '%s'.")
% self.company_id.partner_id.display_name
)
def generate_xml(self):
""" generate the INTRASTAT Declaration XML file """
self.ensure_one()

View File

@@ -1,5 +1,6 @@
* Alexis de Lattre, Akretion <alexis.delattre@akretion.com>
* Luc De Meyer, Noviat <info@noviat.com>
* Denis Roussel <denis.roussel@acsone.eu>
* Tecnativa <www.tecnativa.com>:
* João Marques

View File

@@ -12,3 +12,4 @@ access_account_move_intrastat_line,Full access on Invoice Intrastat Lines,model_
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
access_intrastat_product_declaration_line,Full access on Intrastat Product Declaration Lines to Accountant,model_intrastat_product_declaration_line,account.group_account_user,1,1,1,1
access_intrastat_result_view,Access on intrastat.result.view,model_intrastat_result_view,account.group_account_user,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
12 access_intrastat_product_declaration Full access on Intrastat Product Declarations to Accountant model_intrastat_product_declaration account.group_account_user 1 1 1 1
13 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
14 access_intrastat_product_declaration_line Full access on Intrastat Product Declaration Lines to Accountant model_intrastat_product_declaration_line account.group_account_user 1 1 1 1
15 access_intrastat_result_view Access on intrastat.result.view model_intrastat_result_view account.group_account_user 1 1 1 0

View File

@@ -469,6 +469,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id7">Authors</a></h2>
<ul class="simple">
<li>ACSONE SA/NV</li>
<li>brain-tec AG</li>
<li>Akretion</li>
<li>Noviat</li>
@@ -481,6 +482,8 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
</li>
<li><p class="first">Luc De Meyer, Noviat &lt;<a class="reference external" href="mailto:info&#64;noviat.com">info&#64;noviat.com</a>&gt;</p>
</li>
<li><p class="first">Denis Roussel &lt;<a class="reference external" href="mailto:denis.roussel&#64;acsone.eu">denis.roussel&#64;acsone.eu</a>&gt;</p>
</li>
<li><p class="first">Tecnativa &lt;www.tecnativa.com&gt;:</p>
<blockquote>
<ul class="simple">

View File

@@ -0,0 +1,7 @@
from . import common
from . import common_purchase
from . import common_sale
from . import test_intrastat_product
from . import test_company
from . import test_purchase_order
from . import test_sale_order

View File

@@ -0,0 +1,114 @@
# Copyright 2021 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.addons.intrastat_base.tests.common import IntrastatCommon
class IntrastatProductCommon(IntrastatCommon):
@classmethod
def _init_products(cls):
# Create category - don't init intrastat values, do it in tests
vals = {
"name": "Robots",
"parent_id": cls.category_saleable.id,
}
cls.categ_robots = cls.category_obj.create(vals)
vals = {
"name": "C3PO",
"categ_id": cls.categ_robots.id,
"origin_country_id": cls.env.ref("base.us").id,
"weight": 300,
# Computer - C3PO is one of them
"hs_code_id": cls.hs_code_computer.id,
}
cls.product_c3po = cls.product_template_obj.create(vals)
@classmethod
def _init_company(cls):
# Default transport for company is Road
cls.demo_company.intrastat_transport_id = cls.transport_road
@classmethod
def _init_fiscal_position(cls):
vals = {
"name": "Intrastat Fiscal Position",
"intrastat": True,
}
cls.position = cls.position_obj.create(vals)
@classmethod
def _init_regions(cls):
# Create Belgium Region
cls._create_region()
vals = {
"code": "DE",
"name": "Germany",
"country_id": cls.env.ref("base.de").id,
"description": "Germany",
}
cls._create_region(vals)
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.region_obj = cls.env["intrastat.region"]
cls.transaction_obj = cls.env["intrastat.transaction"]
cls.transport_mode_obj = cls.env["intrastat.transport_mode"]
cls.partner_obj = cls.env["res.partner"]
cls.category_saleable = cls.env.ref("product.product_category_1")
cls.category_obj = cls.env["product.category"]
cls.product_template_obj = cls.env["product.template"]
cls.declaration_obj = cls.env["intrastat.product.declaration"]
cls.position_obj = cls.env["account.fiscal.position"]
cls.hs_code_computer = cls.env.ref("product_harmonized_system.84715000")
cls.transport_rail = cls.env.ref("intrastat_product.intrastat_transport_2")
cls.transport_road = cls.env.ref("intrastat_product.intrastat_transport_3")
cls._init_regions()
cls._init_company()
cls._init_fiscal_position()
cls._init_products()
@classmethod
def _create_region(cls, vals=None):
values = {
"code": "BE_w",
"country_id": cls.env.ref("base.be").id,
"company_id": cls.env.company.id,
"description": "Belgium Walloon Region",
"name": "Walloon Region",
}
if vals is not None:
values.update(vals)
cls.region = cls.region_obj.create(values)
@classmethod
def _create_transaction(cls, vals=None):
values = {
"code": "11",
"company_id": cls.env.company.id,
"description": "Sale / Purchase",
}
if vals is not None:
values.update(vals)
cls.transaction = cls.transaction_obj.create(values)
@classmethod
def _create_transport_mode(cls, vals=None):
values = {}
if vals is not None:
values.update(vals)
cls.transport_mode = cls.transport_mode_obj.create(values)
@classmethod
def _create_declaration(cls, vals=None):
values = {
"company_id": cls.env.company.id,
"declaration_type": "dispatches",
}
if vals is not None:
values.update(vals)
cls.declaration = cls.declaration_obj.create(values)

View File

@@ -0,0 +1,81 @@
# Copyright 2021 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests import Form
from .common import IntrastatProductCommon
class IntrastatPurchaseCommon(IntrastatProductCommon):
"""
We define common flow:
- Supplier in Germany
"""
def _get_expected_vals(self, line):
return {
"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,
"amount_company_currency": line.price_subtotal,
"src_dest_country_id": line.partner_id.country_id,
}
def _check_line_values(self, final=False, declaration=None, purchase=None):
"""
This method allows to test computation lines and declaration
lines values from original sale order line
"""
if declaration is None:
declaration = self.declaration
if purchase is None:
purchase = self.purchase
for line in purchase.order_line:
expected_vals = self._get_expected_vals(line)
comp_line = declaration.computation_line_ids.filtered(
lambda cline: cline.product_id == line.product_id
)
self.assertTrue(
all(comp_line[key] == val for key, val in expected_vals.items())
)
if final:
decl_line = declaration.declaration_line_ids.filtered(
lambda dline: comp_line in dline.computation_line_ids
)
self.assertTrue(
all(decl_line[key] == val for key, val in expected_vals.items())
)
@classmethod
def _init_supplier(cls, vals=None):
values = {
"name": "DE Supplier",
"country_id": cls.env.ref("base.de").id,
"property_account_position_id": cls.position.id,
}
if vals is not None:
values.update(vals)
cls.supplier = cls.partner_obj.create(values)
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.purchase_obj = cls.env["purchase.order"]
cls.move_obj = cls.env["account.move"]
cls._init_supplier()
@classmethod
def _create_purchase_order(cls, vals=None):
vals = {
"partner_id": cls.supplier.id,
}
purchase_new = cls.purchase_obj.new(vals)
purchase_new.onchange_partner_id()
purchase_vals = purchase_new._convert_to_write(purchase_new._cache)
cls.purchase = cls.purchase_obj.create(purchase_vals)
with Form(cls.purchase) as purchase_form:
with purchase_form.order_line.new() as line:
line.product_id = cls.product_c3po.product_variant_ids[0]
line.product_qty = 3.0
# Price should not be void - if no purchase pricelist
line.price_unit = 150.0

View File

@@ -0,0 +1,76 @@
# Copyright 2021 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests import Form
from .common import IntrastatProductCommon
class IntrastatSaleCommon(IntrastatProductCommon):
"""
We define common flow:
- Customer in Netherlands
"""
def _get_expected_vals(self, line):
return {
"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,
}
def _check_line_values(self, final=False, declaration=None, sale=None):
"""
This method allows to test computation lines and declaration
lines values from original sale order line
"""
if declaration is None:
declaration = self.declaration
if sale is None:
sale = self.sale
for line in sale.order_line:
expected_vals = self._get_expected_vals(line)
comp_line = declaration.computation_line_ids.filtered(
lambda cline: cline.product_id == line.product_id
)
self.assertTrue(
all(comp_line[key] == val for key, val in expected_vals.items())
)
if final:
decl_line = declaration.declaration_line_ids.filtered(
lambda dline: comp_line in dline.computation_line_ids
)
self.assertTrue(
all(decl_line[key] == val for key, val in expected_vals.items())
)
@classmethod
def _init_customer(cls, vals=None):
values = {
"name": "NL Customer",
"country_id": cls.env.ref("base.nl").id,
"property_account_position_id": cls.position.id,
}
if vals is not None:
values.update(vals)
cls.customer = cls.partner_obj.create(values)
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.sale_obj = cls.env["sale.order"]
cls._init_customer()
@classmethod
def _create_sale_order(cls, vals=None):
vals = {
"partner_id": cls.customer.id,
}
sale_new = cls.sale_obj.new(vals)
sale_new.onchange_partner_id()
sale_vals = sale_new._convert_to_write(sale_new._cache)
cls.sale = cls.sale_obj.create(sale_vals)
with Form(cls.sale) as sale_form:
with sale_form.order_line.new() as line:
line.product_id = cls.product_c3po.product_variant_ids[0]
line.product_uom_qty = 3.0

View File

@@ -0,0 +1,40 @@
# Copyright 2021 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests.common import SavepointCase
from .common import IntrastatProductCommon
class TestIntrastatCompany(IntrastatProductCommon):
"""Tests for this module"""
def test_company_values(self):
# Exempt for arrivals and dispatches => exempt
self.demo_company.update(
{
"intrastat_arrivals": "exempt",
"intrastat_dispatches": "exempt",
}
)
self.assertEqual("exempt", self.demo_company.intrastat)
# Extended for arrivals or dispatches => extended
self.demo_company.update(
{
"intrastat_arrivals": "extended",
}
)
self.assertEqual("extended", self.demo_company.intrastat)
# standard for arrivals or dispatches => standard
self.demo_company.update(
{
"intrastat_arrivals": "exempt",
"intrastat_dispatches": "standard",
}
)
self.assertEqual("standard", self.demo_company.intrastat)
class TestIntrastatProductCase(TestIntrastatCompany, SavepointCase):
""" Test Intrastat Product """

View File

@@ -0,0 +1,67 @@
# Copyright 2021 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from psycopg2 import IntegrityError
from odoo.exceptions import UserError, ValidationError
from odoo.tests.common import SavepointCase
from odoo.tools import mute_logger
from .common import IntrastatProductCommon
class TestIntrastatProduct(IntrastatProductCommon):
"""Tests for this module"""
# Test duplicates
@mute_logger("odoo.sql_db")
def test_region(self):
with self.assertRaises(IntegrityError):
self._create_region()
@mute_logger("odoo.sql_db")
def test_transaction(self):
self._create_transaction()
with self.assertRaises(IntegrityError):
self._create_transaction()
@mute_logger("odoo.sql_db")
def test_transport_mode(self):
vals = {"code": 1, "name": "Sea"}
with self.assertRaises(IntegrityError):
self._create_transport_mode(vals)
def test_copy(self):
"""
When copying declaration, the new one has an incremented revision
value.
"""
vals = {"declaration_type": "dispatches"}
self._create_declaration(vals)
decl_copy = self.declaration.copy()
self.assertEqual(self.declaration.revision + 1, decl_copy.revision)
def test_declaration_no_country(self):
self.demo_company.country_id = False
with self.assertRaises(ValidationError):
self._create_declaration()
self.declaration.flush()
def test_declaration_no_vat(self):
self.demo_company.partner_id.vat = False
with self.assertRaises(UserError):
self._create_declaration()
self.declaration.flush()
self.declaration._check_generate_xml()
def test_declaration_state(self):
self._create_declaration()
self.declaration.unlink()
self._create_declaration()
self.declaration.state = "done"
with self.assertRaises(UserError):
self.declaration.unlink()
class TestIntrastatProductCase(TestIntrastatProduct, SavepointCase):
""" Test Intrastat Product """

View File

@@ -0,0 +1,53 @@
# Copyright 2021 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from freezegun import freeze_time
from odoo import fields
from odoo.tests.common import SavepointCase
from .common_purchase import IntrastatPurchaseCommon
class TestIntrastatProductPurchase(IntrastatPurchaseCommon):
"""Tests for this module"""
def test_purchase_to_invoice_default(self):
date_order = "2021-09-01"
declaration_date = "2021-10-01"
with freeze_time(date_order):
self._create_purchase_order()
self.purchase.button_confirm()
self.purchase.picking_ids.action_assign()
for line in self.purchase.picking_ids.move_line_ids:
line.qty_done = line.product_uom_qty
self.purchase.picking_ids._action_done()
self.assertEqual("done", self.purchase.picking_ids.state)
with freeze_time(date_order):
action = self.purchase.action_create_invoice()
invoice_id = action["res_id"]
invoice = self.move_obj.browse(invoice_id)
invoice.invoice_date = fields.Date.from_string(date_order)
invoice.action_post()
# Check if transport mode has been transmitted to invoice
# It should be None as not defined on sale order
self.assertFalse(
invoice.intrastat_transport_id,
)
vals = {
"declaration_type": "arrivals",
}
with freeze_time(declaration_date):
self._create_declaration(vals)
self.declaration.action_gather()
self._check_line_values()
self.declaration.generate_declaration()
self._check_line_values(final=True)
class TestIntrastatProductPurchaseCase(TestIntrastatProductPurchase, SavepointCase):
""" Test Intrastat Purchase """

View File

@@ -0,0 +1,88 @@
# Copyright 2021 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from freezegun import freeze_time
from odoo.tests.common import SavepointCase
from .common_sale import IntrastatSaleCommon
class TestIntrastatProductSale(IntrastatSaleCommon):
"""Tests for this module"""
def test_sale_to_invoice_default(self):
self._create_sale_order()
self.sale.action_confirm()
self.sale.picking_ids.action_assign()
for line in self.sale.picking_ids.move_line_ids:
line.qty_done = line.product_uom_qty
self.sale.picking_ids._action_done()
self.assertEqual("done", self.sale.picking_ids.state)
invoice = self.sale._create_invoices()
invoice.action_post()
# Check if transport mode has been transmitted to invoice
# It should be None as not defined on sale order
self.assertFalse(
invoice.intrastat_transport_id,
)
# Test specific transport set on sale to invoice
def test_sale_to_invoice(self):
self._create_sale_order()
# Set intrastat transport mode to rail
self.sale.intrastat_transport_id = self.transport_rail
self.sale.action_confirm()
self.sale.picking_ids.action_assign()
for line in self.sale.picking_ids.move_line_ids:
line.qty_done = line.product_uom_qty
self.sale.picking_ids._action_done()
self.assertEqual("done", self.sale.picking_ids.state)
invoice = self.sale._create_invoices()
invoice.action_post()
# Check if transport mode has been transmitted to invoice
self.assertEqual(
self.transport_rail,
invoice.intrastat_transport_id,
)
def test_sale_declaration(self):
date_order = "2021-09-01"
declaration_date = "2021-10-01"
with freeze_time(date_order):
self._create_sale_order()
# Set intrastat transport mode to rail
self.sale.intrastat_transport_id = self.transport_rail
self.sale.action_confirm()
self.sale.picking_ids.action_assign()
for line in self.sale.picking_ids.move_line_ids:
line.qty_done = line.product_uom_qty
self.sale.picking_ids._action_done()
self.assertEqual("done", self.sale.picking_ids.state)
with freeze_time(date_order):
invoice = self.sale._create_invoices()
invoice.action_post()
# Check if transport mode has been transmitted to invoice
self.assertEqual(
self.transport_rail,
invoice.intrastat_transport_id,
)
vals = {
"declaration_type": "dispatches",
}
with freeze_time(declaration_date):
self._create_declaration(vals)
self.declaration.action_gather()
self._check_line_values()
self.declaration.generate_declaration()
self._check_line_values(final=True)
class TestIntrastatProductSaleCase(TestIntrastatProductSale, SavepointCase):
""" Test Intrastat Sale """

View File

@@ -0,0 +1 @@
from . import intrastat_result_view

View File

@@ -0,0 +1,14 @@
# Copyright 2010-2021 Akretion (<alexis.delattre@akretion.com>)
# Copyright 2009-2021 Noviat (http://www.noviat.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class IntrastatResultView(models.TransientModel):
_name = "intrastat.result.view"
_description = "Pop-up to show errors on intrastat report generation"
note = fields.Text(
string="Notes", readonly=True, default=lambda self: self._context.get("note")
)

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
Copyright 2011-2021 Akretion France (http://www.akretion.com/)
Copyright 2015-2021 Noviat (http://www.noviat.com/)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<record id="intrastat_result_view_form" model="ir.ui.view">
<field name="name">intrastat.result_view_form</field>
<field name="model">intrastat.result.view</field>
<field name="arch" type="xml">
<form string="Intrastat Result View">
<group name="main">
<field name="note" nolabel="1" />
</group>
<footer>
<button string="Ok" class="btn-primary" special="cancel" />
</footer>
</form>
</field>
</record>
</odoo>

2
test-requirements.txt Normal file
View File

@@ -0,0 +1,2 @@
odoo-test-helper
freezegun