diff --git a/README.md b/README.md index 7d6c6d5..0e55279 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/intrastat_base/README.rst b/intrastat_base/README.rst index 1b56569..ce8660e 100644 --- a/intrastat_base/README.rst +++ b/intrastat_base/README.rst @@ -76,6 +76,7 @@ Credits Authors ~~~~~~~ +* ACSONE SA/NV * Akretion * Noviat @@ -86,6 +87,7 @@ Contributors * Luc De Meyer, Noviat * Kumar Aberer, brain-tec AG * Andrea Stirpe +* Denis Roussel Maintainers ~~~~~~~~~~~ diff --git a/intrastat_base/__manifest__.py b/intrastat_base/__manifest__.py index 031abb3..ee90c53 100644 --- a/intrastat_base/__manifest__.py +++ b/intrastat_base/__manifest__.py @@ -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", diff --git a/intrastat_base/i18n/fr.po b/intrastat_base/i18n/fr.po index b6f72ac..2f7b070 100644 --- a/intrastat_base/i18n/fr.po +++ b/intrastat_base/i18n/fr.po @@ -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." diff --git a/intrastat_base/i18n/intrastat_base.pot b/intrastat_base/i18n/intrastat_base.pot index 6fa9236..73102a2 100644 --- a/intrastat_base/i18n/intrastat_base.pot +++ b/intrastat_base/i18n/intrastat_base.pot @@ -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 "" diff --git a/intrastat_base/models/__init__.py b/intrastat_base/models/__init__.py index eff3d68..cea19b9 100644 --- a/intrastat_base/models/__init__.py +++ b/intrastat_base/models/__init__.py @@ -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 diff --git a/intrastat_base/models/account_chart_template.py b/intrastat_base/models/account_chart_template.py new file mode 100644 index 0000000..939e9e2 --- /dev/null +++ b/intrastat_base/models/account_chart_template.py @@ -0,0 +1,17 @@ +# Copyright 2020 Akretion France (http://www.akretion.com/) +# @author: +# 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 diff --git a/intrastat_base/models/account_fiscal_position.py b/intrastat_base/models/account_fiscal_position.py index fe3ebfb..0c56e59 100644 --- a/intrastat_base/models/account_fiscal_position.py +++ b/intrastat_base/models/account_fiscal_position.py @@ -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 diff --git a/intrastat_base/models/account_fiscal_position_template.py b/intrastat_base/models/account_fiscal_position_template.py new file mode 100644 index 0000000..9085f53 --- /dev/null +++ b/intrastat_base/models/account_fiscal_position_template.py @@ -0,0 +1,14 @@ +# Copyright 2020 Akretion France (http://www.akretion.com/) +# @author: +# 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", + ) diff --git a/intrastat_base/models/intrastat_common.py b/intrastat_base/models/intrastat_common.py deleted file mode 100644 index 94dc5a0..0000000 --- a/intrastat_base/models/intrastat_common.py +++ /dev/null @@ -1,132 +0,0 @@ -# Copyright 2010-2020 Akretion () -# 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") - ) diff --git a/intrastat_base/models/res_company.py b/intrastat_base/models/res_company.py index eefce32..7a2dbc9 100644 --- a/intrastat_base/models/res_company.py +++ b/intrastat_base/models/res_company.py @@ -2,8 +2,17 @@ # @author: # 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) diff --git a/intrastat_base/readme/CONTRIBUTORS.rst b/intrastat_base/readme/CONTRIBUTORS.rst index 6a9e1c1..af9ef52 100644 --- a/intrastat_base/readme/CONTRIBUTORS.rst +++ b/intrastat_base/readme/CONTRIBUTORS.rst @@ -2,3 +2,4 @@ * Luc De Meyer, Noviat * Kumar Aberer, brain-tec AG * Andrea Stirpe +* Denis Roussel diff --git a/intrastat_base/security/ir.model.access.csv b/intrastat_base/security/ir.model.access.csv deleted file mode 100644 index fbe710c..0000000 --- a/intrastat_base/security/ir.model.access.csv +++ /dev/null @@ -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 diff --git a/intrastat_base/static/description/index.html b/intrastat_base/static/description/index.html index 3bd1878..020f0ff 100644 --- a/intrastat_base/static/description/index.html +++ b/intrastat_base/static/description/index.html @@ -420,6 +420,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome

Authors

    +
  • ACSONE SA/NV
  • Akretion
  • Noviat
@@ -431,6 +432,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
  • 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>
  • diff --git a/intrastat_base/tests/__init__.py b/intrastat_base/tests/__init__.py index 7836283..a2afb4b 100644 --- a/intrastat_base/tests/__init__.py +++ b/intrastat_base/tests/__init__.py @@ -1 +1,2 @@ +from . import common from . import test_all diff --git a/intrastat_base/tests/common.py b/intrastat_base/tests/common.py new file mode 100644 index 0000000..ac1fbf3 --- /dev/null +++ b/intrastat_base/tests/common.py @@ -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") diff --git a/intrastat_base/tests/models.py b/intrastat_base/tests/models.py new file mode 100644 index 0000000..302914c --- /dev/null +++ b/intrastat_base/tests/models.py @@ -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" diff --git a/intrastat_base/tests/test_all.py b/intrastat_base/tests/test_all.py index f05fc49..40b414f 100644 --- a/intrastat_base/tests/test_all.py +++ b/intrastat_base/tests/test_all.py @@ -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" diff --git a/intrastat_base/views/intrastat.xml b/intrastat_base/views/intrastat.xml index ca14bae..4784270 100644 --- a/intrastat_base/views/intrastat.xml +++ b/intrastat_base/views/intrastat.xml @@ -18,18 +18,4 @@ parent="account.menu_finance_configuration" sequence="50" /> - - intrastat.result_view_form - intrastat.result.view - -
    - - - -
    -
    -
    -
    -
    diff --git a/intrastat_product/README.rst b/intrastat_product/README.rst index 99de851..ba983e7 100644 --- a/intrastat_product/README.rst +++ b/intrastat_product/README.rst @@ -131,6 +131,7 @@ Credits Authors ~~~~~~~ +* ACSONE SA/NV * brain-tec AG * Akretion * Noviat @@ -140,6 +141,7 @@ Contributors * Alexis de Lattre, Akretion * Luc De Meyer, Noviat +* Denis Roussel * Tecnativa : * João Marques diff --git a/intrastat_product/__init__.py b/intrastat_product/__init__.py index bf588bc..cf6083c 100644 --- a/intrastat_product/__init__.py +++ b/intrastat_product/__init__.py @@ -1,2 +1,3 @@ from . import models from . import report +from . import wizards diff --git a/intrastat_product/__manifest__.py b/intrastat_product/__manifest__.py index ca05a0c..deb8484 100644 --- a/intrastat_product/__manifest__.py +++ b/intrastat_product/__manifest__.py @@ -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", ], diff --git a/intrastat_product/i18n/fr.po b/intrastat_product/i18n/fr.po index d6d6d5e..dbc7d74 100644 --- a/intrastat_product/i18n/fr.po +++ b/intrastat_product/i18n/fr.po @@ -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 @@ -857,8 +872,8 @@ msgstr "Transactions pour la DEB" #. module: intrastat_product #: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 #, python-format -msgid "Invalid Year !" -msgstr "Année invalide !" +msgid "Invalid Year!" +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é" diff --git a/intrastat_product/i18n/intrastat_product.pot b/intrastat_product/i18n/intrastat_product.pot index 9a9e01f..31ec071 100644 --- a/intrastat_product/i18n/intrastat_product.pot +++ b/intrastat_product/i18n/intrastat_product.pot @@ -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 @@ -836,7 +851,7 @@ msgstr "" #. module: intrastat_product #: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 #, python-format -msgid "Invalid Year !" +msgid "Invalid Year!" msgstr "" #. module: intrastat_product @@ -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" diff --git a/intrastat_product/models/intrastat_product_declaration.py b/intrastat_product/models/intrastat_product_declaration.py index 861ada5..99add17 100644 --- a/intrastat_product/models/intrastat_product_declaration.py +++ b/intrastat_product/models/intrastat_product_declaration.py @@ -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,12 +203,11 @@ class IntrastatProductDeclaration(models.Model): for this in self: this.valid = True - @api.model @api.constrains("year") def _check_year(self): for this in self: if len(this.year) != 4 or this.year[0] != "2": - raise ValidationError(_("Invalid Year !")) + raise ValidationError(_("Invalid Year!")) @api.onchange("declaration_type") def _onchange_declaration_type(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() diff --git a/intrastat_product/readme/CONTRIBUTORS.rst b/intrastat_product/readme/CONTRIBUTORS.rst index 08d6018..bd08e8d 100644 --- a/intrastat_product/readme/CONTRIBUTORS.rst +++ b/intrastat_product/readme/CONTRIBUTORS.rst @@ -1,5 +1,6 @@ * Alexis de Lattre, Akretion * Luc De Meyer, Noviat +* Denis Roussel * Tecnativa : * João Marques diff --git a/intrastat_product/security/ir.model.access.csv b/intrastat_product/security/ir.model.access.csv index ac93450..65141ca 100644 --- a/intrastat_product/security/ir.model.access.csv +++ b/intrastat_product/security/ir.model.access.csv @@ -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 diff --git a/intrastat_product/static/description/index.html b/intrastat_product/static/description/index.html index 793da6e..18ecb5f 100644 --- a/intrastat_product/static/description/index.html +++ b/intrastat_product/static/description/index.html @@ -469,6 +469,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome

    Authors

      +
    • ACSONE SA/NV
    • brain-tec AG
    • Akretion
    • Noviat
    • @@ -481,6 +482,8 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
    • Luc De Meyer, Noviat <info@noviat.com>

    • +
    • Denis Roussel <denis.roussel@acsone.eu>

      +
    • Tecnativa <www.tecnativa.com>:

        diff --git a/intrastat_product/tests/__init__.py b/intrastat_product/tests/__init__.py new file mode 100644 index 0000000..804b5f7 --- /dev/null +++ b/intrastat_product/tests/__init__.py @@ -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 diff --git a/intrastat_product/tests/common.py b/intrastat_product/tests/common.py new file mode 100644 index 0000000..6efb68b --- /dev/null +++ b/intrastat_product/tests/common.py @@ -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) diff --git a/intrastat_product/tests/common_purchase.py b/intrastat_product/tests/common_purchase.py new file mode 100644 index 0000000..7574457 --- /dev/null +++ b/intrastat_product/tests/common_purchase.py @@ -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 diff --git a/intrastat_product/tests/common_sale.py b/intrastat_product/tests/common_sale.py new file mode 100644 index 0000000..4a3a457 --- /dev/null +++ b/intrastat_product/tests/common_sale.py @@ -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 diff --git a/intrastat_product/tests/test_company.py b/intrastat_product/tests/test_company.py new file mode 100644 index 0000000..7fe99ac --- /dev/null +++ b/intrastat_product/tests/test_company.py @@ -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 """ diff --git a/intrastat_product/tests/test_intrastat_product.py b/intrastat_product/tests/test_intrastat_product.py new file mode 100644 index 0000000..af0b265 --- /dev/null +++ b/intrastat_product/tests/test_intrastat_product.py @@ -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 """ diff --git a/intrastat_product/tests/test_purchase_order.py b/intrastat_product/tests/test_purchase_order.py new file mode 100644 index 0000000..f6538c1 --- /dev/null +++ b/intrastat_product/tests/test_purchase_order.py @@ -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 """ diff --git a/intrastat_product/tests/test_sale_order.py b/intrastat_product/tests/test_sale_order.py new file mode 100644 index 0000000..7d5b411 --- /dev/null +++ b/intrastat_product/tests/test_sale_order.py @@ -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 """ diff --git a/intrastat_product/wizards/__init__.py b/intrastat_product/wizards/__init__.py new file mode 100644 index 0000000..3277b28 --- /dev/null +++ b/intrastat_product/wizards/__init__.py @@ -0,0 +1 @@ +from . import intrastat_result_view diff --git a/intrastat_product/wizards/intrastat_result_view.py b/intrastat_product/wizards/intrastat_result_view.py new file mode 100644 index 0000000..efd743f --- /dev/null +++ b/intrastat_product/wizards/intrastat_result_view.py @@ -0,0 +1,14 @@ +# Copyright 2010-2021 Akretion () +# 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") + ) diff --git a/intrastat_product/wizards/intrastat_result_view.xml b/intrastat_product/wizards/intrastat_result_view.xml new file mode 100644 index 0000000..16b9303 --- /dev/null +++ b/intrastat_product/wizards/intrastat_result_view.xml @@ -0,0 +1,22 @@ + + + + + intrastat.result_view_form + intrastat.result.view + +
        + + + + +
        +
        +
        +
        diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 0000000..864b829 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,2 @@ +odoo-test-helper +freezegun