From a9069c6e0b6e247928c5b67ddc46dbf9c75c60c9 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Tue, 5 Apr 2011 00:57:21 +0200 Subject: [PATCH 01/44] [ADD] intrastat_base: Redesign for 6.1 Complete change of design for intrastat_type ! Now that report_intrastat_product/service object is stored in database, we don't need the legal_intrastat state on invoices any more, because we will be able to create entry lines for DEB for a repair of equipment under warranty without using a legal_intrastat. Report_intrastat_type is now only required for DEB -> object moved to module l10n_fr_intrastat_product. For DEB, the button "regenerate lines" only regenerate DEB lines related to invoices. Renamed intrastat base module, because it doesn't have France-specific parameters any more. Add demo data. Full re-design of intrastat types : probably requires deleting the report_intrastat_type table, restarting OpenERP and re-creating intrastat types. Moved intrastat departments from stock.warehouse to stock.location. Dropped SQL queries ; replaced by traditionnal python code logic. No more need to have one rate per day for invoices with foreign currency. Add total fiscal value for DEB More code factorization. Prepare translation work. Moved some demo data from l10n_fr_intrastat_product to intrastat_base Moved configuration about taxes from company form to tax form Some modifications to ease v5 -> v6 migration : - object report_intrastat_code now belong to group account manager - button functions now return True Tried to implement the following feature : open attachement form when the XML file as been generated : works on v6, but make client crash en v5 -> code has been commented DEB lines with procedure code = 25 are now deducted from the fiscal total. Round invoice total. Moved the field exclude_from_intrastat_if_present of account.tax from l10n_fr_intrastat_product to intrastat_base, because it should also be used in the module l10n_fr_intrastat_service. Take this field into account in the generation of DEB lines (module l10n_fr_intrastat_service). It is now possible to set the H.S. code on the product category. Some "return None" changed to "return True" Implemented the fiscal representative : for example, when you ship to the EU but invoice outside of the EU, your customer needs to have a fiscal representative inside the EU, which will be used for the DEB . depend on base_vat instead of account. Same modification as my previous commit for DEB : when we sell to a physical person in the EU with VAT, the move is not declared in DEB, so it must not block with a "raise" if the partner doesn't have a VAT number. Add option "is_accessory_cost" on product.template : If the invoice has is_accessory_cost services but no regular product -> DES If the invoice has is_accessory_cost services and regular product -> added to the cost of products in DEB Now allows "pricelist for statistical value" which is not in EUR (the currency conversion will be made from the pricelist currency to EUR) Usability improvements : - Order for DEB and DES tree view : "the more recent at the top" - distinction between "Information to declare" and "Additionnal information" in intrastat lines Better string. Update French translation. Use the new logger API of OpenERP 6.1 Move the "EU fiscal representative" field in order to avoid the "compression" of the VAT field that made it too small. Code clean-up : - context is not passed in constraints - don't use lambda when not necessary IMPORTANT CHANGE : - All EU countries should now be intrastat=True, including your own country - When generating lines for Intrastat Product/Service, all invoices for which country == Company's country are excluded Update help message according to my change of commit 61. Fix copyright header. --- intrastat_base/__init__.py | 28 ++++ intrastat_base/__openerp__.py | 54 ++++++ intrastat_base/country.py | 35 ++++ intrastat_base/country_data.xml | 87 ++++++++++ intrastat_base/country_view.xml | 36 ++++ intrastat_base/i18n/fr_FR.po | 176 ++++++++++++++++++++ intrastat_base/i18n/intrastat_base.pot | 166 ++++++++++++++++++ intrastat_base/intrastat_common.py | 132 +++++++++++++++ intrastat_base/intrastat_demo.xml | 57 +++++++ intrastat_base/intrastat_menu.xml | 16 ++ intrastat_base/partner_address.py | 35 ++++ intrastat_base/product.py | 49 ++++++ intrastat_base/product_view.xml | 53 ++++++ intrastat_base/security/ir.model.access.csv | 2 + intrastat_base/tax.py | 33 ++++ intrastat_base/tax_view.xml | 28 ++++ 16 files changed, 987 insertions(+) create mode 100644 intrastat_base/__init__.py create mode 100644 intrastat_base/__openerp__.py create mode 100644 intrastat_base/country.py create mode 100644 intrastat_base/country_data.xml create mode 100644 intrastat_base/country_view.xml create mode 100644 intrastat_base/i18n/fr_FR.po create mode 100644 intrastat_base/i18n/intrastat_base.pot create mode 100644 intrastat_base/intrastat_common.py create mode 100644 intrastat_base/intrastat_demo.xml create mode 100644 intrastat_base/intrastat_menu.xml create mode 100644 intrastat_base/partner_address.py create mode 100644 intrastat_base/product.py create mode 100644 intrastat_base/product_view.xml create mode 100644 intrastat_base/security/ir.model.access.csv create mode 100644 intrastat_base/tax.py create mode 100644 intrastat_base/tax_view.xml diff --git a/intrastat_base/__init__.py b/intrastat_base/__init__.py new file mode 100644 index 0000000..13ca149 --- /dev/null +++ b/intrastat_base/__init__.py @@ -0,0 +1,28 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Report intrastat base module for OpenERP +# Copyright (C) 2011 Akretion (http://www.akretion.com). All Rights Reserved +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import country +import product +import tax +import partner_address +import intrastat_common + diff --git a/intrastat_base/__openerp__.py b/intrastat_base/__openerp__.py new file mode 100644 index 0000000..089173a --- /dev/null +++ b/intrastat_base/__openerp__.py @@ -0,0 +1,54 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Report intrastat base module for OpenERP +# Copyright (C) 2011 Akretion (http://www.akretion.com). All Rights Reserved +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +{ + 'name': 'Base module for Intrastat reporting', + 'version': '1.1', + 'category': 'Localisation/Report Intrastat', + 'license': 'AGPL-3', + 'description': """This module contains the common functions for 2 other modules : +- l10n_fr_intrastat_service : the module for the "Déclaration Européenne des Services" (DES) +- l10n_fr_intrastat_product : the module for the "Déclaration d'Echange de Biens" (DEB) +This module is not usefull if it's not used together with one of those 2 modules. + +This module doesn't have any France-specific stuff. So it can be used as a basis for other intrastat modules for other EU countries. + +WARNING : this module conflicts with the module "report_intrastat" from the addons. If you have already installed the module "report_intrastat", you should uninstall it first before installing this module. + +Please contact Alexis de Lattre from Akretion for any help or question about this module. + """, + 'author': 'Akretion', + 'website': 'http://www.akretion.com', + 'depends': ['base_vat'], + 'init_xml': ['country_data.xml'], + 'update_xml': [ + 'security/ir.model.access.csv', + 'product_view.xml', + 'country_view.xml', + 'tax_view.xml', + 'intrastat_menu.xml', + ], + 'demo_xml': ['intrastat_demo.xml'], + 'installable': True, + 'active': False, +} diff --git a/intrastat_base/country.py b/intrastat_base/country.py new file mode 100644 index 0000000..2542d72 --- /dev/null +++ b/intrastat_base/country.py @@ -0,0 +1,35 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Report intrastat base module for OpenERP +# Copyright (C) 2011-2013 Akretion (http://www.akretion.com). All Rights Reserved +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from osv import osv, fields + +class res_country(osv.osv): + _inherit = 'res.country' + _columns = { + 'intrastat': fields.boolean('EU country', help="Set to True for all European Union countries."), + } + + _defaults = { + 'intrastat': False, + } + +res_country() diff --git a/intrastat_base/country_data.xml b/intrastat_base/country_data.xml new file mode 100644 index 0000000..04fb439 --- /dev/null +++ b/intrastat_base/country_data.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/intrastat_base/country_view.xml b/intrastat_base/country_view.xml new file mode 100644 index 0000000..bf62fa3 --- /dev/null +++ b/intrastat_base/country_view.xml @@ -0,0 +1,36 @@ + + + + + + + + + + intrastat.base.country.tree + res.country + + + + + + + + + + intrastat.base.country.form + res.country + + + + + + + + + + + diff --git a/intrastat_base/i18n/fr_FR.po b/intrastat_base/i18n/fr_FR.po new file mode 100644 index 0000000..c3a85fe --- /dev/null +++ b/intrastat_base/i18n/fr_FR.po @@ -0,0 +1,176 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * intrastat_base +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 6.0.4\n" +"Report-Msgid-Bugs-To: support@openerp.com\n" +"POT-Creation-Date: 2012-06-05 13:28+0000\n" +"PO-Revision-Date: 2012-06-05 13:28+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: intrastat_base +#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root +msgid "Intrastat reporting" +msgstr "DEB et DES" + +#. module: intrastat_base +#: sql_constraint:res.country:0 +msgid "The code of the country must be unique !" +msgstr "Le code du pays doit être unique !" + +#. module: intrastat_base +#: constraint:product.template:0 +msgid "Error: The default UOM and the purchase UOM must be in the same category." +msgstr "Erreur: l'UdM par défaut et l'UdM d'achat doivent appartenir à la même catégorie." + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:64 +#: code:addons/intrastat_base/intrastat_common.py:70 +#: code:addons/intrastat_base/intrastat_common.py:85 +#: code:addons/intrastat_base/intrastat_common.py:93 +#: code:addons/intrastat_base/product.py:41 +#, python-format +msgid "Error :" +msgstr "Erreur :" + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_account_tax +msgid "account.tax" +msgstr "account.tax" + +#. module: intrastat_base +#: field:account.tax,exclude_from_intrastat_if_present:0 +msgid "Exclude invoice line from intrastat if this tax is present" +msgstr "Exclue la ligne de facture de la DEB/DES si cette taxe est présente" + +#. module: intrastat_base +#: help:res.country,intrastat:0 +msgid "Set as True for countries that must be selected in the intrastat reports, i.e. for all European Union countries other than your own country." +msgstr "Activer cette option pour les pays qui doivent être inclus dans la DEB et la DES, i.e. tous les pays de l'Union Européenne sauf votre propre pays." + +#. module: intrastat_base +#: view:product.product:0 +#: view:product.template:0 +msgid "Intrastat properties" +msgstr "Paramètres pour la DEB et la DES" + +#. module: intrastat_base +#: model:ir.module.module,description:intrastat_base.module_meta_information +msgid "This module contains the common functions for 2 other modules :\n" +"- l10n_fr_intrastat_service : the module for the \"Déclaration Européenne des Services\" (DES)\n" +"- l10n_fr_intrastat_product : the module for the \"Déclaration d'Echange de Biens\" (DEB)\n" +"This module is not usefull if it's not used together with one of those 2 modules.\n" +"\n" +"This module doesn't have any France-specific stuff. So it can be used as a basis for other intrastat modules for other EU countries.\n" +"\n" +"WARNING : this module conflicts with the module \"report_intrastat\" from the addons. If you have already installed the module \"report_intrastat\", you should uninstall it first before installing this module.\n" +"\n" +"Please contact Alexis de Lattre from Akretion for any help or question about this module.\n" +" " +msgstr "This module contains the common functions for 2 other modules :\n" +"- l10n_fr_intrastat_service : the module for the \"Déclaration Européenne des Services\" (DES)\n" +"- l10n_fr_intrastat_product : the module for the \"Déclaration d'Echange de Biens\" (DEB)\n" +"This module is not usefull if it's not used together with one of those 2 modules.\n" +"\n" +"This module doesn't have any France-specific stuff. So it can be used as a basis for other intrastat modules for other EU countries.\n" +"\n" +"WARNING : this module conflicts with the module \"report_intrastat\" from the addons. If you have already installed the module \"report_intrastat\", you should uninstall it first before installing this module.\n" +"\n" +"Please contact Alexis de Lattre from Akretion for any help or question about this module.\n" +" " + +#. module: intrastat_base +#: sql_constraint:res.country:0 +msgid "The name of the country must be unique !" +msgstr "Le nom du pays doit être unique !" + +#. module: intrastat_base +#: constraint:product.template:0 +msgid "Error msg is in raise" +msgstr "Error msg is in raise" + +#. module: intrastat_base +#: help:account.tax,exclude_from_intrastat_if_present:0 +msgid "If this tax is present on an invoice line, this invoice line will be skipped when generating Intrastat Product or Service lines from invoices." +msgstr "Si cette taxe est présente sur une ligne de facture, cette ligne de facture ne sera pas prise en compte lors de la génération de la DEB et de la DES depuis les factures." + +#. module: intrastat_base +#: field:product.template,is_accessory_cost:0 +msgid "Is accessory cost" +msgstr "Frais accessoires" + +#. module: intrastat_base +#: field:res.country,intrastat:0 +msgid "Intrastat country" +msgstr "Pays intrastat" + +#. module: intrastat_base +#: help:product.template,exclude_from_intrastat:0 +msgid "If set to True, the product or service will not be taken into account for Intrastat Product or Service reports. So you should leave this field to False unless you have a very good reason." +msgstr "Si l'option est activée, le produit ou service ne sera pris en compte ni pour la DEB ni pour la DES. Cette option doit donc rester désactivée sauf si vous avez une très bonne raison." + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:64 +#, python-format +msgid "The company currency must be 'EUR', but is currently '%s'." +msgstr "La monnaie de la société doit être 'EUR', mais est actuellement '%s'." + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:70 +#, python-format +msgid "The VAT number is not set for the partner '%s'." +msgstr "Le numéro de TVA n'est pas renseigné pour le partenaire '%s'." + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_report_intrastat_common +msgid "Common functions for intrastat reports for products and services" +msgstr "Common functions for intrastat reports for products and services" + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_res_country +msgid "Country" +msgstr "Pays" + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_product_template +msgid "Product Template" +msgstr "Modèle de produit" + +#. module: intrastat_base +#: model:ir.module.module,shortdesc:intrastat_base.module_meta_information +msgid "Base module for Intrastat reporting" +msgstr "Module de base pour les rapports intrastat" + +#. module: intrastat_base +#: field:product.template,exclude_from_intrastat:0 +msgid "Exclude from Intrastat reports" +msgstr "Exclure de la DEB et de la DES" + +#. module: intrastat_base +#: help:product.template,is_accessory_cost:0 +msgid "Activate this option for shipping costs, packaging costs and all services related to the sale of products. This option is used for Intrastat reports." +msgstr "Activez cette option pour les frais de port, les frais d'emballage et tous les services liés à la vente de produits physiques. Cette option est utilisée pour la DEB et la DES." + +#. module: intrastat_base +#: model:product.template,name:intrastat_base.shipping_costs_exclude_product_template +msgid "Shipping costs" +msgstr "Frais de port" + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:85 +#, python-format +msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s." +msgstr "La validation du fichier XML avec le schéma XML officiel a échoué. Le fichier XML généré et le détail de l'erreur ont été écrits dans les logs du serveur. Voici le message d'erreur, qui peut vous donner une idée de la cause du problème : %s." + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_res_partner_address +msgid "Partner Addresses" +msgstr "Carnet d'adresses" + diff --git a/intrastat_base/i18n/intrastat_base.pot b/intrastat_base/i18n/intrastat_base.pot new file mode 100644 index 0000000..d7baf12 --- /dev/null +++ b/intrastat_base/i18n/intrastat_base.pot @@ -0,0 +1,166 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * intrastat_base +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 6.0.4\n" +"Report-Msgid-Bugs-To: support@openerp.com\n" +"POT-Creation-Date: 2012-06-05 13:28+0000\n" +"PO-Revision-Date: 2012-06-05 13:28+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: intrastat_base +#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root +msgid "Intrastat reporting" +msgstr "" + +#. module: intrastat_base +#: sql_constraint:res.country:0 +msgid "The code of the country must be unique !" +msgstr "" + +#. module: intrastat_base +#: constraint:product.template:0 +msgid "Error: The default UOM and the purchase UOM must be in the same category." +msgstr "" + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:64 +#: code:addons/intrastat_base/intrastat_common.py:70 +#: code:addons/intrastat_base/intrastat_common.py:85 +#: code:addons/intrastat_base/intrastat_common.py:93 +#: code:addons/intrastat_base/product.py:41 +#, python-format +msgid "Error :" +msgstr "" + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_account_tax +msgid "account.tax" +msgstr "" + +#. module: intrastat_base +#: field:account.tax,exclude_from_intrastat_if_present:0 +msgid "Exclude invoice line from intrastat if this tax is present" +msgstr "" + +#. module: intrastat_base +#: help:res.country,intrastat:0 +msgid "Set as True for countries that must be selected in the intrastat reports, i.e. for all European Union countries other than your own country." +msgstr "" + +#. module: intrastat_base +#: view:product.product:0 +#: view:product.template:0 +msgid "Intrastat properties" +msgstr "" + +#. module: intrastat_base +#: model:ir.module.module,description:intrastat_base.module_meta_information +msgid "This module contains the common functions for 2 other modules :\n" +"- l10n_fr_intrastat_service : the module for the \"Déclaration Européenne des Services\" (DES)\n" +"- l10n_fr_intrastat_product : the module for the \"Déclaration d'Echange de Biens\" (DEB)\n" +"This module is not usefull if it's not used together with one of those 2 modules.\n" +"\n" +"This module doesn't have any France-specific stuff. So it can be used as a basis for other intrastat modules for other EU countries.\n" +"\n" +"WARNING : this module conflicts with the module \"report_intrastat\" from the addons. If you have already installed the module \"report_intrastat\", you should uninstall it first before installing this module.\n" +"\n" +"Please contact Alexis de Lattre from Akretion for any help or question about this module.\n" +" " +msgstr "" + +#. module: intrastat_base +#: sql_constraint:res.country:0 +msgid "The name of the country must be unique !" +msgstr "" + +#. module: intrastat_base +#: constraint:product.template:0 +msgid "Error msg is in raise" +msgstr "" + +#. module: intrastat_base +#: help:account.tax,exclude_from_intrastat_if_present:0 +msgid "If this tax is present on an invoice line, this invoice line will be skipped when generating Intrastat Product or Service lines from invoices." +msgstr "" + +#. module: intrastat_base +#: field:product.template,is_accessory_cost:0 +msgid "Is accessory cost" +msgstr "" + +#. module: intrastat_base +#: field:res.country,intrastat:0 +msgid "Intrastat country" +msgstr "" + +#. module: intrastat_base +#: help:product.template,exclude_from_intrastat:0 +msgid "If set to True, the product or service will not be taken into account for Intrastat Product or Service reports. So you should leave this field to False unless you have a very good reason." +msgstr "" + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:64 +#, python-format +msgid "The company currency must be 'EUR', but is currently '%s'." +msgstr "" + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:70 +#, python-format +msgid "The VAT number is not set for the partner '%s'." +msgstr "" + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_report_intrastat_common +msgid "Common functions for intrastat reports for products and services" +msgstr "" + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_res_country +msgid "Country" +msgstr "" + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_product_template +msgid "Product Template" +msgstr "" + +#. module: intrastat_base +#: model:ir.module.module,shortdesc:intrastat_base.module_meta_information +msgid "Base module for Intrastat reporting" +msgstr "" + +#. module: intrastat_base +#: field:product.template,exclude_from_intrastat:0 +msgid "Exclude from Intrastat reports" +msgstr "" + +#. module: intrastat_base +#: help:product.template,is_accessory_cost:0 +msgid "Activate this option for shipping costs, packaging costs and all services related to the sale of products. This option is used for Intrastat reports." +msgstr "" + +#. module: intrastat_base +#: model:product.template,name:intrastat_base.shipping_costs_exclude_product_template +msgid "Shipping costs" +msgstr "" + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:85 +#, python-format +msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s." +msgstr "" + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_res_partner_address +msgid "Partner Addresses" +msgstr "" + diff --git a/intrastat_base/intrastat_common.py b/intrastat_base/intrastat_common.py new file mode 100644 index 0000000..8320b8a --- /dev/null +++ b/intrastat_base/intrastat_common.py @@ -0,0 +1,132 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Report intrastat base module for OpenERP +# Copyright (C) 2010-2011 Akretion (http://www.akretion.com/). All rights reserved. +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from osv import osv, fields +from datetime import datetime +from dateutil.relativedelta import relativedelta +from tools.translate import _ + +class report_intrastat_common(osv.osv_memory): + _name = "report.intrastat.common" + _description = "Common functions for intrastat reports for products and services" + + def _compute_numbers(self, cr, uid, ids, object, context=None): + result = {} + for intrastat in object.browse(cr, uid, ids, context=context): + total_amount = 0.0 + num_lines = 0 + for line in intrastat.intrastat_line_ids: + total_amount += line.amount_company_currency + num_lines += 1 + result[intrastat.id] = {'num_lines': num_lines, 'total_amount': total_amount} + return result + + + def _compute_end_date(self, cr, uid, ids, object, context=None): + result = {} + for intrastat in object.browse(cr, uid, ids, context=context): + start_date_datetime = datetime.strptime(intrastat.start_date, '%Y-%m-%d') + end_date_str = datetime.strftime(start_date_datetime + relativedelta(day=31), '%Y-%m-%d') + result[intrastat.id] = end_date_str + return result + + + def _check_start_date(self, cr, uid, ids, object, context=None): + '''Check that the start date is the first day of the month''' + for date_to_check in object.read(cr, uid, ids, ['start_date'], context=context): + datetime_to_check = datetime.strptime(date_to_check['start_date'], '%Y-%m-%d') + if datetime_to_check.day != 1: + return False + return True + + + def _check_generate_lines(self, cr, uid, intrastat, context=None): + if not intrastat.company_id.country_id: + raise osv.except_osv(_('Error :'), _("The country is not set on the company '%s'.") %intrastat.company_id.name) + if not intrastat.currency_id.name == 'EUR': + raise osv.except_osv(_('Error :'), _("The company currency must be 'EUR', but is currently '%s'.") %intrastat.currency_id.name) + return True + + + def _check_generate_xml(self, cr, uid, intrastat, context=None): + if not intrastat.company_id.partner_id.vat: + raise osv.except_osv(_('Error :'), _("The VAT number is not set for the partner '%s'.") %intrastat.company_id.partner_id.name) + return True + + + def _check_xml_schema(self, cr, uid, xml_root, xml_string, xsd, context=None): + '''Validate the XML file against the XSD''' + from lxml import etree + official_des_xml_schema = etree.XMLSchema(etree.fromstring(xsd)) + try: official_des_xml_schema.assertValid(xml_root) + except Exception, e: # if the validation of the XSD fails, we arrive here + import logging + _logger = logging.getLogger(__name__) + _logger.warning("The XML file is invalid against the XML Schema Definition") + _logger.warning(xml_string) + _logger.warning(e) + raise osv.except_osv(_('Error :'), _('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s.') % str(e)) + return True + + + def _attach_xml_file(self, cr, uid, ids, object, xml_string, start_date_datetime, declaration_name, context=None): + '''Attach the XML file to the report_intrastat_product/service object''' + import base64 + if len(ids) != 1: + raise osv.except_osv(_('Error :'), 'Hara kiri in attach_xml_file') + filename = datetime.strftime(start_date_datetime, '%Y-%m') + '_' + declaration_name + '.xml' + attach_name = declaration_name.upper() + ' ' + datetime.strftime(start_date_datetime, '%Y-%m') + attach_obj = self.pool.get('ir.attachment') + if not context: + context = {} + context.update({'default_res_id' : ids[0], 'default_res_model': object._name}) + attach_id = attach_obj.create(cr, uid, {'name': attach_name, 'datas': base64.encodestring(xml_string), 'datas_fname': filename}, context=context) + return attach_id + + + def _open_attach_view(self, cr, uid, attach_id, title='XML file', context=None): + '''Returns an action which opens the form view of the corresponding attachement''' + # Only works in v6 -> not used in v5 + action = { + 'name': title, + 'view_type': 'form', + 'view_mode': 'form,tree', + 'view_id': False, + 'res_model': 'ir.attachment', + 'type': 'ir.actions.act_window', + 'nodestroy': True, + 'target': 'current', + 'res_id': [attach_id], + } + return action + + + def partner_on_change(self, cr, uid, ids, partner_id=False): + result = {} + result['value'] = {} + if partner_id: + company = self.pool.get('res.partner').read(cr, uid, partner_id, ['vat']) + result['value'].update({'partner_vat': company['vat']}) + return result + +report_intrastat_common() + diff --git a/intrastat_base/intrastat_demo.xml b/intrastat_base/intrastat_demo.xml new file mode 100644 index 0000000..d83640e --- /dev/null +++ b/intrastat_base/intrastat_demo.xml @@ -0,0 +1,57 @@ + + + + + + + + + FR58441019213 + + + + BE0828696437 + True + + + + BE0443167858 + True + + + + BE0884025633 + True + + + + True + + + + True + + + + True + + + + True + + + + Shipping costs + SHIP + service + + 30 + True + + + + diff --git a/intrastat_base/intrastat_menu.xml b/intrastat_base/intrastat_menu.xml new file mode 100644 index 0000000..b078c6a --- /dev/null +++ b/intrastat_base/intrastat_menu.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/intrastat_base/partner_address.py b/intrastat_base/partner_address.py new file mode 100644 index 0000000..f36329b --- /dev/null +++ b/intrastat_base/partner_address.py @@ -0,0 +1,35 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Report intrastat base module for OpenERP +# Copyright (C) 2010-2011 Akretion (http://www.akretion.com/) All Rights Reserved +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from osv import osv, fields + +# We want to have the country field on res_partner_address always set +# because the selection of invoices for intrastat reports is based +# on the country of the invoice partner address ! +class res_partner_address(osv.osv): + _inherit = 'res.partner.address' + _columns = { + 'country_id': fields.many2one('res.country', 'Country', required=True), + } + +res_partner_address() + diff --git a/intrastat_base/product.py b/intrastat_base/product.py new file mode 100644 index 0000000..c535a72 --- /dev/null +++ b/intrastat_base/product.py @@ -0,0 +1,49 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Report intrastat base module for OpenERP +# Copyright (C) 2010-2012 Akretion (http://www.akretion.com/) All Rights Reserved +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from osv import osv, fields +from tools.translate import _ + +class product_template(osv.osv): + _inherit = "product.template" + _columns = { + 'exclude_from_intrastat': fields.boolean('Exclude from Intrastat reports', help="If set to True, the product or service will not be taken into account for Intrastat Product or Service reports. So you should leave this field to False unless you have a very good reason."), + 'is_accessory_cost' : fields.boolean('Is accessory cost', help='Activate this option for shipping costs, packaging costs and all services related to the sale of products. This option is used for Intrastat reports.'), + } + + _defaults = { + 'exclude_from_intrastat': False, + } + + + def _check_accessory_cost(self, cr, uid, ids): + for product in self.browse(cr, uid, ids): + if product.is_accessory_cost and product.type != 'service': + raise osv.except_osv(_('Error :'), _("The option 'Is accessory cost?' should only be activated on 'Service' products. You have activated this option for the product '%s' which is of type '%s'" % (product.name, product.type))) + return True + + _constraints = [ + (_check_accessory_cost, "Error msg is in raise", ['is_accessory_cost', 'type']) + ] + +product_template() + diff --git a/intrastat_base/product_view.xml b/intrastat_base/product_view.xml new file mode 100644 index 0000000..28b026e --- /dev/null +++ b/intrastat_base/product_view.xml @@ -0,0 +1,53 @@ + + + + + + + + + + intrastat.base.product.normal.form + product.product + + + + + + + + + + + + + + + + + + + intrastat.base.product.template.form + product.template + + + + + + + + + + + + + + + + + + diff --git a/intrastat_base/security/ir.model.access.csv b/intrastat_base/security/ir.model.access.csv new file mode 100644 index 0000000..d7a2bf1 --- /dev/null +++ b/intrastat_base/security/ir.model.access.csv @@ -0,0 +1,2 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +"access_report_intrastat_common","Read access on report.intrastat.common","model_report_intrastat_common","base.group_user",1,0,0,0 diff --git a/intrastat_base/tax.py b/intrastat_base/tax.py new file mode 100644 index 0000000..4d12d32 --- /dev/null +++ b/intrastat_base/tax.py @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Report intrastat base module for OpenERP +# Copyright (C) 2011 Akretion (http://www.akretion.com). All Rights Reserved +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from osv import osv, fields + + +class account_tax(osv.osv): + _inherit = "account.tax" + _columns = { + 'exclude_from_intrastat_if_present': fields.boolean('Exclude invoice line from intrastat if this tax is present', help="If this tax is present on an invoice line, this invoice line will be skipped when generating Intrastat Product or Service lines from invoices."), + } + +account_tax() + diff --git a/intrastat_base/tax_view.xml b/intrastat_base/tax_view.xml new file mode 100644 index 0000000..e60a327 --- /dev/null +++ b/intrastat_base/tax_view.xml @@ -0,0 +1,28 @@ + + + + + + + + + + intrastat.base.tax + account.tax + form + + + + + + + + + + + + From e07eb1ed811701e61a670b049f874380e88a3ee3 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Wed, 24 Apr 2013 10:55:14 +0200 Subject: [PATCH 02/44] [MIG] intrastat_base: Migration to 7.0 Should now be compatible with both OCB and RS-OCB Add field import_obligation_level on res.company Add group group_detailed_intrastat_product, so that companies that only use obligation = simplified don't see all the additionnal fields. Remove transaction code corresponding to repairs in intrastat types Better on_change on intrastat types (code is mutualised with field.function) Update syntax : demo_xml/update_xml/init_xml -> data/demo Welcome to Croatia in the European Union ! Add an e-mail reminder for l10n_fr_intrastat_product and l10n_fr_intrastat_service (hope that Akretion France won't forget it's own declarations now !!!) On report.intrastat.product and report.intrastat.service : add copy() fonctions, tracking of important fields, a year_month function field and enhance views. Remove date_done field (the tracking in the chatter does the job). Remove class instanciation in the code. Better form view of product category, courtesy of David Beal. Raise an explicit exception (take into account Stefan remark on the merge proposal) Fix to make the module truly usable when user is not part of the group "Detailed intrastat product". Remove dead code and fields that was used when we had to put DEB lines for repair operations (a thing of the past !). Update coding style. Reduce the number of flake8 warnings. On OpenERP 7, when you have the document module installed and you download the attachement via the drop down list on the form view, the name of the file will be the name of the attachement and not datas_fname ; so we need to have name = datas_fname. --- intrastat_base/__init__.py | 14 ++--- intrastat_base/__openerp__.py | 15 ++--- intrastat_base/company.py | 62 ++++++++++++++++++ intrastat_base/company_view.xml | 29 +++++++++ intrastat_base/country.py | 7 +-- intrastat_base/country_data.xml | 3 + intrastat_base/country_view.xml | 4 +- intrastat_base/intrastat_common.py | 63 ++++++++++--------- intrastat_base/intrastat_demo.xml | 8 +-- intrastat_base/intrastat_menu.xml | 2 +- .../{partner_address.py => partner.py} | 16 +++-- intrastat_base/product.py | 20 +++--- intrastat_base/product_view.xml | 32 ++++------ intrastat_base/tax.py | 9 +-- intrastat_base/tax_view.xml | 4 +- 15 files changed, 186 insertions(+), 102 deletions(-) create mode 100644 intrastat_base/company.py create mode 100644 intrastat_base/company_view.xml rename intrastat_base/{partner_address.py => partner.py} (77%) diff --git a/intrastat_base/__init__.py b/intrastat_base/__init__.py index 13ca149..8e2eaa0 100644 --- a/intrastat_base/__init__.py +++ b/intrastat_base/__init__.py @@ -2,7 +2,7 @@ ############################################################################## # # Report intrastat base module for OpenERP -# Copyright (C) 2011 Akretion (http://www.akretion.com). All Rights Reserved +# Copyright (C) 2011-2013 Akretion (http://www.akretion.com) # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -20,9 +20,9 @@ # ############################################################################## -import country -import product -import tax -import partner_address -import intrastat_common - +from . import country +from . import product +from . import tax +from . import partner +from . import company +from . import intrastat_common diff --git a/intrastat_base/__openerp__.py b/intrastat_base/__openerp__.py index 089173a..973786b 100644 --- a/intrastat_base/__openerp__.py +++ b/intrastat_base/__openerp__.py @@ -2,7 +2,7 @@ ############################################################################## # # Report intrastat base module for OpenERP -# Copyright (C) 2011 Akretion (http://www.akretion.com). All Rights Reserved +# Copyright (C) 2011-2013 Akretion (http://www.akretion.com) # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -22,14 +22,15 @@ { - 'name': 'Base module for Intrastat reporting', + 'name': 'Intrastat Reporting Base', 'version': '1.1', 'category': 'Localisation/Report Intrastat', 'license': 'AGPL-3', + 'summary': 'Base module for Intrastat reporting', 'description': """This module contains the common functions for 2 other modules : - l10n_fr_intrastat_service : the module for the "Déclaration Européenne des Services" (DES) - l10n_fr_intrastat_product : the module for the "Déclaration d'Echange de Biens" (DEB) -This module is not usefull if it's not used together with one of those 2 modules. +This module is not usefull if it's not used together with one of those 2 modules or other country-specific intrastat modules. This module doesn't have any France-specific stuff. So it can be used as a basis for other intrastat modules for other EU countries. @@ -40,15 +41,15 @@ Please contact Alexis de Lattre from Akretion for 'author': 'Akretion', 'website': 'http://www.akretion.com', 'depends': ['base_vat'], - 'init_xml': ['country_data.xml'], - 'update_xml': [ - 'security/ir.model.access.csv', + 'data': [ + 'country_data.xml', 'product_view.xml', 'country_view.xml', 'tax_view.xml', + 'company_view.xml', 'intrastat_menu.xml', ], - 'demo_xml': ['intrastat_demo.xml'], + 'demo': ['intrastat_demo.xml'], 'installable': True, 'active': False, } diff --git a/intrastat_base/company.py b/intrastat_base/company.py new file mode 100644 index 0000000..69163f5 --- /dev/null +++ b/intrastat_base/company.py @@ -0,0 +1,62 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Intrastat base module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import orm, fields +from openerp.tools.translate import _ + + +class res_company(orm.Model): + _inherit = "res.company" + + def _compute_intrastat_email_list(self, cr, uid, ids, name, arg, context=None): + result = {} + for company in self.browse(cr, uid, ids, context=context): + result[company.id] = '' + for user in company.intrastat_remind_user_ids: + if result[company.id]: + result[company.id] += ',%s' % (user.email) + else: + result[company.id] = user.email + return result + + _columns = { + 'intrastat_remind_user_ids': fields.many2many('res.users', + id1='company_id', id2='user_id', + string="Users Receiving the Intrastat Reminder", + help="List of OpenERP users who will receive a notification to remind them about the Intrastat declaration."), + 'intrastat_email_list': fields.function(_compute_intrastat_email_list, + type='char', size=1000, + string='List of emails of Users Receiving the Intrastat Reminder', + help='Comma-separated list of email addresses of Users Receiving the Intrastat Reminder. For use in the email template.'), + } + + def _check_intrastat_remind_users(self, cr, uid, ids): + for company in self.browse(cr, uid, ids): + for user in company.intrastat_remind_user_ids: + if not user.email: + raise orm.except_orm(_('Error :'), _("Missing e-mail address on user '%s'.") % (user.name)) + return True + + _constraints = [ + (_check_intrastat_remind_users, "error msg in raise", + ['intrastat_remind_user_ids']), + ] diff --git a/intrastat_base/company_view.xml b/intrastat_base/company_view.xml new file mode 100644 index 0000000..14cf1fe --- /dev/null +++ b/intrastat_base/company_view.xml @@ -0,0 +1,29 @@ + + + + + + + + + intrastat.company.form + res.company + + + + + + + + + + + + + + + diff --git a/intrastat_base/country.py b/intrastat_base/country.py index 2542d72..2cb923f 100644 --- a/intrastat_base/country.py +++ b/intrastat_base/country.py @@ -20,9 +20,10 @@ # ############################################################################## -from osv import osv, fields +from openerp.osv import orm, fields -class res_country(osv.osv): + +class res_country(orm.Model): _inherit = 'res.country' _columns = { 'intrastat': fields.boolean('EU country', help="Set to True for all European Union countries."), @@ -31,5 +32,3 @@ class res_country(osv.osv): _defaults = { 'intrastat': False, } - -res_country() diff --git a/intrastat_base/country_data.xml b/intrastat_base/country_data.xml index 04fb439..c77f548 100644 --- a/intrastat_base/country_data.xml +++ b/intrastat_base/country_data.xml @@ -83,5 +83,8 @@ + + + diff --git a/intrastat_base/country_view.xml b/intrastat_base/country_view.xml index bf62fa3..87e7ec9 100644 --- a/intrastat_base/country_view.xml +++ b/intrastat_base/country_view.xml @@ -1,7 +1,7 @@ @@ -26,7 +26,7 @@ - + diff --git a/intrastat_base/intrastat_common.py b/intrastat_base/intrastat_common.py index 8320b8a..7a21a62 100644 --- a/intrastat_base/intrastat_common.py +++ b/intrastat_base/intrastat_common.py @@ -2,7 +2,7 @@ ############################################################################## # # Report intrastat base module for OpenERP -# Copyright (C) 2010-2011 Akretion (http://www.akretion.com/). All rights reserved. +# Copyright (C) 2010-2013 Akretion (http://www.akretion.com/). All rights reserved. # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -20,12 +20,16 @@ # ############################################################################## -from osv import osv, fields +from openerp.osv import orm +from openerp.tools.translate import _ from datetime import datetime from dateutil.relativedelta import relativedelta -from tools.translate import _ +import logging -class report_intrastat_common(osv.osv_memory): +logger = logging.getLogger(__name__) + + +class report_intrastat_common(orm.TransientModel): _name = "report.intrastat.common" _description = "Common functions for intrastat reports for products and services" @@ -40,16 +44,17 @@ class report_intrastat_common(osv.osv_memory): result[intrastat.id] = {'num_lines': num_lines, 'total_amount': total_amount} return result - - def _compute_end_date(self, cr, uid, ids, object, context=None): + def _compute_dates(self, cr, uid, ids, object, context=None): result = {} for intrastat in object.browse(cr, uid, ids, context=context): start_date_datetime = datetime.strptime(intrastat.start_date, '%Y-%m-%d') end_date_str = datetime.strftime(start_date_datetime + relativedelta(day=31), '%Y-%m-%d') - result[intrastat.id] = end_date_str + result[intrastat.id] = { + 'end_date': end_date_str, + 'year_month': start_date_datetime.strftime('%Y-%m'), + } return result - def _check_start_date(self, cr, uid, ids, object, context=None): '''Check that the start date is the first day of the month''' for date_to_check in object.read(cr, uid, ids, ['start_date'], context=context): @@ -58,54 +63,47 @@ class report_intrastat_common(osv.osv_memory): return False return True - def _check_generate_lines(self, cr, uid, intrastat, context=None): if not intrastat.company_id.country_id: - raise osv.except_osv(_('Error :'), _("The country is not set on the company '%s'.") %intrastat.company_id.name) + raise orm.except_orm(_('Error :'), _("The country is not set on the company '%s'.") % intrastat.company_id.name) if not intrastat.currency_id.name == 'EUR': - raise osv.except_osv(_('Error :'), _("The company currency must be 'EUR', but is currently '%s'.") %intrastat.currency_id.name) + raise orm.except_orm(_('Error :'), _("The company currency must be 'EUR', but is currently '%s'.") % intrastat.currency_id.name) return True - def _check_generate_xml(self, cr, uid, intrastat, context=None): if not intrastat.company_id.partner_id.vat: - raise osv.except_osv(_('Error :'), _("The VAT number is not set for the partner '%s'.") %intrastat.company_id.partner_id.name) + raise orm.except_orm(_('Error :'), _("The VAT number is not set for the partner '%s'.") % intrastat.company_id.partner_id.name) return True - def _check_xml_schema(self, cr, uid, xml_root, xml_string, xsd, context=None): '''Validate the XML file against the XSD''' from lxml import etree official_des_xml_schema = etree.XMLSchema(etree.fromstring(xsd)) - try: official_des_xml_schema.assertValid(xml_root) + try: + official_des_xml_schema.assertValid(xml_root) except Exception, e: # if the validation of the XSD fails, we arrive here import logging _logger = logging.getLogger(__name__) _logger.warning("The XML file is invalid against the XML Schema Definition") _logger.warning(xml_string) _logger.warning(e) - raise osv.except_osv(_('Error :'), _('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s.') % str(e)) + raise orm.except_orm(_('Error :'), _('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s.') % str(e)) return True - def _attach_xml_file(self, cr, uid, ids, object, xml_string, start_date_datetime, declaration_name, context=None): '''Attach the XML file to the report_intrastat_product/service object''' import base64 - if len(ids) != 1: - raise osv.except_osv(_('Error :'), 'Hara kiri in attach_xml_file') + assert len(ids) == 1, "Only one ID accepted" filename = datetime.strftime(start_date_datetime, '%Y-%m') + '_' + declaration_name + '.xml' - attach_name = declaration_name.upper() + ' ' + datetime.strftime(start_date_datetime, '%Y-%m') attach_obj = self.pool.get('ir.attachment') if not context: context = {} - context.update({'default_res_id' : ids[0], 'default_res_model': object._name}) - attach_id = attach_obj.create(cr, uid, {'name': attach_name, 'datas': base64.encodestring(xml_string), 'datas_fname': filename}, context=context) + context.update({'default_res_id': ids[0], 'default_res_model': object._name}) + attach_id = attach_obj.create(cr, uid, {'name': filename, 'datas': base64.encodestring(xml_string), 'datas_fname': filename}, context=context) return attach_id - def _open_attach_view(self, cr, uid, attach_id, title='XML file', context=None): '''Returns an action which opens the form view of the corresponding attachement''' - # Only works in v6 -> not used in v5 action = { 'name': title, 'view_type': 'form', @@ -115,11 +113,10 @@ class report_intrastat_common(osv.osv_memory): 'type': 'ir.actions.act_window', 'nodestroy': True, 'target': 'current', - 'res_id': [attach_id], + 'res_id': attach_id, } return action - def partner_on_change(self, cr, uid, ids, partner_id=False): result = {} result['value'] = {} @@ -128,5 +125,15 @@ class report_intrastat_common(osv.osv_memory): result['value'].update({'partner_vat': company['vat']}) return result -report_intrastat_common() - + def send_reminder_email(self, cr, uid, company, module_name, template_xmlid, intrastat_id, context=None): + template_data = self.pool['ir.model.data'].get_object_reference(cr, uid, module_name, template_xmlid) + if template_data and template_data[0] == 'email.template': + template_id = template_data[1] + else: + raise orm.except_orm(_('Error :'), _("Wrong model for XMLID '%s.%s': model is '%s' and it should be 'email.template'.") % (module_name, template_xmlid, template_data[0])) + if company.intrastat_remind_user_ids: + self.pool['email.template'].send_mail(cr, uid, template_id, intrastat_id, context=context) + logger.info('Intrastat Reminder email has been sent (XMLID: %s).' % template_xmlid) + else: + logger.warning('The list of users receiving the Intrastat Reminder is empty on company %s' % company.name) + return True diff --git a/intrastat_base/intrastat_demo.xml b/intrastat_base/intrastat_demo.xml index d83640e..07c68ab 100644 --- a/intrastat_base/intrastat_demo.xml +++ b/intrastat_base/intrastat_demo.xml @@ -1,7 +1,7 @@ @@ -13,7 +13,7 @@ FR58441019213 - + BE0828696437 True @@ -23,7 +23,7 @@ True - + BE0884025633 True @@ -48,7 +48,7 @@ Shipping costs SHIP service - + 30 True diff --git a/intrastat_base/intrastat_menu.xml b/intrastat_base/intrastat_menu.xml index b078c6a..83434cb 100644 --- a/intrastat_base/intrastat_menu.xml +++ b/intrastat_base/intrastat_menu.xml @@ -1,7 +1,7 @@ diff --git a/intrastat_base/partner_address.py b/intrastat_base/partner.py similarity index 77% rename from intrastat_base/partner_address.py rename to intrastat_base/partner.py index f36329b..a87c0ed 100644 --- a/intrastat_base/partner_address.py +++ b/intrastat_base/partner.py @@ -2,7 +2,7 @@ ############################################################################## # # Report intrastat base module for OpenERP -# Copyright (C) 2010-2011 Akretion (http://www.akretion.com/) All Rights Reserved +# Copyright (C) 2010-2013 Akretion (http://www.akretion.com/) # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -20,16 +20,14 @@ # ############################################################################## -from osv import osv, fields +from openerp.osv import orm, fields -# We want to have the country field on res_partner_address always set + +# We want to have the country field on res_partner always set # because the selection of invoices for intrastat reports is based -# on the country of the invoice partner address ! -class res_partner_address(osv.osv): - _inherit = 'res.partner.address' +# on the country of the invoice partner ! +class res_partner(orm.Model): + _inherit = 'res.partner' _columns = { 'country_id': fields.many2one('res.country', 'Country', required=True), } - -res_partner_address() - diff --git a/intrastat_base/product.py b/intrastat_base/product.py index c535a72..60132f0 100644 --- a/intrastat_base/product.py +++ b/intrastat_base/product.py @@ -2,7 +2,7 @@ ############################################################################## # # Report intrastat base module for OpenERP -# Copyright (C) 2010-2012 Akretion (http://www.akretion.com/) All Rights Reserved +# Copyright (C) 2010-2013 Akretion (http://www.akretion.com/) # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -20,30 +20,28 @@ # ############################################################################## -from osv import osv, fields -from tools.translate import _ +from openerp.osv import orm, fields +from openerp.tools.translate import _ -class product_template(osv.osv): + +class product_template(orm.Model): _inherit = "product.template" _columns = { 'exclude_from_intrastat': fields.boolean('Exclude from Intrastat reports', help="If set to True, the product or service will not be taken into account for Intrastat Product or Service reports. So you should leave this field to False unless you have a very good reason."), - 'is_accessory_cost' : fields.boolean('Is accessory cost', help='Activate this option for shipping costs, packaging costs and all services related to the sale of products. This option is used for Intrastat reports.'), + 'is_accessory_cost': fields.boolean('Is accessory cost', help='Activate this option for shipping costs, packaging costs and all services related to the sale of products. This option is used for Intrastat reports.'), } _defaults = { 'exclude_from_intrastat': False, } - def _check_accessory_cost(self, cr, uid, ids): for product in self.browse(cr, uid, ids): if product.is_accessory_cost and product.type != 'service': - raise osv.except_osv(_('Error :'), _("The option 'Is accessory cost?' should only be activated on 'Service' products. You have activated this option for the product '%s' which is of type '%s'" % (product.name, product.type))) + raise orm.except_orm(_('Error :'), _("The option 'Is accessory cost?' should only be activated on 'Service' products. You have activated this option for the product '%s' which is of type '%s'" % (product.name, product.type))) return True _constraints = [ - (_check_accessory_cost, "Error msg is in raise", ['is_accessory_cost', 'type']) + (_check_accessory_cost, "Error msg is in raise", + ['is_accessory_cost', 'type']) ] - -product_template() - diff --git a/intrastat_base/product_view.xml b/intrastat_base/product_view.xml index 28b026e..fd7c2d4 100644 --- a/intrastat_base/product_view.xml +++ b/intrastat_base/product_view.xml @@ -1,7 +1,7 @@ @@ -15,17 +15,12 @@ product.product - - - - - - - - + + + - - + + @@ -35,17 +30,12 @@ product.template - - - - - - - - + + + - - + + diff --git a/intrastat_base/tax.py b/intrastat_base/tax.py index 4d12d32..5e933d1 100644 --- a/intrastat_base/tax.py +++ b/intrastat_base/tax.py @@ -2,7 +2,7 @@ ############################################################################## # # Report intrastat base module for OpenERP -# Copyright (C) 2011 Akretion (http://www.akretion.com). All Rights Reserved +# Copyright (C) 2011-2013 Akretion (http://www.akretion.com). All Rights Reserved # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -20,14 +20,11 @@ # ############################################################################## -from osv import osv, fields +from openerp.osv import orm, fields -class account_tax(osv.osv): +class account_tax(orm.Model): _inherit = "account.tax" _columns = { 'exclude_from_intrastat_if_present': fields.boolean('Exclude invoice line from intrastat if this tax is present', help="If this tax is present on an invoice line, this invoice line will be skipped when generating Intrastat Product or Service lines from invoices."), } - -account_tax() - diff --git a/intrastat_base/tax_view.xml b/intrastat_base/tax_view.xml index e60a327..c481490 100644 --- a/intrastat_base/tax_view.xml +++ b/intrastat_base/tax_view.xml @@ -17,8 +17,8 @@ - - + + From e1052ae0c5fcc14f312f673193f200aa4ef3a1eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20B=C3=A9al?= Date: Sun, 9 Mar 2014 09:29:59 +0100 Subject: [PATCH 03/44] [FIX] intrastat_base: Several things * switch required=True for country_id from model to views in res.partner * xpath in partner view as Niels Huylebroeck suggest * simplify first xpath too in partner view * xpath in a more generic way --- intrastat_base/__init__.py | 1 - intrastat_base/__openerp__.py | 1 + intrastat_base/partner.py | 33 --------------------------------- intrastat_base/partner_view.xml | 31 +++++++++++++++++++++++++++++++ 4 files changed, 32 insertions(+), 34 deletions(-) delete mode 100644 intrastat_base/partner.py create mode 100644 intrastat_base/partner_view.xml diff --git a/intrastat_base/__init__.py b/intrastat_base/__init__.py index 8e2eaa0..3070e32 100644 --- a/intrastat_base/__init__.py +++ b/intrastat_base/__init__.py @@ -23,6 +23,5 @@ from . import country from . import product from . import tax -from . import partner from . import company from . import intrastat_common diff --git a/intrastat_base/__openerp__.py b/intrastat_base/__openerp__.py index 973786b..9661bd8 100644 --- a/intrastat_base/__openerp__.py +++ b/intrastat_base/__openerp__.py @@ -44,6 +44,7 @@ Please contact Alexis de Lattre from Akretion for 'data': [ 'country_data.xml', 'product_view.xml', + 'partner_view.xml', 'country_view.xml', 'tax_view.xml', 'company_view.xml', diff --git a/intrastat_base/partner.py b/intrastat_base/partner.py deleted file mode 100644 index a87c0ed..0000000 --- a/intrastat_base/partner.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Report intrastat base module for OpenERP -# Copyright (C) 2010-2013 Akretion (http://www.akretion.com/) -# @author Alexis de Lattre -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp.osv import orm, fields - - -# We want to have the country field on res_partner always set -# because the selection of invoices for intrastat reports is based -# on the country of the invoice partner ! -class res_partner(orm.Model): - _inherit = 'res.partner' - _columns = { - 'country_id': fields.many2one('res.country', 'Country', required=True), - } diff --git a/intrastat_base/partner_view.xml b/intrastat_base/partner_view.xml new file mode 100644 index 0000000..7dc9f4e --- /dev/null +++ b/intrastat_base/partner_view.xml @@ -0,0 +1,31 @@ + + + + + + + + + + res.partner + + + + {'readonly': [('use_parent_address','=',True)], 'required': True} + + + + {'required': True} + + + + + + + From 5bf370d19f9cb3e83364f2f2c7a3e0bb348658cc Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Mon, 14 Apr 2014 16:32:08 +0200 Subject: [PATCH 04/44] [IMP] intrastat_base: Several improvements: * Use l10n_fr_* : use the method _company_default_get() intrastat_base : - the module is now PEP-8 compliant ! - add search view on countries - is_accessory_cost is now invisible when product != service - update POT file and FR translation - remove double import of logging lib * Add context in on_change (to be able to use web_context_tunnel) XSD files are now pure XSD files, not python file with the content as string. Convert l10n_fr_intrastat_service to PEP-8 Start to convert l10n_fr_intrastat_product to PEP-8 (not finished yet) l10n_fr_intrastat_product : Update POT file and FR translation. * l10n_fr_intrastat_service : update POT file and FR translation. l10n_fr_intrastat_product : continue PEP-8 compliance --- intrastat_base/company.py | 22 +- intrastat_base/country.py | 6 +- intrastat_base/country_view.xml | 15 ++ intrastat_base/i18n/fr_FR.po | 271 +++++++++++++------------ intrastat_base/i18n/intrastat_base.pot | 245 ++++++++++++---------- intrastat_base/intrastat_common.py | 124 +++++++---- intrastat_base/product.py | 21 +- intrastat_base/product_view.xml | 6 +- intrastat_base/tax.py | 9 +- 9 files changed, 426 insertions(+), 293 deletions(-) diff --git a/intrastat_base/company.py b/intrastat_base/company.py index 69163f5..030101f 100644 --- a/intrastat_base/company.py +++ b/intrastat_base/company.py @@ -27,7 +27,8 @@ from openerp.tools.translate import _ class res_company(orm.Model): _inherit = "res.company" - def _compute_intrastat_email_list(self, cr, uid, ids, name, arg, context=None): + def _compute_intrastat_email_list( + self, cr, uid, ids, name, arg, context=None): result = {} for company in self.browse(cr, uid, ids, context=context): result[company.id] = '' @@ -39,21 +40,24 @@ class res_company(orm.Model): return result _columns = { - 'intrastat_remind_user_ids': fields.many2many('res.users', - id1='company_id', id2='user_id', + 'intrastat_remind_user_ids': fields.many2many( + 'res.users', id1='company_id', id2='user_id', string="Users Receiving the Intrastat Reminder", - help="List of OpenERP users who will receive a notification to remind them about the Intrastat declaration."), - 'intrastat_email_list': fields.function(_compute_intrastat_email_list, - type='char', size=1000, - string='List of emails of Users Receiving the Intrastat Reminder', - help='Comma-separated list of email addresses of Users Receiving the Intrastat Reminder. For use in the email template.'), + help="List of OpenERP users who will receive a notification to " + "remind them about the Intrastat declaration."), + 'intrastat_email_list': fields.function( + _compute_intrastat_email_list, type='char', size=1000, + string='List of emails of Users Receiving the Intrastat Reminder'), } def _check_intrastat_remind_users(self, cr, uid, ids): for company in self.browse(cr, uid, ids): for user in company.intrastat_remind_user_ids: if not user.email: - raise orm.except_orm(_('Error :'), _("Missing e-mail address on user '%s'.") % (user.name)) + raise orm.except_orm( + _('Error :'), + _("Missing e-mail address on user '%s'.") + % (user.name)) return True _constraints = [ diff --git a/intrastat_base/country.py b/intrastat_base/country.py index 2cb923f..e967e92 100644 --- a/intrastat_base/country.py +++ b/intrastat_base/country.py @@ -2,7 +2,7 @@ ############################################################################## # # Report intrastat base module for OpenERP -# Copyright (C) 2011-2013 Akretion (http://www.akretion.com). All Rights Reserved +# Copyright (C) 2011-2013 Akretion (http://www.akretion.com). # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -26,7 +26,9 @@ from openerp.osv import orm, fields class res_country(orm.Model): _inherit = 'res.country' _columns = { - 'intrastat': fields.boolean('EU country', help="Set to True for all European Union countries."), + 'intrastat': fields.boolean( + 'EU Country', + help="Set to True for all European Union countries."), } _defaults = { diff --git a/intrastat_base/country_view.xml b/intrastat_base/country_view.xml index 87e7ec9..2177dbb 100644 --- a/intrastat_base/country_view.xml +++ b/intrastat_base/country_view.xml @@ -31,6 +31,21 @@ + + + intrastat.base.country.search + res.country + + + + + + + + + + diff --git a/intrastat_base/i18n/fr_FR.po b/intrastat_base/i18n/fr_FR.po index c3a85fe..77ac6e9 100644 --- a/intrastat_base/i18n/fr_FR.po +++ b/intrastat_base/i18n/fr_FR.po @@ -4,11 +4,11 @@ # msgid "" msgstr "" -"Project-Id-Version: OpenERP Server 6.0.4\n" -"Report-Msgid-Bugs-To: support@openerp.com\n" -"POT-Creation-Date: 2012-06-05 13:28+0000\n" -"PO-Revision-Date: 2012-06-05 13:28+0000\n" -"Last-Translator: <>\n" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-04-14 14:18+0000\n" +"PO-Revision-Date: 2014-04-14 14:18+0000\n" +"Last-Translator: Alexis de Lattre \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -16,122 +16,24 @@ msgstr "" "Plural-Forms: \n" #. module: intrastat_base -#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root -msgid "Intrastat reporting" -msgstr "DEB et DES" +#: help:product.template,is_accessory_cost:0 +msgid "Activate this option for shipping costs, packaging costs and all services related to the sale of products. This option is used for Intrastat reports." +msgstr "Activez cette option pour les frais de port, les frais d'emballage et tous les services liés à la vente de produits physiques. Cette option est utilisée pour la DEB et la DES." #. module: intrastat_base -#: sql_constraint:res.country:0 -msgid "The code of the country must be unique !" -msgstr "Le code du pays doit être unique !" - -#. module: intrastat_base -#: constraint:product.template:0 -msgid "Error: The default UOM and the purchase UOM must be in the same category." -msgstr "Erreur: l'UdM par défaut et l'UdM d'achat doivent appartenir à la même catégorie." - -#. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:64 -#: code:addons/intrastat_base/intrastat_common.py:70 -#: code:addons/intrastat_base/intrastat_common.py:85 -#: code:addons/intrastat_base/intrastat_common.py:93 -#: code:addons/intrastat_base/product.py:41 -#, python-format -msgid "Error :" -msgstr "Erreur :" - -#. module: intrastat_base -#: model:ir.model,name:intrastat_base.model_account_tax -msgid "account.tax" -msgstr "account.tax" - -#. module: intrastat_base -#: field:account.tax,exclude_from_intrastat_if_present:0 -msgid "Exclude invoice line from intrastat if this tax is present" -msgstr "Exclue la ligne de facture de la DEB/DES si cette taxe est présente" - -#. module: intrastat_base -#: help:res.country,intrastat:0 -msgid "Set as True for countries that must be selected in the intrastat reports, i.e. for all European Union countries other than your own country." -msgstr "Activer cette option pour les pays qui doivent être inclus dans la DEB et la DES, i.e. tous les pays de l'Union Européenne sauf votre propre pays." - -#. module: intrastat_base -#: view:product.product:0 -#: view:product.template:0 -msgid "Intrastat properties" -msgstr "Paramètres pour la DEB et la DES" - -#. module: intrastat_base -#: model:ir.module.module,description:intrastat_base.module_meta_information -msgid "This module contains the common functions for 2 other modules :\n" -"- l10n_fr_intrastat_service : the module for the \"Déclaration Européenne des Services\" (DES)\n" -"- l10n_fr_intrastat_product : the module for the \"Déclaration d'Echange de Biens\" (DEB)\n" -"This module is not usefull if it's not used together with one of those 2 modules.\n" -"\n" -"This module doesn't have any France-specific stuff. So it can be used as a basis for other intrastat modules for other EU countries.\n" -"\n" -"WARNING : this module conflicts with the module \"report_intrastat\" from the addons. If you have already installed the module \"report_intrastat\", you should uninstall it first before installing this module.\n" -"\n" -"Please contact Alexis de Lattre from Akretion for any help or question about this module.\n" -" " -msgstr "This module contains the common functions for 2 other modules :\n" -"- l10n_fr_intrastat_service : the module for the \"Déclaration Européenne des Services\" (DES)\n" -"- l10n_fr_intrastat_product : the module for the \"Déclaration d'Echange de Biens\" (DEB)\n" -"This module is not usefull if it's not used together with one of those 2 modules.\n" -"\n" -"This module doesn't have any France-specific stuff. So it can be used as a basis for other intrastat modules for other EU countries.\n" -"\n" -"WARNING : this module conflicts with the module \"report_intrastat\" from the addons. If you have already installed the module \"report_intrastat\", you should uninstall it first before installing this module.\n" -"\n" -"Please contact Alexis de Lattre from Akretion for any help or question about this module.\n" -" " - -#. module: intrastat_base -#: sql_constraint:res.country:0 -msgid "The name of the country must be unique !" -msgstr "Le nom du pays doit être unique !" - -#. module: intrastat_base -#: constraint:product.template:0 -msgid "Error msg is in raise" -msgstr "Error msg is in raise" - -#. module: intrastat_base -#: help:account.tax,exclude_from_intrastat_if_present:0 -msgid "If this tax is present on an invoice line, this invoice line will be skipped when generating Intrastat Product or Service lines from invoices." -msgstr "Si cette taxe est présente sur une ligne de facture, cette ligne de facture ne sera pas prise en compte lors de la génération de la DEB et de la DES depuis les factures." - -#. module: intrastat_base -#: field:product.template,is_accessory_cost:0 -msgid "Is accessory cost" -msgstr "Frais accessoires" - -#. module: intrastat_base -#: field:res.country,intrastat:0 -msgid "Intrastat country" -msgstr "Pays intrastat" - -#. module: intrastat_base -#: help:product.template,exclude_from_intrastat:0 -msgid "If set to True, the product or service will not be taken into account for Intrastat Product or Service reports. So you should leave this field to False unless you have a very good reason." -msgstr "Si l'option est activée, le produit ou service ne sera pris en compte ni pour la DEB ni pour la DES. Cette option doit donc rester désactivée sauf si vous avez une très bonne raison." - -#. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:64 -#, python-format -msgid "The company currency must be 'EUR', but is currently '%s'." -msgstr "La monnaie de la société doit être 'EUR', mais est actuellement '%s'." - -#. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:70 -#, python-format -msgid "The VAT number is not set for the partner '%s'." -msgstr "Le numéro de TVA n'est pas renseigné pour le partenaire '%s'." +#: view:res.company:0 +msgid "Common Intrastat Settings" +msgstr "Paramètres communs DEB et DES" #. module: intrastat_base #: model:ir.model,name:intrastat_base.model_report_intrastat_common msgid "Common functions for intrastat reports for products and services" -msgstr "Common functions for intrastat reports for products and services" +msgstr "Fonctions communes pour la DEB et la DES" + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_res_company +msgid "Companies" +msgstr "Sociétés" #. module: intrastat_base #: model:ir.model,name:intrastat_base.model_res_country @@ -139,14 +41,26 @@ msgid "Country" msgstr "Pays" #. module: intrastat_base -#: model:ir.model,name:intrastat_base.model_product_template -msgid "Product Template" -msgstr "Modèle de produit" +#: view:res.country:0 +#: field:res.country,intrastat:0 +msgid "EU Country" +msgstr "Pays UE" #. module: intrastat_base -#: model:ir.module.module,shortdesc:intrastat_base.module_meta_information -msgid "Base module for Intrastat reporting" -msgstr "Module de base pour les rapports intrastat" +#: code:addons/intrastat_base/company.py:58 +#: code:addons/intrastat_base/intrastat_common.py:77 +#: code:addons/intrastat_base/intrastat_common.py:82 +#: code:addons/intrastat_base/intrastat_common.py:90 +#: code:addons/intrastat_base/intrastat_common.py:110 +#: code:addons/intrastat_base/product.py:51 +#, python-format +msgid "Error :" +msgstr "Erreur :" + +#. module: intrastat_base +#: constraint:product.template:0 +msgid "Error msg is in raise" +msgstr "Error msg is in raise" #. module: intrastat_base #: field:product.template,exclude_from_intrastat:0 @@ -154,9 +68,76 @@ msgid "Exclude from Intrastat reports" msgstr "Exclure de la DEB et de la DES" #. module: intrastat_base -#: help:product.template,is_accessory_cost:0 -msgid "Activate this option for shipping costs, packaging costs and all services related to the sale of products. This option is used for Intrastat reports." -msgstr "Activez cette option pour les frais de port, les frais d'emballage et tous les services liés à la vente de produits physiques. Cette option est utilisée pour la DEB et la DES." +#: field:account.tax,exclude_from_intrastat_if_present:0 +msgid "Exclude invoice line from intrastat if this tax is present" +msgstr "Exclue la ligne de facture de la DEB/DES si cette taxe est présente" + +#. module: intrastat_base +#: help:product.template,exclude_from_intrastat:0 +msgid "If set to True, the product or service will not be taken into account for Intrastat Product or Service reports. So you should leave this field to False unless you have a very good reason." +msgstr "Si l'option est activée, le produit ou service ne sera pris en compte ni pour la DEB ni pour la DES. Cette option doit donc rester désactivée sauf si vous avez une très bonne raison." + +#. module: intrastat_base +#: help:account.tax,exclude_from_intrastat_if_present:0 +msgid "If this tax is present on an invoice line, this invoice line will be skipped when generating Intrastat Product or Service lines from invoices." +msgstr "Si cette taxe est présente sur une ligne de facture, cette ligne de facture ne sera pas prise en compte lors de la génération de la DEB et de la DES depuis les factures." + +#. module: intrastat_base +#: view:product.product:0 +#: view:product.template:0 +msgid "Intrastat Properties" +msgstr "Propriétés DEB/DES" + +#. module: intrastat_base +#: view:res.company:0 +msgid "Intrastat Settings" +msgstr "Configuration DEB/DES" + +#. module: intrastat_base +#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root +msgid "Intrastat reporting" +msgstr "DEB et DES" + +#. module: intrastat_base +#: field:product.template,is_accessory_cost:0 +msgid "Is accessory cost" +msgstr "Frais accessoires" + +#. module: intrastat_base +#: help:res.company,intrastat_remind_user_ids:0 +msgid "List of OpenERP users who will receive a notification to remind them about the Intrastat declaration." +msgstr "Liste d'utilisateurs OpenERP qui recevront le rappel pour la DEB et/ou la DES." + +#. module: intrastat_base +#: field:res.company,intrastat_email_list:0 +msgid "List of emails of Users Receiving the Intrastat Reminder" +msgstr "Liste des emails d'utilisateurs qui recevront le rappel pour la DEB et/ou la DES" + +#. module: intrastat_base +#: code:addons/intrastat_base/company.py:59 +#, python-format +msgid "Missing e-mail address on user '%s'." +msgstr "Adresse e-mail manquante sur l'utilisateur '%s'." + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_res_partner +msgid "Partner" +msgstr "Partenaire" + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_product_template +msgid "Product Template" +msgstr "Modèle d'article" + +#. module: intrastat_base +#: view:res.country:0 +msgid "Search Countries" +msgstr "Recherche des pays" + +#. module: intrastat_base +#: help:res.country,intrastat:0 +msgid "Set to True for all European Union countries." +msgstr "A cocher pour tous les pays de l'Union Européenne." #. module: intrastat_base #: model:product.template,name:intrastat_base.shipping_costs_exclude_product_template @@ -164,13 +145,47 @@ msgid "Shipping costs" msgstr "Frais de port" #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:85 +#: model:ir.model,name:intrastat_base.model_account_tax +msgid "Tax" +msgstr "Taxes" + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:91 +#, python-format +msgid "The VAT number is not set for the partner '%s'." +msgstr "Le numéro de TVA n'est pas renseigné pour le partenaire '%s'." + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:83 +#, python-format +msgid "The company currency must be 'EUR', but is currently '%s'." +msgstr "La monnaie de la société doit être 'EUR', mais est actuellement '%s'." + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:78 +#, python-format +msgid "The country is not set on the company '%s'." +msgstr "Le pays n'est pas renseigné sur la société '%s'." + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:111 #, python-format msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s." msgstr "La validation du fichier XML avec le schéma XML officiel a échoué. Le fichier XML généré et le détail de l'erreur ont été écrits dans les logs du serveur. Voici le message d'erreur, qui peut vous donner une idée de la cause du problème : %s." #. module: intrastat_base -#: model:ir.model,name:intrastat_base.model_res_partner_address -msgid "Partner Addresses" -msgstr "Carnet d'adresses" +#: code:addons/intrastat_base/product.py:56 +#, python-format +msgid "The option 'Is accessory cost?' should only be activated on 'Service' products. You have activated this option for the product '%s' which is of type '%s'" +msgstr "L'option 'Frais accessoires' ne doit être activée que sur les produits de type 'Service'. Vous avez activé cette option sur le produit '%s' qui est de type '%s'" + +#. module: intrastat_base +#: field:res.company,intrastat_remind_user_ids:0 +msgid "Users Receiving the Intrastat Reminder" +msgstr "Utilisateurs qui reçoivent le rappel DEB/DES" + +#. module: intrastat_base +#: constraint:res.company:0 +msgid "error msg in raise" +msgstr "error msg in raise" diff --git a/intrastat_base/i18n/intrastat_base.pot b/intrastat_base/i18n/intrastat_base.pot index d7baf12..b170abd 100644 --- a/intrastat_base/i18n/intrastat_base.pot +++ b/intrastat_base/i18n/intrastat_base.pot @@ -4,10 +4,10 @@ # msgid "" msgstr "" -"Project-Id-Version: OpenERP Server 6.0.4\n" -"Report-Msgid-Bugs-To: support@openerp.com\n" -"POT-Creation-Date: 2012-06-05 13:28+0000\n" -"PO-Revision-Date: 2012-06-05 13:28+0000\n" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-04-14 14:18+0000\n" +"PO-Revision-Date: 2014-04-14 14:18+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -16,106 +16,13 @@ msgstr "" "Plural-Forms: \n" #. module: intrastat_base -#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root -msgid "Intrastat reporting" +#: help:product.template,is_accessory_cost:0 +msgid "Activate this option for shipping costs, packaging costs and all services related to the sale of products. This option is used for Intrastat reports." msgstr "" #. module: intrastat_base -#: sql_constraint:res.country:0 -msgid "The code of the country must be unique !" -msgstr "" - -#. module: intrastat_base -#: constraint:product.template:0 -msgid "Error: The default UOM and the purchase UOM must be in the same category." -msgstr "" - -#. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:64 -#: code:addons/intrastat_base/intrastat_common.py:70 -#: code:addons/intrastat_base/intrastat_common.py:85 -#: code:addons/intrastat_base/intrastat_common.py:93 -#: code:addons/intrastat_base/product.py:41 -#, python-format -msgid "Error :" -msgstr "" - -#. module: intrastat_base -#: model:ir.model,name:intrastat_base.model_account_tax -msgid "account.tax" -msgstr "" - -#. module: intrastat_base -#: field:account.tax,exclude_from_intrastat_if_present:0 -msgid "Exclude invoice line from intrastat if this tax is present" -msgstr "" - -#. module: intrastat_base -#: help:res.country,intrastat:0 -msgid "Set as True for countries that must be selected in the intrastat reports, i.e. for all European Union countries other than your own country." -msgstr "" - -#. module: intrastat_base -#: view:product.product:0 -#: view:product.template:0 -msgid "Intrastat properties" -msgstr "" - -#. module: intrastat_base -#: model:ir.module.module,description:intrastat_base.module_meta_information -msgid "This module contains the common functions for 2 other modules :\n" -"- l10n_fr_intrastat_service : the module for the \"Déclaration Européenne des Services\" (DES)\n" -"- l10n_fr_intrastat_product : the module for the \"Déclaration d'Echange de Biens\" (DEB)\n" -"This module is not usefull if it's not used together with one of those 2 modules.\n" -"\n" -"This module doesn't have any France-specific stuff. So it can be used as a basis for other intrastat modules for other EU countries.\n" -"\n" -"WARNING : this module conflicts with the module \"report_intrastat\" from the addons. If you have already installed the module \"report_intrastat\", you should uninstall it first before installing this module.\n" -"\n" -"Please contact Alexis de Lattre from Akretion for any help or question about this module.\n" -" " -msgstr "" - -#. module: intrastat_base -#: sql_constraint:res.country:0 -msgid "The name of the country must be unique !" -msgstr "" - -#. module: intrastat_base -#: constraint:product.template:0 -msgid "Error msg is in raise" -msgstr "" - -#. module: intrastat_base -#: help:account.tax,exclude_from_intrastat_if_present:0 -msgid "If this tax is present on an invoice line, this invoice line will be skipped when generating Intrastat Product or Service lines from invoices." -msgstr "" - -#. module: intrastat_base -#: field:product.template,is_accessory_cost:0 -msgid "Is accessory cost" -msgstr "" - -#. module: intrastat_base -#: field:res.country,intrastat:0 -msgid "Intrastat country" -msgstr "" - -#. module: intrastat_base -#: help:product.template,exclude_from_intrastat:0 -msgid "If set to True, the product or service will not be taken into account for Intrastat Product or Service reports. So you should leave this field to False unless you have a very good reason." -msgstr "" - -#. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:64 -#, python-format -msgid "The company currency must be 'EUR', but is currently '%s'." -msgstr "" - -#. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:70 -#, python-format -msgid "The VAT number is not set for the partner '%s'." +#: view:res.company:0 +msgid "Common Intrastat Settings" msgstr "" #. module: intrastat_base @@ -123,19 +30,36 @@ msgstr "" msgid "Common functions for intrastat reports for products and services" msgstr "" +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_res_company +msgid "Companies" +msgstr "" + #. module: intrastat_base #: model:ir.model,name:intrastat_base.model_res_country msgid "Country" msgstr "" #. module: intrastat_base -#: model:ir.model,name:intrastat_base.model_product_template -msgid "Product Template" +#: view:res.country:0 +#: field:res.country,intrastat:0 +msgid "EU Country" msgstr "" #. module: intrastat_base -#: model:ir.module.module,shortdesc:intrastat_base.module_meta_information -msgid "Base module for Intrastat reporting" +#: code:addons/intrastat_base/company.py:58 +#: code:addons/intrastat_base/intrastat_common.py:77 +#: code:addons/intrastat_base/intrastat_common.py:82 +#: code:addons/intrastat_base/intrastat_common.py:90 +#: code:addons/intrastat_base/intrastat_common.py:110 +#: code:addons/intrastat_base/product.py:51 +#, python-format +msgid "Error :" +msgstr "" + +#. module: intrastat_base +#: constraint:product.template:0 +msgid "Error msg is in raise" msgstr "" #. module: intrastat_base @@ -144,8 +68,75 @@ msgid "Exclude from Intrastat reports" msgstr "" #. module: intrastat_base -#: help:product.template,is_accessory_cost:0 -msgid "Activate this option for shipping costs, packaging costs and all services related to the sale of products. This option is used for Intrastat reports." +#: field:account.tax,exclude_from_intrastat_if_present:0 +msgid "Exclude invoice line from intrastat if this tax is present" +msgstr "" + +#. module: intrastat_base +#: help:product.template,exclude_from_intrastat:0 +msgid "If set to True, the product or service will not be taken into account for Intrastat Product or Service reports. So you should leave this field to False unless you have a very good reason." +msgstr "" + +#. module: intrastat_base +#: help:account.tax,exclude_from_intrastat_if_present:0 +msgid "If this tax is present on an invoice line, this invoice line will be skipped when generating Intrastat Product or Service lines from invoices." +msgstr "" + +#. module: intrastat_base +#: view:product.product:0 +#: view:product.template:0 +msgid "Intrastat Properties" +msgstr "" + +#. module: intrastat_base +#: view:res.company:0 +msgid "Intrastat Settings" +msgstr "" + +#. module: intrastat_base +#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root +msgid "Intrastat reporting" +msgstr "" + +#. module: intrastat_base +#: field:product.template,is_accessory_cost:0 +msgid "Is accessory cost" +msgstr "" + +#. module: intrastat_base +#: help:res.company,intrastat_remind_user_ids:0 +msgid "List of OpenERP users who will receive a notification to remind them about the Intrastat declaration." +msgstr "" + +#. module: intrastat_base +#: field:res.company,intrastat_email_list:0 +msgid "List of emails of Users Receiving the Intrastat Reminder" +msgstr "" + +#. module: intrastat_base +#: code:addons/intrastat_base/company.py:59 +#, python-format +msgid "Missing e-mail address on user '%s'." +msgstr "" + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_res_partner +msgid "Partner" +msgstr "" + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_product_template +msgid "Product Template" +msgstr "" + +#. module: intrastat_base +#: view:res.country:0 +msgid "Search Countries" +msgstr "" + +#. module: intrastat_base +#: help:res.country,intrastat:0 +msgid "Set to True for all European Union countries." msgstr "" #. module: intrastat_base @@ -154,13 +145,47 @@ msgid "Shipping costs" msgstr "" #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:85 +#: model:ir.model,name:intrastat_base.model_account_tax +msgid "Tax" +msgstr "" + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:91 +#, python-format +msgid "The VAT number is not set for the partner '%s'." +msgstr "" + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:83 +#, python-format +msgid "The company currency must be 'EUR', but is currently '%s'." +msgstr "" + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:78 +#, python-format +msgid "The country is not set on the company '%s'." +msgstr "" + +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:111 #, python-format msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s." msgstr "" #. module: intrastat_base -#: model:ir.model,name:intrastat_base.model_res_partner_address -msgid "Partner Addresses" +#: code:addons/intrastat_base/product.py:56 +#, python-format +msgid "The option 'Is accessory cost?' should only be activated on 'Service' products. You have activated this option for the product '%s' which is of type '%s'" +msgstr "" + +#. module: intrastat_base +#: field:res.company,intrastat_remind_user_ids:0 +msgid "Users Receiving the Intrastat Reminder" +msgstr "" + +#. module: intrastat_base +#: constraint:res.company:0 +msgid "error msg in raise" msgstr "" diff --git a/intrastat_base/intrastat_common.py b/intrastat_base/intrastat_common.py index 7a21a62..2129f8d 100644 --- a/intrastat_base/intrastat_common.py +++ b/intrastat_base/intrastat_common.py @@ -2,7 +2,7 @@ ############################################################################## # # Report intrastat base module for OpenERP -# Copyright (C) 2010-2013 Akretion (http://www.akretion.com/). All rights reserved. +# Copyright (C) 2010-2013 Akretion (http://www.akretion.com/). # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -22,6 +22,7 @@ from openerp.osv import orm from openerp.tools.translate import _ +from openerp import tools from datetime import datetime from dateutil.relativedelta import relativedelta import logging @@ -31,7 +32,8 @@ logger = logging.getLogger(__name__) class report_intrastat_common(orm.TransientModel): _name = "report.intrastat.common" - _description = "Common functions for intrastat reports for products and services" + _description = "Common functions for intrastat reports for products " + "and services" def _compute_numbers(self, cr, uid, ids, object, context=None): result = {} @@ -41,14 +43,19 @@ class report_intrastat_common(orm.TransientModel): for line in intrastat.intrastat_line_ids: total_amount += line.amount_company_currency num_lines += 1 - result[intrastat.id] = {'num_lines': num_lines, 'total_amount': total_amount} + result[intrastat.id] = { + 'num_lines': num_lines, + 'total_amount': total_amount, + } return result def _compute_dates(self, cr, uid, ids, object, context=None): result = {} for intrastat in object.browse(cr, uid, ids, context=context): - start_date_datetime = datetime.strptime(intrastat.start_date, '%Y-%m-%d') - end_date_str = datetime.strftime(start_date_datetime + relativedelta(day=31), '%Y-%m-%d') + start_date_datetime = datetime.strptime( + intrastat.start_date, '%Y-%m-%d') + end_date_str = datetime.strftime( + start_date_datetime + relativedelta(day=31), '%Y-%m-%d') result[intrastat.id] = { 'end_date': end_date_str, 'year_month': start_date_datetime.strftime('%Y-%m'), @@ -57,53 +64,89 @@ class report_intrastat_common(orm.TransientModel): def _check_start_date(self, cr, uid, ids, object, context=None): '''Check that the start date is the first day of the month''' - for date_to_check in object.read(cr, uid, ids, ['start_date'], context=context): - datetime_to_check = datetime.strptime(date_to_check['start_date'], '%Y-%m-%d') + for date_to_check in object.read( + cr, uid, ids, ['start_date'], context=context): + datetime_to_check = datetime.strptime( + date_to_check['start_date'], '%Y-%m-%d') if datetime_to_check.day != 1: return False return True def _check_generate_lines(self, cr, uid, intrastat, context=None): if not intrastat.company_id.country_id: - raise orm.except_orm(_('Error :'), _("The country is not set on the company '%s'.") % intrastat.company_id.name) + raise orm.except_orm( + _('Error :'), + _("The country is not set on the company '%s'.") + % intrastat.company_id.name) if not intrastat.currency_id.name == 'EUR': - raise orm.except_orm(_('Error :'), _("The company currency must be 'EUR', but is currently '%s'.") % intrastat.currency_id.name) + raise orm.except_orm( + _('Error :'), + _("The company currency must be 'EUR', but is currently '%s'.") + % intrastat.currency_id.name) return True def _check_generate_xml(self, cr, uid, intrastat, context=None): if not intrastat.company_id.partner_id.vat: - raise orm.except_orm(_('Error :'), _("The VAT number is not set for the partner '%s'.") % intrastat.company_id.partner_id.name) + raise orm.except_orm( + _('Error :'), + _("The VAT number is not set for the partner '%s'.") + % intrastat.company_id.partner_id.name) return True - def _check_xml_schema(self, cr, uid, xml_root, xml_string, xsd, context=None): + def _check_xml_schema( + self, cr, uid, xml_root, xml_string, xsd_file, context=None): '''Validate the XML file against the XSD''' from lxml import etree - official_des_xml_schema = etree.XMLSchema(etree.fromstring(xsd)) + xsd_etree_obj = etree.parse( + tools.file_open(xsd_file)) + official_schema = etree.XMLSchema(xsd_etree_obj) try: - official_des_xml_schema.assertValid(xml_root) - except Exception, e: # if the validation of the XSD fails, we arrive here - import logging + official_schema.assertValid(xml_root) + except Exception, e: + # if the validation of the XSD fails, we arrive here _logger = logging.getLogger(__name__) - _logger.warning("The XML file is invalid against the XML Schema Definition") + _logger.warning( + "The XML file is invalid against the XML Schema Definition") _logger.warning(xml_string) _logger.warning(e) - raise orm.except_orm(_('Error :'), _('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s.') % str(e)) + raise orm.except_orm( + _('Error :'), + _("The generated XML file is not valid against the official " + "XML Schema Definition. The generated XML file and the " + "full error have been written in the server logs. " + "Here is the error, which may give you an idea on the " + "cause of the problem : %s.") + % str(e)) return True - def _attach_xml_file(self, cr, uid, ids, object, xml_string, start_date_datetime, declaration_name, context=None): - '''Attach the XML file to the report_intrastat_product/service object''' + def _attach_xml_file( + self, cr, uid, ids, object, xml_string, start_date_datetime, + declaration_name, context=None): + '''Attach the XML file to the report_intrastat_product/service ''' + '''object''' import base64 assert len(ids) == 1, "Only one ID accepted" - filename = datetime.strftime(start_date_datetime, '%Y-%m') + '_' + declaration_name + '.xml' - attach_obj = self.pool.get('ir.attachment') + filename = '%s_%s.xml' % ( + datetime.strftime(start_date_datetime, '%Y-%m'), + declaration_name) if not context: context = {} - context.update({'default_res_id': ids[0], 'default_res_model': object._name}) - attach_id = attach_obj.create(cr, uid, {'name': filename, 'datas': base64.encodestring(xml_string), 'datas_fname': filename}, context=context) + context.update({ + 'default_res_id': ids[0], + 'default_res_model': object._name + }) + attach_id = self.pool['ir.attachment'].create( + cr, uid, { + 'name': filename, + 'datas': base64.encodestring(xml_string), + 'datas_fname': filename}, + context=context) return attach_id - def _open_attach_view(self, cr, uid, attach_id, title='XML file', context=None): - '''Returns an action which opens the form view of the corresponding attachement''' + def _open_attach_view( + self, cr, uid, attach_id, title='XML file', context=None): + '''Returns an action which opens the form view of the ''' + '''corresponding attachement''' action = { 'name': title, 'view_type': 'form', @@ -117,23 +160,30 @@ class report_intrastat_common(orm.TransientModel): } return action - def partner_on_change(self, cr, uid, ids, partner_id=False): + def partner_on_change(self, cr, uid, ids, partner_id=False, context=None): result = {} result['value'] = {} if partner_id: - company = self.pool.get('res.partner').read(cr, uid, partner_id, ['vat']) - result['value'].update({'partner_vat': company['vat']}) + company = self.pool['res.partner'].read( + cr, uid, partner_id, ['vat'], context=context) + result['value']['partner_vat'] = company['vat'] return result - def send_reminder_email(self, cr, uid, company, module_name, template_xmlid, intrastat_id, context=None): - template_data = self.pool['ir.model.data'].get_object_reference(cr, uid, module_name, template_xmlid) - if template_data and template_data[0] == 'email.template': - template_id = template_data[1] - else: - raise orm.except_orm(_('Error :'), _("Wrong model for XMLID '%s.%s': model is '%s' and it should be 'email.template'.") % (module_name, template_xmlid, template_data[0])) + def send_reminder_email( + self, cr, uid, company, module_name, template_xmlid, + intrastat_id, context=None): + template_model, template_id =\ + self.pool['ir.model.data'].get_object_reference( + cr, uid, module_name, template_xmlid) + assert template_model == 'email.template', 'Wrong model' if company.intrastat_remind_user_ids: - self.pool['email.template'].send_mail(cr, uid, template_id, intrastat_id, context=context) - logger.info('Intrastat Reminder email has been sent (XMLID: %s).' % template_xmlid) + self.pool['email.template'].send_mail( + cr, uid, template_id, intrastat_id, context=context) + logger.info( + 'Intrastat Reminder email has been sent (XMLID: %s).' + % template_xmlid) else: - logger.warning('The list of users receiving the Intrastat Reminder is empty on company %s' % company.name) + logger.warning( + 'The list of users receiving the Intrastat Reminder is empty ' + 'on company %s' % company.name) return True diff --git a/intrastat_base/product.py b/intrastat_base/product.py index 60132f0..7181706 100644 --- a/intrastat_base/product.py +++ b/intrastat_base/product.py @@ -27,8 +27,17 @@ from openerp.tools.translate import _ class product_template(orm.Model): _inherit = "product.template" _columns = { - 'exclude_from_intrastat': fields.boolean('Exclude from Intrastat reports', help="If set to True, the product or service will not be taken into account for Intrastat Product or Service reports. So you should leave this field to False unless you have a very good reason."), - 'is_accessory_cost': fields.boolean('Is accessory cost', help='Activate this option for shipping costs, packaging costs and all services related to the sale of products. This option is used for Intrastat reports.'), + 'exclude_from_intrastat': fields.boolean( + 'Exclude from Intrastat reports', + help="If set to True, the product or service will not be " + "taken into account for Intrastat Product or Service reports. " + "So you should leave this field to False unless you have a " + "very good reason."), + 'is_accessory_cost': fields.boolean( + 'Is accessory cost', + help="Activate this option for shipping costs, packaging " + "costs and all services related to the sale of products. " + "This option is used for Intrastat reports."), } _defaults = { @@ -38,7 +47,13 @@ class product_template(orm.Model): def _check_accessory_cost(self, cr, uid, ids): for product in self.browse(cr, uid, ids): if product.is_accessory_cost and product.type != 'service': - raise orm.except_orm(_('Error :'), _("The option 'Is accessory cost?' should only be activated on 'Service' products. You have activated this option for the product '%s' which is of type '%s'" % (product.name, product.type))) + raise orm.except_orm( + _('Error :'), + _("The option 'Is accessory cost?' should only be " + "activated on 'Service' products. You have activated " + "this option for the product '%s' which is of type " + "'%s'" + % (product.name, product.type))) return True _constraints = [ diff --git a/intrastat_base/product_view.xml b/intrastat_base/product_view.xml index fd7c2d4..a551868 100644 --- a/intrastat_base/product_view.xml +++ b/intrastat_base/product_view.xml @@ -18,7 +18,8 @@ - + @@ -33,7 +34,8 @@ - + diff --git a/intrastat_base/tax.py b/intrastat_base/tax.py index 5e933d1..fae6a3d 100644 --- a/intrastat_base/tax.py +++ b/intrastat_base/tax.py @@ -2,7 +2,7 @@ ############################################################################## # # Report intrastat base module for OpenERP -# Copyright (C) 2011-2013 Akretion (http://www.akretion.com). All Rights Reserved +# Copyright (C) 2011-2013 Akretion (http://www.akretion.com). # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -25,6 +25,11 @@ from openerp.osv import orm, fields class account_tax(orm.Model): _inherit = "account.tax" + _columns = { - 'exclude_from_intrastat_if_present': fields.boolean('Exclude invoice line from intrastat if this tax is present', help="If this tax is present on an invoice line, this invoice line will be skipped when generating Intrastat Product or Service lines from invoices."), + 'exclude_from_intrastat_if_present': fields.boolean( + 'Exclude invoice line from intrastat if this tax is present', + help="If this tax is present on an invoice line, this invoice " + "line will be skipped when generating Intrastat Product or " + "Service lines from invoices."), } From 38cb4e6269b4bfc99daf8b74a6a95dfae1cf7a37 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Mon, 23 Jun 2014 12:12:40 +0200 Subject: [PATCH 05/44] [MIG] intrastat_base: Migration to 8.0 * Add intrastat_type_data and update demo data accordingly Remove version="7.0" from form views Add ondelete='restrict' on M2O pointing to intrastat.type Add graph views on intrastat.product and intrastat.service... because Odoo v8 graph views are so cool ! :) * When the obligation level for import is none, the type of the DEB is automatically set to export. [FIX] country -> country_id type='string' -> type='char' (v8 only accepts char) Change "error msg in raise", because v8 displays this to the user Remove statistical_pricelist_id from demo data Harmonize labels of button between DEB and DES * Add module intrastat_product. Rename report.intrastat.product to l10n.fr.report.intrastat.product (same for service and for lines) + migration scripts * intrastat_base + l10n_fr_intrastat_service : port to new API --- intrastat_base/__init__.py | 4 +- intrastat_base/__openerp__.py | 5 +- intrastat_base/company.py | 70 ++++----- intrastat_base/company_view.xml | 4 +- intrastat_base/country.py | 19 +-- intrastat_base/country_view.xml | 9 +- intrastat_base/i18n/fr_FR.po | 2 +- intrastat_base/i18n/intrastat_base.pot | 2 +- intrastat_base/intrastat_common.py | 189 +++++++++++-------------- intrastat_base/intrastat_demo.xml | 2 +- intrastat_base/intrastat_menu.xml | 4 +- intrastat_base/product.py | 61 ++++---- intrastat_base/product_view.xml | 27 +--- intrastat_base/tax.py | 20 ++- intrastat_base/tax_view.xml | 7 +- 15 files changed, 177 insertions(+), 248 deletions(-) diff --git a/intrastat_base/__init__.py b/intrastat_base/__init__.py index 3070e32..21b2067 100644 --- a/intrastat_base/__init__.py +++ b/intrastat_base/__init__.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Report intrastat base module for OpenERP -# Copyright (C) 2011-2013 Akretion (http://www.akretion.com) +# Report intrastat base module for Odoo +# Copyright (C) 2011-2014 Akretion (http://www.akretion.com) # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify diff --git a/intrastat_base/__openerp__.py b/intrastat_base/__openerp__.py index 9661bd8..179cb4a 100644 --- a/intrastat_base/__openerp__.py +++ b/intrastat_base/__openerp__.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Report intrastat base module for OpenERP -# Copyright (C) 2011-2013 Akretion (http://www.akretion.com) +# Report intrastat base module for Odoo +# Copyright (C) 2011-2014 Akretion (http://www.akretion.com) # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -52,5 +52,4 @@ Please contact Alexis de Lattre from Akretion for ], 'demo': ['intrastat_demo.xml'], 'installable': True, - 'active': False, } diff --git a/intrastat_base/company.py b/intrastat_base/company.py index 030101f..9fea8e4 100644 --- a/intrastat_base/company.py +++ b/intrastat_base/company.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Intrastat base module for OpenERP -# Copyright (C) 2013 Akretion (http://www.akretion.com) +# Intrastat base module for Odoo +# Copyright (C) 2013-2014 Akretion (http://www.akretion.com) # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -20,47 +20,37 @@ # ############################################################################## -from openerp.osv import orm, fields -from openerp.tools.translate import _ +from openerp import models, fields, api, _ +from openerp.exceptions import ValidationError -class res_company(orm.Model): +class ResCompany(models.Model): _inherit = "res.company" - def _compute_intrastat_email_list( - self, cr, uid, ids, name, arg, context=None): - result = {} - for company in self.browse(cr, uid, ids, context=context): - result[company.id] = '' - for user in company.intrastat_remind_user_ids: - if result[company.id]: - result[company.id] += ',%s' % (user.email) - else: - result[company.id] = user.email - return result + @api.one + @api.depends( + 'intrastat_remind_user_ids', 'intrastat_remind_user_ids.email') + def _compute_intrastat_email_list(self): + emails = [] + for user in self.intrastat_remind_user_ids: + if user.email: + emails.append(user.email) + self.intrastat_email_list = ','.join(emails) - _columns = { - 'intrastat_remind_user_ids': fields.many2many( - 'res.users', id1='company_id', id2='user_id', - string="Users Receiving the Intrastat Reminder", - help="List of OpenERP users who will receive a notification to " - "remind them about the Intrastat declaration."), - 'intrastat_email_list': fields.function( - _compute_intrastat_email_list, type='char', size=1000, - string='List of emails of Users Receiving the Intrastat Reminder'), - } + intrastat_remind_user_ids = fields.Many2many( + 'res.users', column1='company_id', column2='user_id', + string="Users Receiving the Intrastat Reminder", + help="List of OpenERP users who will receive a notification to " + "remind them about the Intrastat declaration.") + intrastat_email_list = fields.Char( + compute='_compute_intrastat_email_list', + string='List of emails of Users Receiving the Intrastat Reminder') - def _check_intrastat_remind_users(self, cr, uid, ids): - for company in self.browse(cr, uid, ids): - for user in company.intrastat_remind_user_ids: - if not user.email: - raise orm.except_orm( - _('Error :'), - _("Missing e-mail address on user '%s'.") - % (user.name)) - return True - - _constraints = [ - (_check_intrastat_remind_users, "error msg in raise", - ['intrastat_remind_user_ids']), - ] + @api.one + @api.constrains('intrastat_remind_user_ids') + def _check_intrastat_remind_users(self): + for user in self.intrastat_remind_user_ids: + if not user.email: + raise ValidationError( + _("Missing e-mail address on user '%s'.") + % (user.name)) diff --git a/intrastat_base/company_view.xml b/intrastat_base/company_view.xml index 14cf1fe..87933f4 100644 --- a/intrastat_base/company_view.xml +++ b/intrastat_base/company_view.xml @@ -1,7 +1,7 @@ @@ -9,7 +9,7 @@ - + intrastat.company.form res.company diff --git a/intrastat_base/country.py b/intrastat_base/country.py index e967e92..7f03e5d 100644 --- a/intrastat_base/country.py +++ b/intrastat_base/country.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Report intrastat base module for OpenERP -# Copyright (C) 2011-2013 Akretion (http://www.akretion.com). +# Report intrastat base module for Odoo +# Copyright (C) 2011-2014 Akretion (http://www.akretion.com). # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -20,17 +20,12 @@ # ############################################################################## -from openerp.osv import orm, fields +from openerp import models, fields -class res_country(orm.Model): +class ResCountry(models.Model): _inherit = 'res.country' - _columns = { - 'intrastat': fields.boolean( - 'EU Country', - help="Set to True for all European Union countries."), - } - _defaults = { - 'intrastat': False, - } + intrastat = fields.Boolean( + string='EU Country', + help="Set to True for all European Union countries.") diff --git a/intrastat_base/country_view.xml b/intrastat_base/country_view.xml index 2177dbb..d887a22 100644 --- a/intrastat_base/country_view.xml +++ b/intrastat_base/country_view.xml @@ -1,7 +1,7 @@ @@ -9,7 +9,7 @@ - + intrastat.base.country.tree res.country @@ -20,7 +20,7 @@ - + intrastat.base.country.form res.country @@ -32,7 +32,7 @@ - + intrastat.base.country.search res.country @@ -46,6 +46,5 @@ - diff --git a/intrastat_base/i18n/fr_FR.po b/intrastat_base/i18n/fr_FR.po index 77ac6e9..de7e5db 100644 --- a/intrastat_base/i18n/fr_FR.po +++ b/intrastat_base/i18n/fr_FR.po @@ -95,7 +95,7 @@ msgstr "Configuration DEB/DES" #. module: intrastat_base #: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root -msgid "Intrastat reporting" +msgid "Intrastat Reporting" msgstr "DEB et DES" #. module: intrastat_base diff --git a/intrastat_base/i18n/intrastat_base.pot b/intrastat_base/i18n/intrastat_base.pot index b170abd..d184def 100644 --- a/intrastat_base/i18n/intrastat_base.pot +++ b/intrastat_base/i18n/intrastat_base.pot @@ -95,7 +95,7 @@ msgstr "" #. module: intrastat_base #: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root -msgid "Intrastat reporting" +msgid "Intrastat Reporting" msgstr "" #. module: intrastat_base diff --git a/intrastat_base/intrastat_common.py b/intrastat_base/intrastat_common.py index 2129f8d..fa65afe 100644 --- a/intrastat_base/intrastat_common.py +++ b/intrastat_base/intrastat_common.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Report intrastat base module for OpenERP -# Copyright (C) 2010-2013 Akretion (http://www.akretion.com/). +# Report intrastat base module for Odoo +# Copyright (C) 2010-2014 Akretion (http://www.akretion.com/). # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -20,9 +20,9 @@ # ############################################################################## -from openerp.osv import orm -from openerp.tools.translate import _ -from openerp import tools +from openerp import models, api, tools, _ +from openerp.tools import DEFAULT_SERVER_DATE_FORMAT +from openerp.exceptions import Warning, ValidationError from datetime import datetime from dateutil.relativedelta import relativedelta import logging @@ -30,71 +30,64 @@ import logging logger = logging.getLogger(__name__) -class report_intrastat_common(orm.TransientModel): +class ReportIntrastatCommon(models.AbstractModel): _name = "report.intrastat.common" _description = "Common functions for intrastat reports for products " "and services" - def _compute_numbers(self, cr, uid, ids, object, context=None): - result = {} - for intrastat in object.browse(cr, uid, ids, context=context): - total_amount = 0.0 - num_lines = 0 - for line in intrastat.intrastat_line_ids: - total_amount += line.amount_company_currency - num_lines += 1 - result[intrastat.id] = { - 'num_lines': num_lines, - 'total_amount': total_amount, - } - return result + @api.one + @api.depends( + 'intrastat_line_ids', 'intrastat_line_ids.amount_company_currency') + def _compute_numbers(self): + total_amount = 0.0 + num_lines = 0 + for line in self.intrastat_line_ids: + total_amount += line.amount_company_currency + num_lines += 1 + self.num_lines = num_lines + self.total_amount = total_amount - def _compute_dates(self, cr, uid, ids, object, context=None): - result = {} - for intrastat in object.browse(cr, uid, ids, context=context): - start_date_datetime = datetime.strptime( - intrastat.start_date, '%Y-%m-%d') - end_date_str = datetime.strftime( - start_date_datetime + relativedelta(day=31), '%Y-%m-%d') - result[intrastat.id] = { - 'end_date': end_date_str, - 'year_month': start_date_datetime.strftime('%Y-%m'), - } - return result + @api.one + @api.depends('start_date') + def _compute_dates(self): + start_date_dt = datetime.strptime( + self.start_date, DEFAULT_SERVER_DATE_FORMAT) + self.end_date = datetime.strftime( + start_date_dt + relativedelta(day=31), DEFAULT_SERVER_DATE_FORMAT) + self.year_month = start_date_dt.strftime('%Y-%m') - def _check_start_date(self, cr, uid, ids, object, context=None): + @api.one + @api.constrains('start_date') + def _check_start_date(self): '''Check that the start date is the first day of the month''' - for date_to_check in object.read( - cr, uid, ids, ['start_date'], context=context): - datetime_to_check = datetime.strptime( - date_to_check['start_date'], '%Y-%m-%d') - if datetime_to_check.day != 1: - return False - return True + datetime_to_check = datetime.strptime( + self.start_date, DEFAULT_SERVER_DATE_FORMAT) + if datetime_to_check.day != 1: + return ValidationError( + _('The start date must be the first day of the month')) - def _check_generate_lines(self, cr, uid, intrastat, context=None): - if not intrastat.company_id.country_id: - raise orm.except_orm( - _('Error :'), + @api.one + def _check_generate_lines(self): + if not self.company_id.country_id: + raise Warning( _("The country is not set on the company '%s'.") - % intrastat.company_id.name) - if not intrastat.currency_id.name == 'EUR': - raise orm.except_orm( - _('Error :'), + % self.company_id.name) + if self.currency_id.name != 'EUR': + raise Warning( _("The company currency must be 'EUR', but is currently '%s'.") - % intrastat.currency_id.name) + % self.currency_id.name) return True - def _check_generate_xml(self, cr, uid, intrastat, context=None): - if not intrastat.company_id.partner_id.vat: - raise orm.except_orm( - _('Error :'), + @api.one + def _check_generate_xml(self): + if not self.company_id.partner_id.vat: + raise Warning( _("The VAT number is not set for the partner '%s'.") - % intrastat.company_id.partner_id.name) + % self.company_id.partner_id.name) return True - def _check_xml_schema( - self, cr, uid, xml_root, xml_string, xsd_file, context=None): + @api.model + def _check_xml_schema(self, xml_root, xml_string, xsd_file): '''Validate the XML file against the XSD''' from lxml import etree xsd_etree_obj = etree.parse( @@ -104,13 +97,12 @@ class report_intrastat_common(orm.TransientModel): official_schema.assertValid(xml_root) except Exception, e: # if the validation of the XSD fails, we arrive here - _logger = logging.getLogger(__name__) - _logger.warning( + logger = logging.getLogger(__name__) + logger.warning( "The XML file is invalid against the XML Schema Definition") - _logger.warning(xml_string) - _logger.warning(e) - raise orm.except_orm( - _('Error :'), + logger.warning(xml_string) + logger.warning(e) + raise Warning( _("The generated XML file is not valid against the official " "XML Schema Definition. The generated XML file and the " "full error have been written in the server logs. " @@ -119,39 +111,29 @@ class report_intrastat_common(orm.TransientModel): % str(e)) return True - def _attach_xml_file( - self, cr, uid, ids, object, xml_string, start_date_datetime, - declaration_name, context=None): + @api.multi + def _attach_xml_file(self, xml_string, declaration_name): '''Attach the XML file to the report_intrastat_product/service ''' '''object''' + self.ensure_one() import base64 - assert len(ids) == 1, "Only one ID accepted" - filename = '%s_%s.xml' % ( - datetime.strftime(start_date_datetime, '%Y-%m'), - declaration_name) - if not context: - context = {} - context.update({ - 'default_res_id': ids[0], - 'default_res_model': object._name - }) - attach_id = self.pool['ir.attachment'].create( - cr, uid, { - 'name': filename, - 'datas': base64.encodestring(xml_string), - 'datas_fname': filename}, - context=context) - return attach_id + filename = '%s_%s.xml' % (self.year_month, declaration_name) + attach = self.with_context( + default_res_id=self.id, + default_res_model=self._name).env['ir.attachment'].create({ + 'name': filename, + 'datas': base64.encodestring(xml_string), + 'datas_fname': filename}) + return attach.id - def _open_attach_view( - self, cr, uid, attach_id, title='XML file', context=None): + @api.model + def _open_attach_view(self, attach_id, title='XML file'): '''Returns an action which opens the form view of the ''' '''corresponding attachement''' action = { 'name': title, 'view_type': 'form', - 'view_mode': 'form,tree', - 'view_id': False, + 'view_mode': 'form', 'res_model': 'ir.attachment', 'type': 'ir.actions.act_window', 'nodestroy': True, @@ -160,30 +142,27 @@ class report_intrastat_common(orm.TransientModel): } return action - def partner_on_change(self, cr, uid, ids, partner_id=False, context=None): - result = {} - result['value'] = {} - if partner_id: - company = self.pool['res.partner'].read( - cr, uid, partner_id, ['vat'], context=context) - result['value']['partner_vat'] = company['vat'] - return result - - def send_reminder_email( - self, cr, uid, company, module_name, template_xmlid, - intrastat_id, context=None): - template_model, template_id =\ - self.pool['ir.model.data'].get_object_reference( - cr, uid, module_name, template_xmlid) - assert template_model == 'email.template', 'Wrong model' - if company.intrastat_remind_user_ids: + @api.one + def send_reminder_email(self, mail_template_xmlid): + mail_template = self.env.ref(mail_template_xmlid) + if self.company_id.intrastat_remind_user_ids: self.pool['email.template'].send_mail( - cr, uid, template_id, intrastat_id, context=context) + self._cr, self._uid, mail_template.id, self.id, + context=self._context) logger.info( 'Intrastat Reminder email has been sent (XMLID: %s).' - % template_xmlid) + % mail_template_xmlid) else: logger.warning( 'The list of users receiving the Intrastat Reminder is empty ' - 'on company %s' % company.name) + 'on company %s' % self.company_id.name) return True + + @api.multi + def unlink(self): + for intrastat in self: + if intrastat.state == 'done': + raise Warning( + _('Cannot delete the declaration %s ' + 'because it is in Done state') % self.year_month) + return super(ReportIntrastatCommon, self).unlink() diff --git a/intrastat_base/intrastat_demo.xml b/intrastat_base/intrastat_demo.xml index 07c68ab..953d92b 100644 --- a/intrastat_base/intrastat_demo.xml +++ b/intrastat_base/intrastat_demo.xml @@ -1,7 +1,7 @@ diff --git a/intrastat_base/intrastat_menu.xml b/intrastat_base/intrastat_menu.xml index 83434cb..85303c1 100644 --- a/intrastat_base/intrastat_menu.xml +++ b/intrastat_base/intrastat_menu.xml @@ -1,7 +1,7 @@ @@ -9,7 +9,7 @@ - + diff --git a/intrastat_base/product.py b/intrastat_base/product.py index 7181706..ca1652e 100644 --- a/intrastat_base/product.py +++ b/intrastat_base/product.py @@ -2,7 +2,7 @@ ############################################################################## # # Report intrastat base module for OpenERP -# Copyright (C) 2010-2013 Akretion (http://www.akretion.com/) +# Copyright (C) 2010-2014 Akretion (http://www.akretion.com/) # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -20,43 +20,32 @@ # ############################################################################## -from openerp.osv import orm, fields -from openerp.tools.translate import _ +from openerp import models, fields, api, _ +from openerp.exceptions import ValidationError -class product_template(orm.Model): +class ProductTemplate(models.Model): _inherit = "product.template" - _columns = { - 'exclude_from_intrastat': fields.boolean( - 'Exclude from Intrastat reports', - help="If set to True, the product or service will not be " - "taken into account for Intrastat Product or Service reports. " - "So you should leave this field to False unless you have a " - "very good reason."), - 'is_accessory_cost': fields.boolean( - 'Is accessory cost', - help="Activate this option for shipping costs, packaging " - "costs and all services related to the sale of products. " - "This option is used for Intrastat reports."), - } - _defaults = { - 'exclude_from_intrastat': False, - } + exclude_from_intrastat = fields.Boolean( + string='Exclude from Intrastat reports', + help="If set to True, the product or service will not be " + "taken into account for Intrastat Product or Service reports. " + "So you should leave this field to False unless you have a " + "very good reason.") + is_accessory_cost = fields.Boolean( + string='Is accessory cost', + help="Activate this option for shipping costs, packaging " + "costs and all services related to the sale of products. " + "This option is used for Intrastat reports.") - def _check_accessory_cost(self, cr, uid, ids): - for product in self.browse(cr, uid, ids): - if product.is_accessory_cost and product.type != 'service': - raise orm.except_orm( - _('Error :'), - _("The option 'Is accessory cost?' should only be " - "activated on 'Service' products. You have activated " - "this option for the product '%s' which is of type " - "'%s'" - % (product.name, product.type))) - return True - - _constraints = [ - (_check_accessory_cost, "Error msg is in raise", - ['is_accessory_cost', 'type']) - ] + @api.one + @api.constrains('type', 'is_accessory_cost') + def _check_accessory_cost(self): + if self.is_accessory_cost and self.type != 'service': + raise ValidationError( + _("The option 'Is accessory cost?' should only be " + "activated on 'Service' products. You have activated " + "this option for the product '%s' which is of type " + "'%s'" + % (self.name, self.type))) diff --git a/intrastat_base/product_view.xml b/intrastat_base/product_view.xml index a551868..dc61ca5 100644 --- a/intrastat_base/product_view.xml +++ b/intrastat_base/product_view.xml @@ -1,7 +1,7 @@ @@ -9,11 +9,10 @@ - - - intrastat.base.product.normal.form - product.product - + + intrastat.base.product.template.form + product.template + @@ -25,21 +24,5 @@ - - - intrastat.base.product.template.form - product.template - - - - - - - - - - - diff --git a/intrastat_base/tax.py b/intrastat_base/tax.py index fae6a3d..2b98678 100644 --- a/intrastat_base/tax.py +++ b/intrastat_base/tax.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Report intrastat base module for OpenERP -# Copyright (C) 2011-2013 Akretion (http://www.akretion.com). +# Report intrastat base module for Odoo +# Copyright (C) 2011-2014 Akretion (http://www.akretion.com). # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -20,16 +20,14 @@ # ############################################################################## -from openerp.osv import orm, fields +from openerp import models, fields -class account_tax(orm.Model): +class AccountTax(models.Model): _inherit = "account.tax" - _columns = { - 'exclude_from_intrastat_if_present': fields.boolean( - 'Exclude invoice line from intrastat if this tax is present', - help="If this tax is present on an invoice line, this invoice " - "line will be skipped when generating Intrastat Product or " - "Service lines from invoices."), - } + exclude_from_intrastat_if_present = fields.Boolean( + string='Exclude invoice line from intrastat if this tax is present', + help="If this tax is present on an invoice line, this invoice " + "line will be skipped when generating Intrastat Product or " + "Service lines from invoices.") diff --git a/intrastat_base/tax_view.xml b/intrastat_base/tax_view.xml index c481490..5defe29 100644 --- a/intrastat_base/tax_view.xml +++ b/intrastat_base/tax_view.xml @@ -1,7 +1,7 @@ @@ -10,17 +10,14 @@ - + intrastat.base.tax account.tax - form - - From a09875399302afc1ce48fc69e337b4dcddf4d25c Mon Sep 17 00:00:00 2001 From: Ronald Portier Date: Wed, 4 Feb 2015 20:11:31 +0100 Subject: [PATCH 06/44] Make dutch ICP report workable on odoo 8.0 [FIX] Some small changes in base, to make check_generate_lines better reusable (no need to force currency field on report), and do away with '_' before method name, as method should not be private, as it is called from other classes. --- intrastat_base/intrastat_common.py | 199 +++++++++++++++++------------ 1 file changed, 115 insertions(+), 84 deletions(-) diff --git a/intrastat_base/intrastat_common.py b/intrastat_base/intrastat_common.py index fa65afe..47c10ac 100644 --- a/intrastat_base/intrastat_common.py +++ b/intrastat_base/intrastat_common.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Report intrastat base module for Odoo -# Copyright (C) 2010-2014 Akretion (http://www.akretion.com/). +# Report intrastat base module for OpenERP +# Copyright (C) 2010-2013 Akretion (http://www.akretion.com/). # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -20,9 +20,9 @@ # ############################################################################## -from openerp import models, api, tools, _ -from openerp.tools import DEFAULT_SERVER_DATE_FORMAT -from openerp.exceptions import Warning, ValidationError +from openerp.osv import orm +from openerp.tools.translate import _ +from openerp import tools from datetime import datetime from dateutil.relativedelta import relativedelta import logging @@ -30,64 +30,81 @@ import logging logger = logging.getLogger(__name__) -class ReportIntrastatCommon(models.AbstractModel): +class report_intrastat_common(orm.TransientModel): _name = "report.intrastat.common" _description = "Common functions for intrastat reports for products " "and services" - @api.one - @api.depends( - 'intrastat_line_ids', 'intrastat_line_ids.amount_company_currency') - def _compute_numbers(self): - total_amount = 0.0 - num_lines = 0 - for line in self.intrastat_line_ids: - total_amount += line.amount_company_currency - num_lines += 1 - self.num_lines = num_lines - self.total_amount = total_amount + def _compute_numbers(self, cr, uid, ids, object, context=None): + result = {} + for intrastat in object.browse(cr, uid, ids, context=context): + total_amount = 0.0 + num_lines = 0 + for line in intrastat.intrastat_line_ids: + total_amount += line.amount_company_currency + num_lines += 1 + result[intrastat.id] = { + 'num_lines': num_lines, + 'total_amount': total_amount, + } + return result - @api.one - @api.depends('start_date') - def _compute_dates(self): - start_date_dt = datetime.strptime( - self.start_date, DEFAULT_SERVER_DATE_FORMAT) - self.end_date = datetime.strftime( - start_date_dt + relativedelta(day=31), DEFAULT_SERVER_DATE_FORMAT) - self.year_month = start_date_dt.strftime('%Y-%m') + def _compute_dates(self, cr, uid, ids, object, context=None): + result = {} + for intrastat in object.browse(cr, uid, ids, context=context): + start_date_datetime = datetime.strptime( + intrastat.start_date, '%Y-%m-%d') + end_date_str = datetime.strftime( + start_date_datetime + relativedelta(day=31), '%Y-%m-%d') + result[intrastat.id] = { + 'end_date': end_date_str, + 'year_month': start_date_datetime.strftime('%Y-%m'), + } + return result - @api.one - @api.constrains('start_date') - def _check_start_date(self): + def _check_start_date(self, cr, uid, ids, object, context=None): '''Check that the start date is the first day of the month''' - datetime_to_check = datetime.strptime( - self.start_date, DEFAULT_SERVER_DATE_FORMAT) - if datetime_to_check.day != 1: - return ValidationError( - _('The start date must be the first day of the month')) + for date_to_check in object.read( + cr, uid, ids, ['start_date'], context=context): + datetime_to_check = datetime.strptime( + date_to_check['start_date'], '%Y-%m-%d') + if datetime_to_check.day != 1: + return False + return True - @api.one - def _check_generate_lines(self): - if not self.company_id.country_id: - raise Warning( + def check_generate_lines(self, cr, uid, intrastat, context=None): + """Check wether all requirements are met for generating lines.""" + if not intrastat.company_id: + # Should not be possible, but just in case: + raise orm.except_orm( + _('Error :'), + _("Company not yet set on intrastat report.") + ) + company_obj = intrastat.company_id # Simplify references + if not company_obj.country_id: + raise orm.except_orm( + _('Error :'), _("The country is not set on the company '%s'.") - % self.company_id.name) - if self.currency_id.name != 'EUR': - raise Warning( + % company_obj.name + ) + if not company_obj.currency_id.name == 'EUR': + raise orm.except_orm( + _('Error :'), _("The company currency must be 'EUR', but is currently '%s'.") - % self.currency_id.name) + % company_obj.currency_id.name + ) return True - @api.one - def _check_generate_xml(self): - if not self.company_id.partner_id.vat: - raise Warning( + def _check_generate_xml(self, cr, uid, intrastat, context=None): + if not intrastat.company_id.partner_id.vat: + raise orm.except_orm( + _('Error :'), _("The VAT number is not set for the partner '%s'.") - % self.company_id.partner_id.name) + % intrastat.company_id.partner_id.name) return True - @api.model - def _check_xml_schema(self, xml_root, xml_string, xsd_file): + def _check_xml_schema( + self, cr, uid, xml_root, xml_string, xsd_file, context=None): '''Validate the XML file against the XSD''' from lxml import etree xsd_etree_obj = etree.parse( @@ -97,12 +114,13 @@ class ReportIntrastatCommon(models.AbstractModel): official_schema.assertValid(xml_root) except Exception, e: # if the validation of the XSD fails, we arrive here - logger = logging.getLogger(__name__) - logger.warning( + _logger = logging.getLogger(__name__) + _logger.warning( "The XML file is invalid against the XML Schema Definition") - logger.warning(xml_string) - logger.warning(e) - raise Warning( + _logger.warning(xml_string) + _logger.warning(e) + raise orm.except_orm( + _('Error :'), _("The generated XML file is not valid against the official " "XML Schema Definition. The generated XML file and the " "full error have been written in the server logs. " @@ -111,29 +129,39 @@ class ReportIntrastatCommon(models.AbstractModel): % str(e)) return True - @api.multi - def _attach_xml_file(self, xml_string, declaration_name): + def _attach_xml_file( + self, cr, uid, ids, object, xml_string, start_date_datetime, + declaration_name, context=None): '''Attach the XML file to the report_intrastat_product/service ''' '''object''' - self.ensure_one() import base64 - filename = '%s_%s.xml' % (self.year_month, declaration_name) - attach = self.with_context( - default_res_id=self.id, - default_res_model=self._name).env['ir.attachment'].create({ - 'name': filename, - 'datas': base64.encodestring(xml_string), - 'datas_fname': filename}) - return attach.id + assert len(ids) == 1, "Only one ID accepted" + filename = '%s_%s.xml' % ( + datetime.strftime(start_date_datetime, '%Y-%m'), + declaration_name) + if not context: + context = {} + context.update({ + 'default_res_id': ids[0], + 'default_res_model': object._name + }) + attach_id = self.pool['ir.attachment'].create( + cr, uid, { + 'name': filename, + 'datas': base64.encodestring(xml_string), + 'datas_fname': filename}, + context=context) + return attach_id - @api.model - def _open_attach_view(self, attach_id, title='XML file'): + def _open_attach_view( + self, cr, uid, attach_id, title='XML file', context=None): '''Returns an action which opens the form view of the ''' '''corresponding attachement''' action = { 'name': title, 'view_type': 'form', - 'view_mode': 'form', + 'view_mode': 'form,tree', + 'view_id': False, 'res_model': 'ir.attachment', 'type': 'ir.actions.act_window', 'nodestroy': True, @@ -142,27 +170,30 @@ class ReportIntrastatCommon(models.AbstractModel): } return action - @api.one - def send_reminder_email(self, mail_template_xmlid): - mail_template = self.env.ref(mail_template_xmlid) - if self.company_id.intrastat_remind_user_ids: + def partner_on_change(self, cr, uid, ids, partner_id=False, context=None): + result = {} + result['value'] = {} + if partner_id: + company = self.pool['res.partner'].read( + cr, uid, partner_id, ['vat'], context=context) + result['value']['partner_vat'] = company['vat'] + return result + + def send_reminder_email( + self, cr, uid, company, module_name, template_xmlid, + intrastat_id, context=None): + template_model, template_id =\ + self.pool['ir.model.data'].get_object_reference( + cr, uid, module_name, template_xmlid) + assert template_model == 'email.template', 'Wrong model' + if company.intrastat_remind_user_ids: self.pool['email.template'].send_mail( - self._cr, self._uid, mail_template.id, self.id, - context=self._context) + cr, uid, template_id, intrastat_id, context=context) logger.info( 'Intrastat Reminder email has been sent (XMLID: %s).' - % mail_template_xmlid) + % template_xmlid) else: logger.warning( 'The list of users receiving the Intrastat Reminder is empty ' - 'on company %s' % self.company_id.name) + 'on company %s' % company.name) return True - - @api.multi - def unlink(self): - for intrastat in self: - if intrastat.state == 'done': - raise Warning( - _('Cannot delete the declaration %s ' - 'because it is in Done state') % self.year_month) - return super(ReportIntrastatCommon, self).unlink() From c3f32d3a6566e2bf1c0736346b1bdddbcfd179b4 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Sat, 7 Feb 2015 11:36:42 +0100 Subject: [PATCH 07/44] Continue the port to the new API Access for intrastat report to accounting user and not only accounting manager. --- intrastat_base/__openerp__.py | 3 +- intrastat_base/intrastat_common.py | 195 ++++++++++++----------------- 2 files changed, 81 insertions(+), 117 deletions(-) diff --git a/intrastat_base/__openerp__.py b/intrastat_base/__openerp__.py index 179cb4a..e795155 100644 --- a/intrastat_base/__openerp__.py +++ b/intrastat_base/__openerp__.py @@ -2,7 +2,7 @@ ############################################################################## # # Report intrastat base module for Odoo -# Copyright (C) 2011-2014 Akretion (http://www.akretion.com) +# Copyright (C) 2011-2015 Akretion (http://www.akretion.com) # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -20,7 +20,6 @@ # ############################################################################## - { 'name': 'Intrastat Reporting Base', 'version': '1.1', diff --git a/intrastat_base/intrastat_common.py b/intrastat_base/intrastat_common.py index 47c10ac..b6d8b2f 100644 --- a/intrastat_base/intrastat_common.py +++ b/intrastat_base/intrastat_common.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Report intrastat base module for OpenERP -# Copyright (C) 2010-2013 Akretion (http://www.akretion.com/). +# Report intrastat base module for Odoo +# Copyright (C) 2010-2014 Akretion (http://www.akretion.com/). # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -20,9 +20,8 @@ # ############################################################################## -from openerp.osv import orm -from openerp.tools.translate import _ -from openerp import tools +from openerp import models, fields, api, tools, _ +from openerp.exceptions import Warning, ValidationError from datetime import datetime from dateutil.relativedelta import relativedelta import logging @@ -30,81 +29,61 @@ import logging logger = logging.getLogger(__name__) -class report_intrastat_common(orm.TransientModel): +class ReportIntrastatCommon(models.AbstractModel): _name = "report.intrastat.common" _description = "Common functions for intrastat reports for products " "and services" - def _compute_numbers(self, cr, uid, ids, object, context=None): - result = {} - for intrastat in object.browse(cr, uid, ids, context=context): - total_amount = 0.0 - num_lines = 0 - for line in intrastat.intrastat_line_ids: - total_amount += line.amount_company_currency - num_lines += 1 - result[intrastat.id] = { - 'num_lines': num_lines, - 'total_amount': total_amount, - } - return result + @api.one + @api.depends( + 'intrastat_line_ids', 'intrastat_line_ids.amount_company_currency') + def _compute_numbers(self): + total_amount = 0.0 + num_lines = 0 + for line in self.intrastat_line_ids: + total_amount += line.amount_company_currency + num_lines += 1 + self.num_lines = num_lines + self.total_amount = total_amount - def _compute_dates(self, cr, uid, ids, object, context=None): - result = {} - for intrastat in object.browse(cr, uid, ids, context=context): - start_date_datetime = datetime.strptime( - intrastat.start_date, '%Y-%m-%d') - end_date_str = datetime.strftime( - start_date_datetime + relativedelta(day=31), '%Y-%m-%d') - result[intrastat.id] = { - 'end_date': end_date_str, - 'year_month': start_date_datetime.strftime('%Y-%m'), - } - return result + @api.one + @api.depends('start_date') + def _compute_dates(self): + start_date_dt = fields.Date.from_string(self.start_date) + self.end_date = fields.Date.to_string( + start_date_dt + relativedelta(day=31)) + self.year_month = start_date_dt.strftime('%Y-%m') - def _check_start_date(self, cr, uid, ids, object, context=None): + @api.one + def _check_start_date(self): '''Check that the start date is the first day of the month''' - for date_to_check in object.read( - cr, uid, ids, ['start_date'], context=context): - datetime_to_check = datetime.strptime( - date_to_check['start_date'], '%Y-%m-%d') - if datetime_to_check.day != 1: - return False - return True + datetime_to_check = fields.Date.from_string(self.start_date) + if datetime_to_check.day != 1: + raise ValidationError( + _('The start date must be the first day of the month')) - def check_generate_lines(self, cr, uid, intrastat, context=None): - """Check wether all requirements are met for generating lines.""" - if not intrastat.company_id: - # Should not be possible, but just in case: - raise orm.except_orm( - _('Error :'), - _("Company not yet set on intrastat report.") - ) - company_obj = intrastat.company_id # Simplify references - if not company_obj.country_id: - raise orm.except_orm( - _('Error :'), + @api.one + def _check_generate_lines(self): + if not self.company_id.country_id: + raise Warning( _("The country is not set on the company '%s'.") - % company_obj.name - ) - if not company_obj.currency_id.name == 'EUR': - raise orm.except_orm( - _('Error :'), + % self.company_id.name) + if self.currency_id.name != 'EUR': + raise Warning( _("The company currency must be 'EUR', but is currently '%s'.") - % company_obj.currency_id.name - ) + % self.currency_id.name) return True - def _check_generate_xml(self, cr, uid, intrastat, context=None): - if not intrastat.company_id.partner_id.vat: - raise orm.except_orm( - _('Error :'), + @api.one + def _check_generate_xml(self): + if not self.company_id.partner_id.vat: + raise Warning( _("The VAT number is not set for the partner '%s'.") - % intrastat.company_id.partner_id.name) + % self.company_id.partner_id.name) return True - def _check_xml_schema( - self, cr, uid, xml_root, xml_string, xsd_file, context=None): + @api.model + def _check_xml_schema(self, xml_root, xml_string, xsd_file): '''Validate the XML file against the XSD''' from lxml import etree xsd_etree_obj = etree.parse( @@ -114,13 +93,12 @@ class report_intrastat_common(orm.TransientModel): official_schema.assertValid(xml_root) except Exception, e: # if the validation of the XSD fails, we arrive here - _logger = logging.getLogger(__name__) - _logger.warning( + logger = logging.getLogger(__name__) + logger.warning( "The XML file is invalid against the XML Schema Definition") - _logger.warning(xml_string) - _logger.warning(e) - raise orm.except_orm( - _('Error :'), + logger.warning(xml_string) + logger.warning(e) + raise Warning( _("The generated XML file is not valid against the official " "XML Schema Definition. The generated XML file and the " "full error have been written in the server logs. " @@ -129,39 +107,29 @@ class report_intrastat_common(orm.TransientModel): % str(e)) return True - def _attach_xml_file( - self, cr, uid, ids, object, xml_string, start_date_datetime, - declaration_name, context=None): + @api.multi + def _attach_xml_file(self, xml_string, declaration_name): '''Attach the XML file to the report_intrastat_product/service ''' '''object''' + self.ensure_one() import base64 - assert len(ids) == 1, "Only one ID accepted" - filename = '%s_%s.xml' % ( - datetime.strftime(start_date_datetime, '%Y-%m'), - declaration_name) - if not context: - context = {} - context.update({ - 'default_res_id': ids[0], - 'default_res_model': object._name - }) - attach_id = self.pool['ir.attachment'].create( - cr, uid, { - 'name': filename, - 'datas': base64.encodestring(xml_string), - 'datas_fname': filename}, - context=context) - return attach_id + filename = '%s_%s.xml' % (self.year_month, declaration_name) + attach = self.with_context( + default_res_id=self.id, + default_res_model=self._name).env['ir.attachment'].create({ + 'name': filename, + 'datas': base64.encodestring(xml_string), + 'datas_fname': filename}) + return attach.id - def _open_attach_view( - self, cr, uid, attach_id, title='XML file', context=None): + @api.model + def _open_attach_view(self, attach_id, title='XML file'): '''Returns an action which opens the form view of the ''' '''corresponding attachement''' action = { 'name': title, 'view_type': 'form', - 'view_mode': 'form,tree', - 'view_id': False, + 'view_mode': 'form', 'res_model': 'ir.attachment', 'type': 'ir.actions.act_window', 'nodestroy': True, @@ -170,30 +138,27 @@ class report_intrastat_common(orm.TransientModel): } return action - def partner_on_change(self, cr, uid, ids, partner_id=False, context=None): - result = {} - result['value'] = {} - if partner_id: - company = self.pool['res.partner'].read( - cr, uid, partner_id, ['vat'], context=context) - result['value']['partner_vat'] = company['vat'] - return result - - def send_reminder_email( - self, cr, uid, company, module_name, template_xmlid, - intrastat_id, context=None): - template_model, template_id =\ - self.pool['ir.model.data'].get_object_reference( - cr, uid, module_name, template_xmlid) - assert template_model == 'email.template', 'Wrong model' - if company.intrastat_remind_user_ids: + @api.one + def send_reminder_email(self, mail_template_xmlid): + mail_template = self.env.ref(mail_template_xmlid) + if self.company_id.intrastat_remind_user_ids: self.pool['email.template'].send_mail( - cr, uid, template_id, intrastat_id, context=context) + self._cr, self._uid, mail_template.id, self.id, + context=self._context) logger.info( 'Intrastat Reminder email has been sent (XMLID: %s).' - % template_xmlid) + % mail_template_xmlid) else: logger.warning( 'The list of users receiving the Intrastat Reminder is empty ' - 'on company %s' % company.name) + 'on company %s' % self.company_id.name) return True + + @api.multi + def unlink(self): + for intrastat in self: + if intrastat.state == 'done': + raise Warning( + _('Cannot delete the declaration %s ' + 'because it is in Done state') % self.year_month) + return super(ReportIntrastatCommon, self).unlink() From 5dafa77e3e46dd6423330b232210648fdce15b29 Mon Sep 17 00:00:00 2001 From: Ronald Portier Date: Fri, 13 Feb 2015 11:24:14 +0100 Subject: [PATCH 08/44] Revert rename of _check_generate_lines to version withouth underscore. In pending merge request from Alexis, _check_generate_lines will no longer be called from outside the class, so no longer any need to change private function name convention to public name convention. This will also make it easier to merge all changes. --- intrastat_base/intrastat_common.py | 195 +++++++++++++++++------------ 1 file changed, 115 insertions(+), 80 deletions(-) diff --git a/intrastat_base/intrastat_common.py b/intrastat_base/intrastat_common.py index b6d8b2f..3db1764 100644 --- a/intrastat_base/intrastat_common.py +++ b/intrastat_base/intrastat_common.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Report intrastat base module for Odoo -# Copyright (C) 2010-2014 Akretion (http://www.akretion.com/). +# Report intrastat base module for OpenERP +# Copyright (C) 2010-2013 Akretion (http://www.akretion.com/). # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -20,8 +20,9 @@ # ############################################################################## -from openerp import models, fields, api, tools, _ -from openerp.exceptions import Warning, ValidationError +from openerp.osv import orm +from openerp.tools.translate import _ +from openerp import tools from datetime import datetime from dateutil.relativedelta import relativedelta import logging @@ -29,61 +30,81 @@ import logging logger = logging.getLogger(__name__) -class ReportIntrastatCommon(models.AbstractModel): +class report_intrastat_common(orm.TransientModel): _name = "report.intrastat.common" _description = "Common functions for intrastat reports for products " "and services" - @api.one - @api.depends( - 'intrastat_line_ids', 'intrastat_line_ids.amount_company_currency') - def _compute_numbers(self): - total_amount = 0.0 - num_lines = 0 - for line in self.intrastat_line_ids: - total_amount += line.amount_company_currency - num_lines += 1 - self.num_lines = num_lines - self.total_amount = total_amount + def _compute_numbers(self, cr, uid, ids, object, context=None): + result = {} + for intrastat in object.browse(cr, uid, ids, context=context): + total_amount = 0.0 + num_lines = 0 + for line in intrastat.intrastat_line_ids: + total_amount += line.amount_company_currency + num_lines += 1 + result[intrastat.id] = { + 'num_lines': num_lines, + 'total_amount': total_amount, + } + return result - @api.one - @api.depends('start_date') - def _compute_dates(self): - start_date_dt = fields.Date.from_string(self.start_date) - self.end_date = fields.Date.to_string( - start_date_dt + relativedelta(day=31)) - self.year_month = start_date_dt.strftime('%Y-%m') + def _compute_dates(self, cr, uid, ids, object, context=None): + result = {} + for intrastat in object.browse(cr, uid, ids, context=context): + start_date_datetime = datetime.strptime( + intrastat.start_date, '%Y-%m-%d') + end_date_str = datetime.strftime( + start_date_datetime + relativedelta(day=31), '%Y-%m-%d') + result[intrastat.id] = { + 'end_date': end_date_str, + 'year_month': start_date_datetime.strftime('%Y-%m'), + } + return result - @api.one - def _check_start_date(self): + def _check_start_date(self, cr, uid, ids, object, context=None): '''Check that the start date is the first day of the month''' - datetime_to_check = fields.Date.from_string(self.start_date) - if datetime_to_check.day != 1: - raise ValidationError( - _('The start date must be the first day of the month')) + for date_to_check in object.read( + cr, uid, ids, ['start_date'], context=context): + datetime_to_check = datetime.strptime( + date_to_check['start_date'], '%Y-%m-%d') + if datetime_to_check.day != 1: + return False + return True - @api.one - def _check_generate_lines(self): - if not self.company_id.country_id: - raise Warning( + def _check_generate_lines(self, cr, uid, intrastat, context=None): + """Check wether all requirements are met for generating lines.""" + if not intrastat.company_id: + # Should not be possible, but just in case: + raise orm.except_orm( + _('Error :'), + _("Company not yet set on intrastat report.") + ) + company_obj = intrastat.company_id # Simplify references + if not company_obj.country_id: + raise orm.except_orm( + _('Error :'), _("The country is not set on the company '%s'.") - % self.company_id.name) - if self.currency_id.name != 'EUR': - raise Warning( + % company_obj.name + ) + if not company_obj.currency_id.name == 'EUR': + raise orm.except_orm( + _('Error :'), _("The company currency must be 'EUR', but is currently '%s'.") - % self.currency_id.name) + % company_obj.currency_id.name + ) return True - @api.one - def _check_generate_xml(self): - if not self.company_id.partner_id.vat: - raise Warning( + def _check_generate_xml(self, cr, uid, intrastat, context=None): + if not intrastat.company_id.partner_id.vat: + raise orm.except_orm( + _('Error :'), _("The VAT number is not set for the partner '%s'.") - % self.company_id.partner_id.name) + % intrastat.company_id.partner_id.name) return True - @api.model - def _check_xml_schema(self, xml_root, xml_string, xsd_file): + def _check_xml_schema( + self, cr, uid, xml_root, xml_string, xsd_file, context=None): '''Validate the XML file against the XSD''' from lxml import etree xsd_etree_obj = etree.parse( @@ -93,12 +114,13 @@ class ReportIntrastatCommon(models.AbstractModel): official_schema.assertValid(xml_root) except Exception, e: # if the validation of the XSD fails, we arrive here - logger = logging.getLogger(__name__) - logger.warning( + _logger = logging.getLogger(__name__) + _logger.warning( "The XML file is invalid against the XML Schema Definition") - logger.warning(xml_string) - logger.warning(e) - raise Warning( + _logger.warning(xml_string) + _logger.warning(e) + raise orm.except_orm( + _('Error :'), _("The generated XML file is not valid against the official " "XML Schema Definition. The generated XML file and the " "full error have been written in the server logs. " @@ -107,29 +129,39 @@ class ReportIntrastatCommon(models.AbstractModel): % str(e)) return True - @api.multi - def _attach_xml_file(self, xml_string, declaration_name): + def _attach_xml_file( + self, cr, uid, ids, object, xml_string, start_date_datetime, + declaration_name, context=None): '''Attach the XML file to the report_intrastat_product/service ''' '''object''' - self.ensure_one() import base64 - filename = '%s_%s.xml' % (self.year_month, declaration_name) - attach = self.with_context( - default_res_id=self.id, - default_res_model=self._name).env['ir.attachment'].create({ - 'name': filename, - 'datas': base64.encodestring(xml_string), - 'datas_fname': filename}) - return attach.id + assert len(ids) == 1, "Only one ID accepted" + filename = '%s_%s.xml' % ( + datetime.strftime(start_date_datetime, '%Y-%m'), + declaration_name) + if not context: + context = {} + context.update({ + 'default_res_id': ids[0], + 'default_res_model': object._name + }) + attach_id = self.pool['ir.attachment'].create( + cr, uid, { + 'name': filename, + 'datas': base64.encodestring(xml_string), + 'datas_fname': filename}, + context=context) + return attach_id - @api.model - def _open_attach_view(self, attach_id, title='XML file'): + def _open_attach_view( + self, cr, uid, attach_id, title='XML file', context=None): '''Returns an action which opens the form view of the ''' '''corresponding attachement''' action = { 'name': title, 'view_type': 'form', - 'view_mode': 'form', + 'view_mode': 'form,tree', + 'view_id': False, 'res_model': 'ir.attachment', 'type': 'ir.actions.act_window', 'nodestroy': True, @@ -138,27 +170,30 @@ class ReportIntrastatCommon(models.AbstractModel): } return action - @api.one - def send_reminder_email(self, mail_template_xmlid): - mail_template = self.env.ref(mail_template_xmlid) - if self.company_id.intrastat_remind_user_ids: + def partner_on_change(self, cr, uid, ids, partner_id=False, context=None): + result = {} + result['value'] = {} + if partner_id: + company = self.pool['res.partner'].read( + cr, uid, partner_id, ['vat'], context=context) + result['value']['partner_vat'] = company['vat'] + return result + + def send_reminder_email( + self, cr, uid, company, module_name, template_xmlid, + intrastat_id, context=None): + template_model, template_id =\ + self.pool['ir.model.data'].get_object_reference( + cr, uid, module_name, template_xmlid) + assert template_model == 'email.template', 'Wrong model' + if company.intrastat_remind_user_ids: self.pool['email.template'].send_mail( - self._cr, self._uid, mail_template.id, self.id, - context=self._context) + cr, uid, template_id, intrastat_id, context=context) logger.info( 'Intrastat Reminder email has been sent (XMLID: %s).' - % mail_template_xmlid) + % template_xmlid) else: logger.warning( 'The list of users receiving the Intrastat Reminder is empty ' - 'on company %s' % self.company_id.name) + 'on company %s' % company.name) return True - - @api.multi - def unlink(self): - for intrastat in self: - if intrastat.state == 'done': - raise Warning( - _('Cannot delete the declaration %s ' - 'because it is in Done state') % self.year_month) - return super(ReportIntrastatCommon, self).unlink() From e097562f64fcc284a601adc9a9ec63b7f7c64f5b Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Tue, 14 Apr 2015 22:33:32 +0200 Subject: [PATCH 09/44] [IMP] intrasta_base: Several imps: * Move description from __openerp__.py to README.rst Add conflict key in __openerp__.py Simplify code that create attachment Thanks to Luc de Meyer (Noviat) for his help on this. * Update README.rst and translation files * Simplify @depends, as suggested by Yannick * Better use of the new API for send_mail(), as suggested by Yannick (and tested be me) * Large code re-engineering following the Akretion-Noviat code sprint on intrastat This code has been written both by Luc de Meyer and myself. * Add first draft of code to generate decl lines --- intrastat_base/README.rst | 44 +++++ intrastat_base/__openerp__.py | 20 +-- intrastat_base/company_view.xml | 2 +- intrastat_base/country.py | 2 +- intrastat_base/i18n/fr_FR.po | 99 ++++++------ intrastat_base/i18n/intrastat_base.pot | 95 +++++------ intrastat_base/intrastat_common.py | 216 +++++++++++-------------- intrastat_base/intrastat_menu.xml | 16 -- intrastat_base/intrastat_view.xml | 36 +++++ intrastat_base/product.py | 2 +- intrastat_base/tax.py | 2 +- 11 files changed, 273 insertions(+), 261 deletions(-) create mode 100644 intrastat_base/README.rst delete mode 100644 intrastat_base/intrastat_menu.xml create mode 100644 intrastat_base/intrastat_view.xml diff --git a/intrastat_base/README.rst b/intrastat_base/README.rst new file mode 100644 index 0000000..a941d1d --- /dev/null +++ b/intrastat_base/README.rst @@ -0,0 +1,44 @@ +Intrastat Base Module +===================== + +This module contains common functions for the Intrastat reporting and +should be used in combination with country-specific reporting modules +such as: + +- *l10n_fr_intrastat_service*: + the module for the *Déclaration Européenne des Services* (DES) for France +- *l10n_fr_intrastat_product*: + the module for the *Déclaration d'Echange de Biens* (DEB) for France +- *l10n_be_intrastat_product*: + the module for the Intrastat Declaration for Belgium. + +These country-specific modules can be found in the OCA localization for those countries. + +Installation +============ + +WARNING: +This module conflicts with the module *report_intrastat* from the official addons. +If you have already installed the module *report_intrastat*, +you should uninstall it first before installing this module. + +Credits +======= + +Contributors +------------ + +* Alexis de Lattre, Akretion + +Maintainer +---------- + +.. image:: http://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: http://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. + +To contribute to this module, please visit http://odoo-community.org. diff --git a/intrastat_base/__openerp__.py b/intrastat_base/__openerp__.py index e795155..ea5483f 100644 --- a/intrastat_base/__openerp__.py +++ b/intrastat_base/__openerp__.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Report intrastat base module for Odoo +# Intrastat base module for Odoo # Copyright (C) 2011-2015 Akretion (http://www.akretion.com) # @author Alexis de Lattre # @@ -23,23 +23,13 @@ { 'name': 'Intrastat Reporting Base', 'version': '1.1', - 'category': 'Localisation/Report Intrastat', + 'category': 'Intrastat', 'license': 'AGPL-3', 'summary': 'Base module for Intrastat reporting', - 'description': """This module contains the common functions for 2 other modules : -- l10n_fr_intrastat_service : the module for the "Déclaration Européenne des Services" (DES) -- l10n_fr_intrastat_product : the module for the "Déclaration d'Echange de Biens" (DEB) -This module is not usefull if it's not used together with one of those 2 modules or other country-specific intrastat modules. - -This module doesn't have any France-specific stuff. So it can be used as a basis for other intrastat modules for other EU countries. - -WARNING : this module conflicts with the module "report_intrastat" from the addons. If you have already installed the module "report_intrastat", you should uninstall it first before installing this module. - -Please contact Alexis de Lattre from Akretion for any help or question about this module. - """, - 'author': 'Akretion', + 'author': 'Akretion,Odoo Community Association (OCA)', 'website': 'http://www.akretion.com', 'depends': ['base_vat'], + 'conflicts': ['report_intrastat'], 'data': [ 'country_data.xml', 'product_view.xml', @@ -47,7 +37,7 @@ Please contact Alexis de Lattre from Akretion for 'country_view.xml', 'tax_view.xml', 'company_view.xml', - 'intrastat_menu.xml', + 'intrastat_view.xml', ], 'demo': ['intrastat_demo.xml'], 'installable': True, diff --git a/intrastat_base/company_view.xml b/intrastat_base/company_view.xml index 87933f4..1df7aed 100644 --- a/intrastat_base/company_view.xml +++ b/intrastat_base/company_view.xml @@ -16,7 +16,7 @@ - + diff --git a/intrastat_base/country.py b/intrastat_base/country.py index 7f03e5d..7a34e77 100644 --- a/intrastat_base/country.py +++ b/intrastat_base/country.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Report intrastat base module for Odoo +# Intrastat base module for Odoo # Copyright (C) 2011-2014 Akretion (http://www.akretion.com). # @author Alexis de Lattre # diff --git a/intrastat_base/i18n/fr_FR.po b/intrastat_base/i18n/fr_FR.po index de7e5db..1b3d759 100644 --- a/intrastat_base/i18n/fr_FR.po +++ b/intrastat_base/i18n/fr_FR.po @@ -1,14 +1,14 @@ -# Translation of OpenERP Server. +# Translation of Odoo Server. # This file contains the translation of the following modules: # * intrastat_base # msgid "" msgstr "" -"Project-Id-Version: OpenERP Server 7.0\n" +"Project-Id-Version: Odoo Server 8.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-04-14 14:18+0000\n" -"PO-Revision-Date: 2014-04-14 14:18+0000\n" -"Last-Translator: Alexis de Lattre \n" +"POT-Creation-Date: 2015-05-27 18:43+0000\n" +"PO-Revision-Date: 2015-05-27 18:43+0000\n" +"Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -21,47 +21,43 @@ msgid "Activate this option for shipping costs, packaging costs and all services msgstr "Activez cette option pour les frais de port, les frais d'emballage et tous les services liés à la vente de produits physiques. Cette option est utilisée pour la DEB et la DES." #. module: intrastat_base -#: view:res.company:0 +#: code:addons/intrastat_base/intrastat_common.py:165 +#, python-format +msgid "Cannot delete the declaration %s because it is in Done state" +msgstr "Impossible de supprimer la déclaration %s car elle est à l'état déclaré" + +#. module: intrastat_base +#: view:res.company:intrastat_base.view_company_form msgid "Common Intrastat Settings" msgstr "Paramètres communs DEB et DES" #. module: intrastat_base #: model:ir.model,name:intrastat_base.model_report_intrastat_common -msgid "Common functions for intrastat reports for products and services" -msgstr "Fonctions communes pour la DEB et la DES" +msgid "Common functions for intrastat reports for products " +msgstr "" #. module: intrastat_base #: model:ir.model,name:intrastat_base.model_res_company msgid "Companies" msgstr "Sociétés" +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:68 +#, python-format +msgid "Company not yet set on intrastat report." +msgstr "Société non configurée sur le rapport intrastat." + #. module: intrastat_base #: model:ir.model,name:intrastat_base.model_res_country msgid "Country" msgstr "Pays" #. module: intrastat_base -#: view:res.country:0 +#: view:res.country:intrastat_base.view_country_search #: field:res.country,intrastat:0 msgid "EU Country" msgstr "Pays UE" -#. module: intrastat_base -#: code:addons/intrastat_base/company.py:58 -#: code:addons/intrastat_base/intrastat_common.py:77 -#: code:addons/intrastat_base/intrastat_common.py:82 -#: code:addons/intrastat_base/intrastat_common.py:90 -#: code:addons/intrastat_base/intrastat_common.py:110 -#: code:addons/intrastat_base/product.py:51 -#, python-format -msgid "Error :" -msgstr "Erreur :" - -#. module: intrastat_base -#: constraint:product.template:0 -msgid "Error msg is in raise" -msgstr "Error msg is in raise" - #. module: intrastat_base #: field:product.template,exclude_from_intrastat:0 msgid "Exclude from Intrastat reports" @@ -72,6 +68,11 @@ msgstr "Exclure de la DEB et de la DES" msgid "Exclude invoice line from intrastat if this tax is present" msgstr "Exclue la ligne de facture de la DEB/DES si cette taxe est présente" +#. module: intrastat_base +#: field:report.intrastat.common,id:0 +msgid "ID" +msgstr "ID" + #. module: intrastat_base #: help:product.template,exclude_from_intrastat:0 msgid "If set to True, the product or service will not be taken into account for Intrastat Product or Service reports. So you should leave this field to False unless you have a very good reason." @@ -83,21 +84,20 @@ msgid "If this tax is present on an invoice line, this invoice line will be skip msgstr "Si cette taxe est présente sur une ligne de facture, cette ligne de facture ne sera pas prise en compte lors de la génération de la DEB et de la DES depuis les factures." #. module: intrastat_base -#: view:product.product:0 -#: view:product.template:0 +#: view:product.template:intrastat_base.product_template_form_view msgid "Intrastat Properties" msgstr "Propriétés DEB/DES" -#. module: intrastat_base -#: view:res.company:0 -msgid "Intrastat Settings" -msgstr "Configuration DEB/DES" - #. module: intrastat_base #: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root msgid "Intrastat Reporting" msgstr "DEB et DES" +#. module: intrastat_base +#: view:res.company:intrastat_base.view_company_form +msgid "Intrastat Settings" +msgstr "Configuration DEB/DES" + #. module: intrastat_base #: field:product.template,is_accessory_cost:0 msgid "Is accessory cost" @@ -109,28 +109,18 @@ msgid "List of OpenERP users who will receive a notification to remind them abou msgstr "Liste d'utilisateurs OpenERP qui recevront le rappel pour la DEB et/ou la DES." #. module: intrastat_base -#: field:res.company,intrastat_email_list:0 -msgid "List of emails of Users Receiving the Intrastat Reminder" -msgstr "Liste des emails d'utilisateurs qui recevront le rappel pour la DEB et/ou la DES" - -#. module: intrastat_base -#: code:addons/intrastat_base/company.py:59 +#: code:addons/intrastat_base/company.py:55 #, python-format msgid "Missing e-mail address on user '%s'." msgstr "Adresse e-mail manquante sur l'utilisateur '%s'." -#. module: intrastat_base -#: model:ir.model,name:intrastat_base.model_res_partner -msgid "Partner" -msgstr "Partenaire" - #. module: intrastat_base #: model:ir.model,name:intrastat_base.model_product_template msgid "Product Template" msgstr "Modèle d'article" #. module: intrastat_base -#: view:res.country:0 +#: view:res.country:intrastat_base.view_country_search msgid "Search Countries" msgstr "Recherche des pays" @@ -150,42 +140,43 @@ msgid "Tax" msgstr "Taxes" #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:91 +#: code:addons/intrastat_base/intrastat_common.py:84 #, python-format msgid "The VAT number is not set for the partner '%s'." msgstr "Le numéro de TVA n'est pas renseigné pour le partenaire '%s'." #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:83 +#: code:addons/intrastat_base/intrastat_common.py:76 #, python-format msgid "The company currency must be 'EUR', but is currently '%s'." msgstr "La monnaie de la société doit être 'EUR', mais est actuellement '%s'." #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:78 +#: code:addons/intrastat_base/intrastat_common.py:72 #, python-format msgid "The country is not set on the company '%s'." msgstr "Le pays n'est pas renseigné sur la société '%s'." #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:111 +#: code:addons/intrastat_base/intrastat_common.py:105 #, python-format msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s." msgstr "La validation du fichier XML avec le schéma XML officiel a échoué. Le fichier XML généré et le détail de l'erreur ont été écrits dans les logs du serveur. Voici le message d'erreur, qui peut vous donner une idée de la cause du problème : %s." #. module: intrastat_base -#: code:addons/intrastat_base/product.py:56 +#: code:addons/intrastat_base/product.py:51 #, python-format msgid "The option 'Is accessory cost?' should only be activated on 'Service' products. You have activated this option for the product '%s' which is of type '%s'" msgstr "L'option 'Frais accessoires' ne doit être activée que sur les produits de type 'Service'. Vous avez activé cette option sur le produit '%s' qui est de type '%s'" +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:62 +#, python-format +msgid "The start date must be the first day of the month" +msgstr "La date de début doit être le premier jour du mois" + #. module: intrastat_base #: field:res.company,intrastat_remind_user_ids:0 msgid "Users Receiving the Intrastat Reminder" msgstr "Utilisateurs qui reçoivent le rappel DEB/DES" -#. module: intrastat_base -#: constraint:res.company:0 -msgid "error msg in raise" -msgstr "error msg in raise" - diff --git a/intrastat_base/i18n/intrastat_base.pot b/intrastat_base/i18n/intrastat_base.pot index d184def..fdc6996 100644 --- a/intrastat_base/i18n/intrastat_base.pot +++ b/intrastat_base/i18n/intrastat_base.pot @@ -1,13 +1,13 @@ -# Translation of OpenERP Server. +# Translation of Odoo Server. # This file contains the translation of the following modules: # * intrastat_base # msgid "" msgstr "" -"Project-Id-Version: OpenERP Server 7.0\n" +"Project-Id-Version: Odoo Server 8.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-04-14 14:18+0000\n" -"PO-Revision-Date: 2014-04-14 14:18+0000\n" +"POT-Creation-Date: 2015-05-27 18:43+0000\n" +"PO-Revision-Date: 2015-05-27 18:43+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -21,13 +21,19 @@ msgid "Activate this option for shipping costs, packaging costs and all services msgstr "" #. module: intrastat_base -#: view:res.company:0 +#: code:addons/intrastat_base/intrastat_common.py:165 +#, python-format +msgid "Cannot delete the declaration %s because it is in Done state" +msgstr "" + +#. module: intrastat_base +#: view:res.company:intrastat_base.view_company_form msgid "Common Intrastat Settings" msgstr "" #. module: intrastat_base #: model:ir.model,name:intrastat_base.model_report_intrastat_common -msgid "Common functions for intrastat reports for products and services" +msgid "Common functions for intrastat reports for products " msgstr "" #. module: intrastat_base @@ -35,33 +41,23 @@ msgstr "" msgid "Companies" msgstr "" +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:68 +#, python-format +msgid "Company not yet set on intrastat report." +msgstr "" + #. module: intrastat_base #: model:ir.model,name:intrastat_base.model_res_country msgid "Country" msgstr "" #. module: intrastat_base -#: view:res.country:0 +#: view:res.country:intrastat_base.view_country_search #: field:res.country,intrastat:0 msgid "EU Country" msgstr "" -#. module: intrastat_base -#: code:addons/intrastat_base/company.py:58 -#: code:addons/intrastat_base/intrastat_common.py:77 -#: code:addons/intrastat_base/intrastat_common.py:82 -#: code:addons/intrastat_base/intrastat_common.py:90 -#: code:addons/intrastat_base/intrastat_common.py:110 -#: code:addons/intrastat_base/product.py:51 -#, python-format -msgid "Error :" -msgstr "" - -#. module: intrastat_base -#: constraint:product.template:0 -msgid "Error msg is in raise" -msgstr "" - #. module: intrastat_base #: field:product.template,exclude_from_intrastat:0 msgid "Exclude from Intrastat reports" @@ -72,6 +68,11 @@ msgstr "" msgid "Exclude invoice line from intrastat if this tax is present" msgstr "" +#. module: intrastat_base +#: field:report.intrastat.common,id:0 +msgid "ID" +msgstr "" + #. module: intrastat_base #: help:product.template,exclude_from_intrastat:0 msgid "If set to True, the product or service will not be taken into account for Intrastat Product or Service reports. So you should leave this field to False unless you have a very good reason." @@ -83,21 +84,20 @@ msgid "If this tax is present on an invoice line, this invoice line will be skip msgstr "" #. module: intrastat_base -#: view:product.product:0 -#: view:product.template:0 +#: view:product.template:intrastat_base.product_template_form_view msgid "Intrastat Properties" msgstr "" -#. module: intrastat_base -#: view:res.company:0 -msgid "Intrastat Settings" -msgstr "" - #. module: intrastat_base #: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root msgid "Intrastat Reporting" msgstr "" +#. module: intrastat_base +#: view:res.company:intrastat_base.view_company_form +msgid "Intrastat Settings" +msgstr "" + #. module: intrastat_base #: field:product.template,is_accessory_cost:0 msgid "Is accessory cost" @@ -109,28 +109,18 @@ msgid "List of OpenERP users who will receive a notification to remind them abou msgstr "" #. module: intrastat_base -#: field:res.company,intrastat_email_list:0 -msgid "List of emails of Users Receiving the Intrastat Reminder" -msgstr "" - -#. module: intrastat_base -#: code:addons/intrastat_base/company.py:59 +#: code:addons/intrastat_base/company.py:55 #, python-format msgid "Missing e-mail address on user '%s'." msgstr "" -#. module: intrastat_base -#: model:ir.model,name:intrastat_base.model_res_partner -msgid "Partner" -msgstr "" - #. module: intrastat_base #: model:ir.model,name:intrastat_base.model_product_template msgid "Product Template" msgstr "" #. module: intrastat_base -#: view:res.country:0 +#: view:res.country:intrastat_base.view_country_search msgid "Search Countries" msgstr "" @@ -150,42 +140,43 @@ msgid "Tax" msgstr "" #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:91 +#: code:addons/intrastat_base/intrastat_common.py:84 #, python-format msgid "The VAT number is not set for the partner '%s'." msgstr "" #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:83 +#: code:addons/intrastat_base/intrastat_common.py:76 #, python-format msgid "The company currency must be 'EUR', but is currently '%s'." msgstr "" #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:78 +#: code:addons/intrastat_base/intrastat_common.py:72 #, python-format msgid "The country is not set on the company '%s'." msgstr "" #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:111 +#: code:addons/intrastat_base/intrastat_common.py:105 #, python-format msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s." msgstr "" #. module: intrastat_base -#: code:addons/intrastat_base/product.py:56 +#: code:addons/intrastat_base/product.py:51 #, python-format msgid "The option 'Is accessory cost?' should only be activated on 'Service' products. You have activated this option for the product '%s' which is of type '%s'" msgstr "" +#. module: intrastat_base +#: code:addons/intrastat_base/intrastat_common.py:62 +#, python-format +msgid "The start date must be the first day of the month" +msgstr "" + #. module: intrastat_base #: field:res.company,intrastat_remind_user_ids:0 msgid "Users Receiving the Intrastat Reminder" msgstr "" -#. module: intrastat_base -#: constraint:res.company:0 -msgid "error msg in raise" -msgstr "" - diff --git a/intrastat_base/intrastat_common.py b/intrastat_base/intrastat_common.py index 3db1764..a18ea07 100644 --- a/intrastat_base/intrastat_common.py +++ b/intrastat_base/intrastat_common.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Report intrastat base module for OpenERP -# Copyright (C) 2010-2013 Akretion (http://www.akretion.com/). +# Intrastat base module for Odoo +# Copyright (C) 2010-2014 Akretion (http://www.akretion.com/). # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify @@ -20,91 +20,72 @@ # ############################################################################## -from openerp.osv import orm -from openerp.tools.translate import _ -from openerp import tools -from datetime import datetime +from openerp import models, fields, api, tools, _ +from openerp.exceptions import Warning, ValidationError from dateutil.relativedelta import relativedelta import logging logger = logging.getLogger(__name__) -class report_intrastat_common(orm.TransientModel): - _name = "report.intrastat.common" +class IntrastatCommon(models.AbstractModel): + _name = "intrastat.common" _description = "Common functions for intrastat reports for products " "and services" - def _compute_numbers(self, cr, uid, ids, object, context=None): - result = {} - for intrastat in object.browse(cr, uid, ids, context=context): - total_amount = 0.0 - num_lines = 0 - for line in intrastat.intrastat_line_ids: - total_amount += line.amount_company_currency - num_lines += 1 - result[intrastat.id] = { - 'num_lines': num_lines, - 'total_amount': total_amount, - } - return result + @api.one + @api.depends('declaration_line_ids.amount_company_currency') + def _compute_numbers(self): + total_amount = 0.0 + num_lines = 0 + for line in self.declaration_line_ids: + total_amount += line.amount_company_currency + num_lines += 1 + self.num_decl_lines = num_lines + self.total_amount = total_amount - def _compute_dates(self, cr, uid, ids, object, context=None): - result = {} - for intrastat in object.browse(cr, uid, ids, context=context): - start_date_datetime = datetime.strptime( - intrastat.start_date, '%Y-%m-%d') - end_date_str = datetime.strftime( - start_date_datetime + relativedelta(day=31), '%Y-%m-%d') - result[intrastat.id] = { - 'end_date': end_date_str, - 'year_month': start_date_datetime.strftime('%Y-%m'), - } - return result + @api.one + @api.depends('start_date') + def _compute_dates(self): + start_date_dt = fields.Date.from_string(self.start_date) + self.end_date = fields.Date.to_string( + start_date_dt + relativedelta(day=31)) + self.year_month = start_date_dt.strftime('%Y-%m') - def _check_start_date(self, cr, uid, ids, object, context=None): + @api.one + def _check_start_date(self): '''Check that the start date is the first day of the month''' - for date_to_check in object.read( - cr, uid, ids, ['start_date'], context=context): - datetime_to_check = datetime.strptime( - date_to_check['start_date'], '%Y-%m-%d') - if datetime_to_check.day != 1: - return False - return True + datetime_to_check = fields.Date.from_string(self.start_date) + if datetime_to_check.day != 1: + raise ValidationError( + _('The start date must be the first day of the month')) - def _check_generate_lines(self, cr, uid, intrastat, context=None): + @api.one + def _check_generate_lines(self): """Check wether all requirements are met for generating lines.""" - if not intrastat.company_id: - # Should not be possible, but just in case: - raise orm.except_orm( - _('Error :'), - _("Company not yet set on intrastat report.") - ) - company_obj = intrastat.company_id # Simplify references + if not self.company_id: + raise Warning(_("Company not yet set on intrastat report.")) + company_obj = self.company_id if not company_obj.country_id: - raise orm.except_orm( - _('Error :'), + raise Warning( _("The country is not set on the company '%s'.") - % company_obj.name - ) - if not company_obj.currency_id.name == 'EUR': - raise orm.except_orm( - _('Error :'), + % company_obj.name) + if company_obj.currency_id.name != 'EUR': + raise Warning( _("The company currency must be 'EUR', but is currently '%s'.") - % company_obj.currency_id.name - ) + % company_obj.currency_id.name) return True - def _check_generate_xml(self, cr, uid, intrastat, context=None): - if not intrastat.company_id.partner_id.vat: - raise orm.except_orm( - _('Error :'), + @api.one + def _check_generate_xml(self): + if not self.company_id.partner_id.vat: + raise Warning( _("The VAT number is not set for the partner '%s'.") - % intrastat.company_id.partner_id.name) + % self.company_id.partner_id.name) return True - def _check_xml_schema( - self, cr, uid, xml_root, xml_string, xsd_file, context=None): + @api.model + def _check_xml_schema(self, xml_root, xml_string, xsd_file): '''Validate the XML file against the XSD''' from lxml import etree xsd_etree_obj = etree.parse( @@ -114,13 +95,12 @@ class report_intrastat_common(orm.TransientModel): official_schema.assertValid(xml_root) except Exception, e: # if the validation of the XSD fails, we arrive here - _logger = logging.getLogger(__name__) - _logger.warning( + logger = logging.getLogger(__name__) + logger.warning( "The XML file is invalid against the XML Schema Definition") - _logger.warning(xml_string) - _logger.warning(e) - raise orm.except_orm( - _('Error :'), + logger.warning(xml_string) + logger.warning(e) + raise Warning( _("The generated XML file is not valid against the official " "XML Schema Definition. The generated XML file and the " "full error have been written in the server logs. " @@ -129,39 +109,29 @@ class report_intrastat_common(orm.TransientModel): % str(e)) return True - def _attach_xml_file( - self, cr, uid, ids, object, xml_string, start_date_datetime, - declaration_name, context=None): - '''Attach the XML file to the report_intrastat_product/service ''' - '''object''' + @api.multi + def _attach_xml_file(self, xml_string, declaration_name): + '''Attach the XML file to the report_intrastat_product/service + object''' + self.ensure_one() import base64 - assert len(ids) == 1, "Only one ID accepted" - filename = '%s_%s.xml' % ( - datetime.strftime(start_date_datetime, '%Y-%m'), - declaration_name) - if not context: - context = {} - context.update({ - 'default_res_id': ids[0], - 'default_res_model': object._name - }) - attach_id = self.pool['ir.attachment'].create( - cr, uid, { - 'name': filename, - 'datas': base64.encodestring(xml_string), - 'datas_fname': filename}, - context=context) - return attach_id + filename = '%s_%s.xml' % (self.year_month, declaration_name) + attach = self.env['ir.attachment'].create({ + 'name': filename, + 'res_id': self.id, + 'res_model': self._name, + 'datas': base64.encodestring(xml_string), + 'datas_fname': filename}) + return attach.id - def _open_attach_view( - self, cr, uid, attach_id, title='XML file', context=None): - '''Returns an action which opens the form view of the ''' - '''corresponding attachement''' + @api.model + def _open_attach_view(self, attach_id, title='XML file'): + '''Returns an action which opens the form view of the + corresponding attachement''' action = { 'name': title, 'view_type': 'form', - 'view_mode': 'form,tree', - 'view_id': False, + 'view_mode': 'form', 'res_model': 'ir.attachment', 'type': 'ir.actions.act_window', 'nodestroy': True, @@ -170,30 +140,36 @@ class report_intrastat_common(orm.TransientModel): } return action - def partner_on_change(self, cr, uid, ids, partner_id=False, context=None): - result = {} - result['value'] = {} - if partner_id: - company = self.pool['res.partner'].read( - cr, uid, partner_id, ['vat'], context=context) - result['value']['partner_vat'] = company['vat'] - return result - - def send_reminder_email( - self, cr, uid, company, module_name, template_xmlid, - intrastat_id, context=None): - template_model, template_id =\ - self.pool['ir.model.data'].get_object_reference( - cr, uid, module_name, template_xmlid) - assert template_model == 'email.template', 'Wrong model' - if company.intrastat_remind_user_ids: - self.pool['email.template'].send_mail( - cr, uid, template_id, intrastat_id, context=context) + @api.one + def send_reminder_email(self, mail_template_xmlid): + mail_template = self.env.ref(mail_template_xmlid) + if self.company_id.intrastat_remind_user_ids: + mail_template.send_mail(self.id) logger.info( 'Intrastat Reminder email has been sent (XMLID: %s).' - % template_xmlid) + % mail_template_xmlid) else: logger.warning( 'The list of users receiving the Intrastat Reminder is empty ' - 'on company %s' % company.name) + 'on company %s' % self.company_id.name) return True + + @api.multi + def unlink(self): + for intrastat in self: + if intrastat.state == 'done': + raise Warning( + _('Cannot delete the declaration %s ' + 'because it is in Done state') % self.year_month) + return super(IntrastatCommon, self).unlink() + + +class IntrastatResultView(models.TransientModel): + """ + Transient Model to display Intrastat Report results + """ + _name = 'intrastat.result.view' + + note = fields.Text( + string='Notes', readonly=True, + default=lambda self: self._context.get('note')) diff --git a/intrastat_base/intrastat_menu.xml b/intrastat_base/intrastat_menu.xml deleted file mode 100644 index 85303c1..0000000 --- a/intrastat_base/intrastat_menu.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - diff --git a/intrastat_base/intrastat_view.xml b/intrastat_base/intrastat_view.xml new file mode 100644 index 0000000..4d9c22a --- /dev/null +++ b/intrastat_base/intrastat_view.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + intrastat.result_view_form + intrastat.result.view + +
+ + + +
+
+
+
+
+ +
+
diff --git a/intrastat_base/product.py b/intrastat_base/product.py index ca1652e..5373cb3 100644 --- a/intrastat_base/product.py +++ b/intrastat_base/product.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Report intrastat base module for OpenERP +# Intrastat base module for Odoo # Copyright (C) 2010-2014 Akretion (http://www.akretion.com/) # @author Alexis de Lattre # diff --git a/intrastat_base/tax.py b/intrastat_base/tax.py index 2b98678..197e51d 100644 --- a/intrastat_base/tax.py +++ b/intrastat_base/tax.py @@ -1,7 +1,7 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Report intrastat base module for Odoo +# Intrastat base module for Odoo # Copyright (C) 2011-2014 Akretion (http://www.akretion.com). # @author Alexis de Lattre # From 686288c040d88aaf9bbe28f69f4f1b7df904c7de Mon Sep 17 00:00:00 2001 From: luc-demeyer Date: Tue, 20 Oct 2015 20:26:19 +0200 Subject: [PATCH 10/44] [REF] intrastat_base: major update intrastat V3 --- intrastat_base/README.rst | 37 +++++++++++++++++-- intrastat_base/__init__.py | 6 +-- intrastat_base/__openerp__.py | 20 +++++----- intrastat_base/{ => data}/country_data.xml | 0 intrastat_base/{ => demo}/intrastat_demo.xml | 0 intrastat_base/models/__init__.py | 27 ++++++++++++++ .../{tax.py => models/account_tax.py} | 0 .../{ => models}/intrastat_common.py | 27 +++++++++++++- .../product_template.py} | 0 .../{company.py => models/res_company.py} | 20 +++++----- .../{country.py => models/res_country.py} | 0 .../{tax_view.xml => views/account_tax.xml} | 0 .../intrastat.xml} | 2 +- .../product_template.xml} | 0 .../res_company.xml} | 0 .../res_country.xml} | 2 +- .../res_partner.xml} | 0 17 files changed, 110 insertions(+), 31 deletions(-) rename intrastat_base/{ => data}/country_data.xml (100%) rename intrastat_base/{ => demo}/intrastat_demo.xml (100%) create mode 100644 intrastat_base/models/__init__.py rename intrastat_base/{tax.py => models/account_tax.py} (100%) rename intrastat_base/{ => models}/intrastat_common.py (90%) rename intrastat_base/{product.py => models/product_template.py} (100%) rename intrastat_base/{company.py => models/res_company.py} (100%) rename intrastat_base/{country.py => models/res_country.py} (100%) rename intrastat_base/{tax_view.xml => views/account_tax.xml} (100%) rename intrastat_base/{intrastat_view.xml => views/intrastat.xml} (94%) rename intrastat_base/{product_view.xml => views/product_template.xml} (100%) rename intrastat_base/{company_view.xml => views/res_company.xml} (100%) rename intrastat_base/{country_view.xml => views/res_country.xml} (96%) rename intrastat_base/{partner_view.xml => views/res_partner.xml} (100%) diff --git a/intrastat_base/README.rst b/intrastat_base/README.rst index a941d1d..1a5cc85 100644 --- a/intrastat_base/README.rst +++ b/intrastat_base/README.rst @@ -1,3 +1,9 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + + +===================== Intrastat Base Module ===================== @@ -12,16 +18,39 @@ such as: - *l10n_be_intrastat_product*: the module for the Intrastat Declaration for Belgium. -These country-specific modules can be found in the OCA localization for those countries. Installation ============ WARNING: + This module conflicts with the module *report_intrastat* from the official addons. If you have already installed the module *report_intrastat*, you should uninstall it first before installing this module. +Usage +===== + +To create H.S. codes, go to the menu *Sales > Configuration > Product Categories and Attributes > H.S. Codes*. + +Then you will be able to set the H.S. code on an product (under the *Information* tab) or on a product category. On the product form, you will also be able to set the *Country of Origin* of a product (for example, if the product is *made in China*, select *China* as *Country of Origin*). + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/91/8.0 + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed feedback `here `_. + + Credits ======= @@ -29,16 +58,18 @@ Contributors ------------ * Alexis de Lattre, Akretion +* Luc De Meyer, Noviat Maintainer ---------- - .. image:: http://odoo-community.org/logo.png :alt: Odoo Community Association :target: http://odoo-community.org This module is maintained by the OCA. -OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. To contribute to this module, please visit http://odoo-community.org. diff --git a/intrastat_base/__init__.py b/intrastat_base/__init__.py index 21b2067..cd5b2df 100644 --- a/intrastat_base/__init__.py +++ b/intrastat_base/__init__.py @@ -20,8 +20,4 @@ # ############################################################################## -from . import country -from . import product -from . import tax -from . import company -from . import intrastat_common +from . import models diff --git a/intrastat_base/__openerp__.py b/intrastat_base/__openerp__.py index ea5483f..f50f146 100644 --- a/intrastat_base/__openerp__.py +++ b/intrastat_base/__openerp__.py @@ -22,7 +22,7 @@ { 'name': 'Intrastat Reporting Base', - 'version': '1.1', + 'version': '1.2', 'category': 'Intrastat', 'license': 'AGPL-3', 'summary': 'Base module for Intrastat reporting', @@ -31,14 +31,16 @@ 'depends': ['base_vat'], 'conflicts': ['report_intrastat'], 'data': [ - 'country_data.xml', - 'product_view.xml', - 'partner_view.xml', - 'country_view.xml', - 'tax_view.xml', - 'company_view.xml', - 'intrastat_view.xml', + 'data/country_data.xml', + 'views/product_template.xml', + 'views/res_partner.xml', + 'views/res_country.xml', + 'views/account_tax.xml', + 'views/res_company.xml', + 'views/intrastat.xml', + ], + 'demo': [ + 'demo/intrastat_demo.xml', ], - 'demo': ['intrastat_demo.xml'], 'installable': True, } diff --git a/intrastat_base/country_data.xml b/intrastat_base/data/country_data.xml similarity index 100% rename from intrastat_base/country_data.xml rename to intrastat_base/data/country_data.xml diff --git a/intrastat_base/intrastat_demo.xml b/intrastat_base/demo/intrastat_demo.xml similarity index 100% rename from intrastat_base/intrastat_demo.xml rename to intrastat_base/demo/intrastat_demo.xml diff --git a/intrastat_base/models/__init__.py b/intrastat_base/models/__init__.py new file mode 100644 index 0000000..18530f9 --- /dev/null +++ b/intrastat_base/models/__init__.py @@ -0,0 +1,27 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Report intrastat base module for Odoo +# Copyright (C) 2011-2014 Akretion (http://www.akretion.com) +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from . import res_country +from . import product_template +from . import account_tax +from . import res_company +from . import intrastat_common diff --git a/intrastat_base/tax.py b/intrastat_base/models/account_tax.py similarity index 100% rename from intrastat_base/tax.py rename to intrastat_base/models/account_tax.py diff --git a/intrastat_base/intrastat_common.py b/intrastat_base/models/intrastat_common.py similarity index 90% rename from intrastat_base/intrastat_common.py rename to intrastat_base/models/intrastat_common.py index a18ea07..ae892c0 100644 --- a/intrastat_base/intrastat_common.py +++ b/intrastat_base/models/intrastat_common.py @@ -85,14 +85,16 @@ class IntrastatCommon(models.AbstractModel): return True @api.model - def _check_xml_schema(self, xml_root, xml_string, xsd_file): + def _check_xml_schema(self, xml_string, xsd_file): '''Validate the XML file against the XSD''' from lxml import etree + from StringIO import StringIO xsd_etree_obj = etree.parse( tools.file_open(xsd_file)) official_schema = etree.XMLSchema(xsd_etree_obj) try: - official_schema.assertValid(xml_root) + t = etree.parse(StringIO(xml_string)) + official_schema.assertValid(t) except Exception, e: # if the validation of the XSD fails, we arrive here logger = logging.getLogger(__name__) @@ -124,6 +126,13 @@ class IntrastatCommon(models.AbstractModel): 'datas_fname': filename}) return attach.id + @api.multi + def _unlink_attachments(self): + atts = self.env['ir.attachment'].search( + [('res_model', '=', self._name), + ('res_id', '=', self.id)]) + atts.unlink() + @api.model def _open_attach_view(self, attach_id, title='XML file'): '''Returns an action which opens the form view of the @@ -140,6 +149,20 @@ class IntrastatCommon(models.AbstractModel): } return action + @api.multi + 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 + @api.one def send_reminder_email(self, mail_template_xmlid): mail_template = self.env.ref(mail_template_xmlid) diff --git a/intrastat_base/product.py b/intrastat_base/models/product_template.py similarity index 100% rename from intrastat_base/product.py rename to intrastat_base/models/product_template.py diff --git a/intrastat_base/company.py b/intrastat_base/models/res_company.py similarity index 100% rename from intrastat_base/company.py rename to intrastat_base/models/res_company.py index 9fea8e4..2206c76 100644 --- a/intrastat_base/company.py +++ b/intrastat_base/models/res_company.py @@ -27,16 +27,6 @@ from openerp.exceptions import ValidationError class ResCompany(models.Model): _inherit = "res.company" - @api.one - @api.depends( - 'intrastat_remind_user_ids', 'intrastat_remind_user_ids.email') - def _compute_intrastat_email_list(self): - emails = [] - for user in self.intrastat_remind_user_ids: - if user.email: - emails.append(user.email) - self.intrastat_email_list = ','.join(emails) - intrastat_remind_user_ids = fields.Many2many( 'res.users', column1='company_id', column2='user_id', string="Users Receiving the Intrastat Reminder", @@ -46,6 +36,16 @@ class ResCompany(models.Model): compute='_compute_intrastat_email_list', string='List of emails of Users Receiving the Intrastat Reminder') + @api.one + @api.depends( + 'intrastat_remind_user_ids', 'intrastat_remind_user_ids.email') + def _compute_intrastat_email_list(self): + emails = [] + for user in self.intrastat_remind_user_ids: + if user.email: + emails.append(user.email) + self.intrastat_email_list = ','.join(emails) + @api.one @api.constrains('intrastat_remind_user_ids') def _check_intrastat_remind_users(self): diff --git a/intrastat_base/country.py b/intrastat_base/models/res_country.py similarity index 100% rename from intrastat_base/country.py rename to intrastat_base/models/res_country.py diff --git a/intrastat_base/tax_view.xml b/intrastat_base/views/account_tax.xml similarity index 100% rename from intrastat_base/tax_view.xml rename to intrastat_base/views/account_tax.xml diff --git a/intrastat_base/intrastat_view.xml b/intrastat_base/views/intrastat.xml similarity index 94% rename from intrastat_base/intrastat_view.xml rename to intrastat_base/views/intrastat.xml index 4d9c22a..7b4cdf7 100644 --- a/intrastat_base/intrastat_view.xml +++ b/intrastat_base/views/intrastat.xml @@ -17,7 +17,7 @@ parent="account.menu_finance_configuration" sequence="50"/> - + intrastat.result_view_form intrastat.result.view diff --git a/intrastat_base/product_view.xml b/intrastat_base/views/product_template.xml similarity index 100% rename from intrastat_base/product_view.xml rename to intrastat_base/views/product_template.xml diff --git a/intrastat_base/company_view.xml b/intrastat_base/views/res_company.xml similarity index 100% rename from intrastat_base/company_view.xml rename to intrastat_base/views/res_company.xml diff --git a/intrastat_base/country_view.xml b/intrastat_base/views/res_country.xml similarity index 96% rename from intrastat_base/country_view.xml rename to intrastat_base/views/res_country.xml index d887a22..ac0f6f6 100644 --- a/intrastat_base/country_view.xml +++ b/intrastat_base/views/res_country.xml @@ -32,7 +32,7 @@ - + intrastat.base.country.search res.country diff --git a/intrastat_base/partner_view.xml b/intrastat_base/views/res_partner.xml similarity index 100% rename from intrastat_base/partner_view.xml rename to intrastat_base/views/res_partner.xml From 7ed51c8b2679e30be0ffeee7c238798b6b0f9973 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Tue, 10 Nov 2015 21:36:50 +0100 Subject: [PATCH 11/44] [IMP] intrastat_base: A lot of imps: * Add product_origin_country_id on declaration/computation lines Copy incoterms and destination country from SO to invoice when invoicing from SO We need weight even when supplementary units is used Small cleanups and enhancements * Add support for accessory costs Add default values for intrastat transaction on company Code cleanup * If rounded weight is 0, put 1 Take into account the taxes for B2C Small code cleanup * Remove field exclude_from_intrastat Re-organise view of intrastat.product.declaration * Add option intrastat_accessory_costs on company Set more fields as invisible (localisation should put them visible if they need it) Fix handling of suppl. units when hs_code is empty on invoice line (but set on product) Small usability enhancements * Warning -> UserError * Inspired by the PR https://github.com/akretion/account-financial-reporting/pull/8 of Luc de Meyer * total_amount is a sum of integers, so it should be an integer Add transport mode in computation tree view * Demo VAT number should be on EU customers --- intrastat_base/__openerp__.py | 2 +- intrastat_base/demo/intrastat_demo.xml | 2 +- intrastat_base/models/__init__.py | 22 +------------- intrastat_base/models/account_tax.py | 2 +- intrastat_base/models/intrastat_common.py | 35 ++++++----------------- intrastat_base/models/product_template.py | 8 +----- intrastat_base/models/res_company.py | 2 +- intrastat_base/models/res_country.py | 2 +- intrastat_base/views/account_tax.xml | 5 ++-- intrastat_base/views/intrastat.xml | 2 +- intrastat_base/views/product_template.xml | 4 +-- 11 files changed, 22 insertions(+), 64 deletions(-) diff --git a/intrastat_base/__openerp__.py b/intrastat_base/__openerp__.py index f50f146..a9e92b0 100644 --- a/intrastat_base/__openerp__.py +++ b/intrastat_base/__openerp__.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Intrastat base module for Odoo diff --git a/intrastat_base/demo/intrastat_demo.xml b/intrastat_base/demo/intrastat_demo.xml index 953d92b..422afa8 100644 --- a/intrastat_base/demo/intrastat_demo.xml +++ b/intrastat_base/demo/intrastat_demo.xml @@ -18,7 +18,7 @@ True - + BE0443167858 True diff --git a/intrastat_base/models/__init__.py b/intrastat_base/models/__init__.py index 18530f9..a571f6a 100644 --- a/intrastat_base/models/__init__.py +++ b/intrastat_base/models/__init__.py @@ -1,24 +1,4 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Report intrastat base module for Odoo -# Copyright (C) 2011-2014 Akretion (http://www.akretion.com) -# @author Alexis de Lattre -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# -*- coding: utf-8 -*- from . import res_country from . import product_template diff --git a/intrastat_base/models/account_tax.py b/intrastat_base/models/account_tax.py index 197e51d..e11db59 100644 --- a/intrastat_base/models/account_tax.py +++ b/intrastat_base/models/account_tax.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Intrastat base module for Odoo diff --git a/intrastat_base/models/intrastat_common.py b/intrastat_base/models/intrastat_common.py index ae892c0..3d44b7c 100644 --- a/intrastat_base/models/intrastat_common.py +++ b/intrastat_base/models/intrastat_common.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Intrastat base module for Odoo @@ -21,8 +21,7 @@ ############################################################################## from openerp import models, fields, api, tools, _ -from openerp.exceptions import Warning, ValidationError -from dateutil.relativedelta import relativedelta +from openerp.exceptions import Warning as UserError import logging logger = logging.getLogger(__name__) @@ -36,7 +35,7 @@ class IntrastatCommon(models.AbstractModel): @api.one @api.depends('declaration_line_ids.amount_company_currency') def _compute_numbers(self): - total_amount = 0.0 + total_amount = 0 # it is an integer num_lines = 0 for line in self.declaration_line_ids: total_amount += line.amount_company_currency @@ -44,34 +43,18 @@ class IntrastatCommon(models.AbstractModel): self.num_decl_lines = num_lines self.total_amount = total_amount - @api.one - @api.depends('start_date') - def _compute_dates(self): - start_date_dt = fields.Date.from_string(self.start_date) - self.end_date = fields.Date.to_string( - start_date_dt + relativedelta(day=31)) - self.year_month = start_date_dt.strftime('%Y-%m') - - @api.one - def _check_start_date(self): - '''Check that the start date is the first day of the month''' - datetime_to_check = fields.Date.from_string(self.start_date) - if datetime_to_check.day != 1: - raise ValidationError( - _('The start date must be the first day of the month')) - @api.one def _check_generate_lines(self): """Check wether all requirements are met for generating lines.""" if not self.company_id: - raise Warning(_("Company not yet set on intrastat report.")) + raise UserError(_("Company not yet set on intrastat report.")) company_obj = self.company_id if not company_obj.country_id: - raise Warning( + raise UserError( _("The country is not set on the company '%s'.") % company_obj.name) if company_obj.currency_id.name != 'EUR': - raise Warning( + raise UserError( _("The company currency must be 'EUR', but is currently '%s'.") % company_obj.currency_id.name) return True @@ -79,7 +62,7 @@ class IntrastatCommon(models.AbstractModel): @api.one def _check_generate_xml(self): if not self.company_id.partner_id.vat: - raise Warning( + raise UserError( _("The VAT number is not set for the partner '%s'.") % self.company_id.partner_id.name) return True @@ -102,7 +85,7 @@ class IntrastatCommon(models.AbstractModel): "The XML file is invalid against the XML Schema Definition") logger.warning(xml_string) logger.warning(e) - raise Warning( + raise UserError( _("The generated XML file is not valid against the official " "XML Schema Definition. The generated XML file and the " "full error have been written in the server logs. " @@ -181,7 +164,7 @@ class IntrastatCommon(models.AbstractModel): def unlink(self): for intrastat in self: if intrastat.state == 'done': - raise Warning( + raise UserError( _('Cannot delete the declaration %s ' 'because it is in Done state') % self.year_month) return super(IntrastatCommon, self).unlink() diff --git a/intrastat_base/models/product_template.py b/intrastat_base/models/product_template.py index 5373cb3..30132bc 100644 --- a/intrastat_base/models/product_template.py +++ b/intrastat_base/models/product_template.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Intrastat base module for Odoo @@ -27,12 +27,6 @@ from openerp.exceptions import ValidationError class ProductTemplate(models.Model): _inherit = "product.template" - exclude_from_intrastat = fields.Boolean( - string='Exclude from Intrastat reports', - help="If set to True, the product or service will not be " - "taken into account for Intrastat Product or Service reports. " - "So you should leave this field to False unless you have a " - "very good reason.") is_accessory_cost = fields.Boolean( string='Is accessory cost', help="Activate this option for shipping costs, packaging " diff --git a/intrastat_base/models/res_company.py b/intrastat_base/models/res_company.py index 2206c76..1175d76 100644 --- a/intrastat_base/models/res_company.py +++ b/intrastat_base/models/res_company.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Intrastat base module for Odoo diff --git a/intrastat_base/models/res_country.py b/intrastat_base/models/res_country.py index 7a34e77..8703f10 100644 --- a/intrastat_base/models/res_country.py +++ b/intrastat_base/models/res_country.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Intrastat base module for Odoo diff --git a/intrastat_base/views/account_tax.xml b/intrastat_base/views/account_tax.xml index 5defe29..1e91bb5 100644 --- a/intrastat_base/views/account_tax.xml +++ b/intrastat_base/views/account_tax.xml @@ -1,7 +1,7 @@ @@ -16,7 +16,8 @@ - + + diff --git a/intrastat_base/views/intrastat.xml b/intrastat_base/views/intrastat.xml index 7b4cdf7..73762d0 100644 --- a/intrastat_base/views/intrastat.xml +++ b/intrastat_base/views/intrastat.xml @@ -11,7 +11,7 @@ diff --git a/intrastat_base/views/product_template.xml b/intrastat_base/views/product_template.xml index dc61ca5..1f4f73f 100644 --- a/intrastat_base/views/product_template.xml +++ b/intrastat_base/views/product_template.xml @@ -16,9 +16,9 @@ - + attrs="{'invisible': [('type', '!=', 'service')]}" + invisible="1"/> From 3f4de3d06cabf460f3a6016133f169d7fa7c9636 Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Mon, 30 May 2016 13:02:55 +0200 Subject: [PATCH 12/44] [FIX] intrastat_base: this week's ci errors + wrong variable name --- intrastat_base/__openerp__.py | 2 +- intrastat_base/models/intrastat_common.py | 75 ++++++++++++----------- intrastat_base/models/product_template.py | 17 ++--- intrastat_base/models/res_company.py | 26 ++++---- 4 files changed, 64 insertions(+), 56 deletions(-) diff --git a/intrastat_base/__openerp__.py b/intrastat_base/__openerp__.py index a9e92b0..594ff8a 100644 --- a/intrastat_base/__openerp__.py +++ b/intrastat_base/__openerp__.py @@ -22,7 +22,7 @@ { 'name': 'Intrastat Reporting Base', - 'version': '1.2', + 'version': '8.0.1.2.0', 'category': 'Intrastat', 'license': 'AGPL-3', 'summary': 'Base module for Intrastat reporting', diff --git a/intrastat_base/models/intrastat_common.py b/intrastat_base/models/intrastat_common.py index 3d44b7c..ff49c96 100644 --- a/intrastat_base/models/intrastat_common.py +++ b/intrastat_base/models/intrastat_common.py @@ -32,39 +32,43 @@ class IntrastatCommon(models.AbstractModel): _description = "Common functions for intrastat reports for products " "and services" - @api.one + @api.multi @api.depends('declaration_line_ids.amount_company_currency') def _compute_numbers(self): - total_amount = 0 # it is an integer - num_lines = 0 - for line in self.declaration_line_ids: - total_amount += line.amount_company_currency - num_lines += 1 - self.num_decl_lines = num_lines - self.total_amount = total_amount + for this in self: + total_amount = 0 # it is an integer + num_lines = 0 + for line in this.declaration_line_ids: + total_amount += line.amount_company_currency + num_lines += 1 + this.num_decl_lines = num_lines + this.total_amount = total_amount - @api.one + @api.multi def _check_generate_lines(self): """Check wether all requirements are met for generating lines.""" - if not self.company_id: - raise UserError(_("Company not yet set on intrastat report.")) - company_obj = self.company_id - if not company_obj.country_id: - raise UserError( - _("The country is not set on the company '%s'.") - % company_obj.name) - if company_obj.currency_id.name != 'EUR': - raise UserError( - _("The company currency must be 'EUR', but is currently '%s'.") - % company_obj.currency_id.name) + for this in self: + if not this.company_id: + raise UserError(_("Company not yet set on intrastat report.")) + company = this.company_id + if not company.country_id: + raise UserError( + _("The country is not set on the company '%s'.") + % company.name) + if company.currency_id.name != 'EUR': + raise UserError( + _("The company currency must be 'EUR', but is currently " + "'%s'.") + % company.currency_id.name) return True - @api.one + @api.multi def _check_generate_xml(self): - 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.name) + 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) return True @api.model @@ -146,18 +150,19 @@ class IntrastatCommon(models.AbstractModel): """ return False - @api.one + @api.multi def send_reminder_email(self, mail_template_xmlid): mail_template = self.env.ref(mail_template_xmlid) - if self.company_id.intrastat_remind_user_ids: - mail_template.send_mail(self.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' % self.company_id.name) + 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 @api.multi diff --git a/intrastat_base/models/product_template.py b/intrastat_base/models/product_template.py index 30132bc..07e0b2b 100644 --- a/intrastat_base/models/product_template.py +++ b/intrastat_base/models/product_template.py @@ -33,13 +33,14 @@ class ProductTemplate(models.Model): "costs and all services related to the sale of products. " "This option is used for Intrastat reports.") - @api.one + @api.multi @api.constrains('type', 'is_accessory_cost') def _check_accessory_cost(self): - if self.is_accessory_cost and self.type != 'service': - raise ValidationError( - _("The option 'Is accessory cost?' should only be " - "activated on 'Service' products. You have activated " - "this option for the product '%s' which is of type " - "'%s'" - % (self.name, self.type))) + for this in self: + if this.is_accessory_cost and this.type != 'service': + raise ValidationError( + _("The option 'Is accessory cost?' should only be " + "activated on 'Service' products. You have activated " + "this option for the product '%s' which is of type " + "'%s'") % + (this.name, this.type)) diff --git a/intrastat_base/models/res_company.py b/intrastat_base/models/res_company.py index 1175d76..291d846 100644 --- a/intrastat_base/models/res_company.py +++ b/intrastat_base/models/res_company.py @@ -36,21 +36,23 @@ class ResCompany(models.Model): compute='_compute_intrastat_email_list', string='List of emails of Users Receiving the Intrastat Reminder') - @api.one + @api.multi @api.depends( 'intrastat_remind_user_ids', 'intrastat_remind_user_ids.email') def _compute_intrastat_email_list(self): - emails = [] - for user in self.intrastat_remind_user_ids: - if user.email: - emails.append(user.email) - self.intrastat_email_list = ','.join(emails) + for this in self: + emails = [] + for user in this.intrastat_remind_user_ids: + if user.email: + emails.append(user.email) + this.intrastat_email_list = ','.join(emails) - @api.one + @api.multi @api.constrains('intrastat_remind_user_ids') def _check_intrastat_remind_users(self): - for user in self.intrastat_remind_user_ids: - if not user.email: - raise ValidationError( - _("Missing e-mail address on user '%s'.") - % (user.name)) + for this in self: + for user in this.intrastat_remind_user_ids: + if not user.email: + raise ValidationError( + _("Missing e-mail address on user '%s'.") % + (user.name)) From a8c798a32462e493421b129db38a8092da1c1027 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Tue, 21 Jun 2016 10:41:52 +0200 Subject: [PATCH 13/44] Cleaner view inheritance (works both in v8 and v9) --- intrastat_base/views/res_company.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intrastat_base/views/res_company.xml b/intrastat_base/views/res_company.xml index 1df7aed..0565f00 100644 --- a/intrastat_base/views/res_company.xml +++ b/intrastat_base/views/res_company.xml @@ -14,8 +14,8 @@ res.company - - + + From bb1ab1c1885294d26882ebe5543e9a9bf39185a9 Mon Sep 17 00:00:00 2001 From: luc-demeyer Date: Mon, 3 Oct 2016 15:25:23 +0200 Subject: [PATCH 14/44] update intrastat_base --- intrastat_base/__init__.py | 23 +---------------------- intrastat_base/__openerp__.py | 2 +- intrastat_base/views/account_tax.xml | 3 +-- 3 files changed, 3 insertions(+), 25 deletions(-) diff --git a/intrastat_base/__init__.py b/intrastat_base/__init__.py index cd5b2df..a0fdc10 100644 --- a/intrastat_base/__init__.py +++ b/intrastat_base/__init__.py @@ -1,23 +1,2 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Report intrastat base module for Odoo -# Copyright (C) 2011-2014 Akretion (http://www.akretion.com) -# @author Alexis de Lattre -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - +# -*- coding: utf-8 -*- from . import models diff --git a/intrastat_base/__openerp__.py b/intrastat_base/__openerp__.py index 594ff8a..12a810b 100644 --- a/intrastat_base/__openerp__.py +++ b/intrastat_base/__openerp__.py @@ -22,7 +22,7 @@ { 'name': 'Intrastat Reporting Base', - 'version': '8.0.1.2.0', + 'version': '8.0.1.3.0', 'category': 'Intrastat', 'license': 'AGPL-3', 'summary': 'Base module for Intrastat reporting', diff --git a/intrastat_base/views/account_tax.xml b/intrastat_base/views/account_tax.xml index 1e91bb5..d38cee6 100644 --- a/intrastat_base/views/account_tax.xml +++ b/intrastat_base/views/account_tax.xml @@ -16,8 +16,7 @@ - - + From 6c50d22e18ce4d0b2c7fe00ed2c0cf537e8266b0 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Tue, 4 Oct 2016 00:41:33 +0200 Subject: [PATCH 15/44] [IMP] intrastat_base: Update README.rst + rename variables + restore code lost in transition to github/OCA/intrastat --- intrastat_base/README.rst | 44 ++--- intrastat_base/i18n/fr_FR.po | 182 -------------------- intrastat_base/security/ir.model.access.csv | 2 - intrastat_base/views/res_partner.xml | 11 +- 4 files changed, 28 insertions(+), 211 deletions(-) delete mode 100644 intrastat_base/i18n/fr_FR.po delete mode 100644 intrastat_base/security/ir.model.access.csv diff --git a/intrastat_base/README.rst b/intrastat_base/README.rst index 1a5cc85..284f240 100644 --- a/intrastat_base/README.rst +++ b/intrastat_base/README.rst @@ -2,14 +2,14 @@ :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 +============== +Intrastat Base +============== -===================== -Intrastat Base Module -===================== - -This module contains common functions for the Intrastat reporting and -should be used in combination with country-specific reporting modules -such as: +This module contains common functions for the intrastat reporting and +should be used in combination with the generic reporting module +*intrastat_product* and with the country-specific reporting modules such +as: - *l10n_fr_intrastat_service*: the module for the *Déclaration Européenne des Services* (DES) for France @@ -31,25 +31,28 @@ you should uninstall it first before installing this module. Usage ===== -To create H.S. codes, go to the menu *Sales > Configuration > Product Categories and Attributes > H.S. Codes*. +This module adds an intrastat property on countries and activates this property +on the 28 countries of the European Union. -Then you will be able to set the H.S. code on an product (under the *Information* tab) or on a product category. On the product form, you will also be able to set the *Country of Origin* of a product (for example, if the product is *made in China*, select *China* as *Country of Origin*). +With this module, the country field on partners becomes a required field. + +It adds an option *Exclude invoice line from intrastat if this tax is present* +on taxes. + +It adds a tab *Intrastat* on the company form view. .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot :target: https://runbot.odoo-community.org/runbot/91/8.0 - Bug Tracker =========== -Bugs are tracked on `GitHub Issues `_. -In case of trouble, please check there if your issue has already been reported. -If you spotted it first, help us smashing it by providing a detailed and welcomed feedback `here `_. - +Bugs are tracked on `GitHub Issues +`_. In case +of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and +welcomed feedback. Credits ======= @@ -62,9 +65,10 @@ Contributors Maintainer ---------- -.. image:: http://odoo-community.org/logo.png + +.. image:: https://odoo-community.org/logo.png :alt: Odoo Community Association - :target: http://odoo-community.org + :target: https://odoo-community.org This module is maintained by the OCA. @@ -72,4 +76,4 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -To contribute to this module, please visit http://odoo-community.org. +To contribute to this module, please visit https://odoo-community.org. diff --git a/intrastat_base/i18n/fr_FR.po b/intrastat_base/i18n/fr_FR.po deleted file mode 100644 index 1b3d759..0000000 --- a/intrastat_base/i18n/fr_FR.po +++ /dev/null @@ -1,182 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * intrastat_base -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-05-27 18:43+0000\n" -"PO-Revision-Date: 2015-05-27 18:43+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: intrastat_base -#: help:product.template,is_accessory_cost:0 -msgid "Activate this option for shipping costs, packaging costs and all services related to the sale of products. This option is used for Intrastat reports." -msgstr "Activez cette option pour les frais de port, les frais d'emballage et tous les services liés à la vente de produits physiques. Cette option est utilisée pour la DEB et la DES." - -#. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:165 -#, python-format -msgid "Cannot delete the declaration %s because it is in Done state" -msgstr "Impossible de supprimer la déclaration %s car elle est à l'état déclaré" - -#. module: intrastat_base -#: view:res.company:intrastat_base.view_company_form -msgid "Common Intrastat Settings" -msgstr "Paramètres communs DEB et DES" - -#. module: intrastat_base -#: model:ir.model,name:intrastat_base.model_report_intrastat_common -msgid "Common functions for intrastat reports for products " -msgstr "" - -#. module: intrastat_base -#: model:ir.model,name:intrastat_base.model_res_company -msgid "Companies" -msgstr "Sociétés" - -#. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:68 -#, python-format -msgid "Company not yet set on intrastat report." -msgstr "Société non configurée sur le rapport intrastat." - -#. module: intrastat_base -#: model:ir.model,name:intrastat_base.model_res_country -msgid "Country" -msgstr "Pays" - -#. module: intrastat_base -#: view:res.country:intrastat_base.view_country_search -#: field:res.country,intrastat:0 -msgid "EU Country" -msgstr "Pays UE" - -#. module: intrastat_base -#: field:product.template,exclude_from_intrastat:0 -msgid "Exclude from Intrastat reports" -msgstr "Exclure de la DEB et de la DES" - -#. module: intrastat_base -#: field:account.tax,exclude_from_intrastat_if_present:0 -msgid "Exclude invoice line from intrastat if this tax is present" -msgstr "Exclue la ligne de facture de la DEB/DES si cette taxe est présente" - -#. module: intrastat_base -#: field:report.intrastat.common,id:0 -msgid "ID" -msgstr "ID" - -#. module: intrastat_base -#: help:product.template,exclude_from_intrastat:0 -msgid "If set to True, the product or service will not be taken into account for Intrastat Product or Service reports. So you should leave this field to False unless you have a very good reason." -msgstr "Si l'option est activée, le produit ou service ne sera pris en compte ni pour la DEB ni pour la DES. Cette option doit donc rester désactivée sauf si vous avez une très bonne raison." - -#. module: intrastat_base -#: help:account.tax,exclude_from_intrastat_if_present:0 -msgid "If this tax is present on an invoice line, this invoice line will be skipped when generating Intrastat Product or Service lines from invoices." -msgstr "Si cette taxe est présente sur une ligne de facture, cette ligne de facture ne sera pas prise en compte lors de la génération de la DEB et de la DES depuis les factures." - -#. module: intrastat_base -#: view:product.template:intrastat_base.product_template_form_view -msgid "Intrastat Properties" -msgstr "Propriétés DEB/DES" - -#. module: intrastat_base -#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root -msgid "Intrastat Reporting" -msgstr "DEB et DES" - -#. module: intrastat_base -#: view:res.company:intrastat_base.view_company_form -msgid "Intrastat Settings" -msgstr "Configuration DEB/DES" - -#. module: intrastat_base -#: field:product.template,is_accessory_cost:0 -msgid "Is accessory cost" -msgstr "Frais accessoires" - -#. module: intrastat_base -#: help:res.company,intrastat_remind_user_ids:0 -msgid "List of OpenERP users who will receive a notification to remind them about the Intrastat declaration." -msgstr "Liste d'utilisateurs OpenERP qui recevront le rappel pour la DEB et/ou la DES." - -#. module: intrastat_base -#: code:addons/intrastat_base/company.py:55 -#, python-format -msgid "Missing e-mail address on user '%s'." -msgstr "Adresse e-mail manquante sur l'utilisateur '%s'." - -#. module: intrastat_base -#: model:ir.model,name:intrastat_base.model_product_template -msgid "Product Template" -msgstr "Modèle d'article" - -#. module: intrastat_base -#: view:res.country:intrastat_base.view_country_search -msgid "Search Countries" -msgstr "Recherche des pays" - -#. module: intrastat_base -#: help:res.country,intrastat:0 -msgid "Set to True for all European Union countries." -msgstr "A cocher pour tous les pays de l'Union Européenne." - -#. module: intrastat_base -#: model:product.template,name:intrastat_base.shipping_costs_exclude_product_template -msgid "Shipping costs" -msgstr "Frais de port" - -#. module: intrastat_base -#: model:ir.model,name:intrastat_base.model_account_tax -msgid "Tax" -msgstr "Taxes" - -#. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:84 -#, python-format -msgid "The VAT number is not set for the partner '%s'." -msgstr "Le numéro de TVA n'est pas renseigné pour le partenaire '%s'." - -#. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:76 -#, python-format -msgid "The company currency must be 'EUR', but is currently '%s'." -msgstr "La monnaie de la société doit être 'EUR', mais est actuellement '%s'." - -#. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:72 -#, python-format -msgid "The country is not set on the company '%s'." -msgstr "Le pays n'est pas renseigné sur la société '%s'." - -#. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:105 -#, python-format -msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s." -msgstr "La validation du fichier XML avec le schéma XML officiel a échoué. Le fichier XML généré et le détail de l'erreur ont été écrits dans les logs du serveur. Voici le message d'erreur, qui peut vous donner une idée de la cause du problème : %s." - -#. module: intrastat_base -#: code:addons/intrastat_base/product.py:51 -#, python-format -msgid "The option 'Is accessory cost?' should only be activated on 'Service' products. You have activated this option for the product '%s' which is of type '%s'" -msgstr "L'option 'Frais accessoires' ne doit être activée que sur les produits de type 'Service'. Vous avez activé cette option sur le produit '%s' qui est de type '%s'" - -#. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:62 -#, python-format -msgid "The start date must be the first day of the month" -msgstr "La date de début doit être le premier jour du mois" - -#. module: intrastat_base -#: field:res.company,intrastat_remind_user_ids:0 -msgid "Users Receiving the Intrastat Reminder" -msgstr "Utilisateurs qui reçoivent le rappel DEB/DES" - diff --git a/intrastat_base/security/ir.model.access.csv b/intrastat_base/security/ir.model.access.csv deleted file mode 100644 index d7a2bf1..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_report_intrastat_common","Read access on report.intrastat.common","model_report_intrastat_common","base.group_user",1,0,0,0 diff --git a/intrastat_base/views/res_partner.xml b/intrastat_base/views/res_partner.xml index 7dc9f4e..6184e8c 100644 --- a/intrastat_base/views/res_partner.xml +++ b/intrastat_base/views/res_partner.xml @@ -9,21 +9,18 @@ - + res.partner - - {'readonly': [('use_parent_address','=',True)], 'required': True} + + 1 - - {'required': True} + 1 - From bf35526b313bb2a5d84cf704ce66c58dfbca5b82 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Tue, 11 Oct 2016 14:59:28 +0200 Subject: [PATCH 16/44] [MIG] intrastat_base: Migration to v10 * Update README.rst: switch to new intrastat project * Move Intrastat menu entry to Accounting > Report instead of Accounting > Report > PDF Reports (because intrastat reports are not in PDF !) --- intrastat_base/README.rst | 4 +- intrastat_base/__manifest__.py | 28 +++ intrastat_base/__openerp__.py | 46 ----- intrastat_base/data/country_data.xml | 175 +++++++++--------- intrastat_base/demo/intrastat_demo.xml | 40 +--- intrastat_base/models/__init__.py | 1 + .../models/account_config_settings.py | 12 ++ intrastat_base/models/account_tax.py | 24 +-- intrastat_base/models/intrastat_common.py | 26 +-- intrastat_base/models/product_template.py | 26 +-- intrastat_base/models/res_company.py | 28 +-- intrastat_base/models/res_country.py | 24 +-- .../views/account_config_settings.xml | 23 +++ intrastat_base/views/account_tax.xml | 14 +- intrastat_base/views/intrastat.xml | 15 +- intrastat_base/views/product_template.xml | 16 +- intrastat_base/views/res_company.xml | 29 --- intrastat_base/views/res_country.xml | 12 +- intrastat_base/views/res_partner.xml | 13 +- 19 files changed, 206 insertions(+), 350 deletions(-) create mode 100644 intrastat_base/__manifest__.py delete mode 100644 intrastat_base/__openerp__.py create mode 100644 intrastat_base/models/account_config_settings.py create mode 100644 intrastat_base/views/account_config_settings.xml delete mode 100644 intrastat_base/views/res_company.xml diff --git a/intrastat_base/README.rst b/intrastat_base/README.rst index 284f240..65531ec 100644 --- a/intrastat_base/README.rst +++ b/intrastat_base/README.rst @@ -43,13 +43,13 @@ It adds a tab *Intrastat* on the company form view. .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/91/8.0 + :target: https://runbot.odoo-community.org/runbot/227/10.0 Bug Tracker =========== Bugs are tracked on `GitHub Issues -`_. In case +`_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed feedback. diff --git a/intrastat_base/__manifest__.py b/intrastat_base/__manifest__.py new file mode 100644 index 0000000..c30463a --- /dev/null +++ b/intrastat_base/__manifest__.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# © 2011-2016 Akretion (http://www.akretion.com) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Intrastat Reporting Base', + 'version': '10.0.1.0.0', + 'category': 'Intrastat', + 'license': 'AGPL-3', + 'summary': 'Base module for Intrastat reporting', + 'author': 'Akretion,Odoo Community Association (OCA)', + 'website': 'http://www.akretion.com', + 'depends': ['base_vat'], + 'conflicts': ['report_intrastat'], + 'data': [ + 'data/country_data.xml', + 'views/product_template.xml', + 'views/res_partner.xml', + 'views/res_country.xml', + 'views/account_tax.xml', + 'views/account_config_settings.xml', + 'views/intrastat.xml', + ], + 'demo': [ + 'demo/intrastat_demo.xml', + ], + 'installable': True, +} diff --git a/intrastat_base/__openerp__.py b/intrastat_base/__openerp__.py deleted file mode 100644 index 12a810b..0000000 --- a/intrastat_base/__openerp__.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Intrastat base module for Odoo -# Copyright (C) 2011-2015 Akretion (http://www.akretion.com) -# @author Alexis de Lattre -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -{ - 'name': 'Intrastat Reporting Base', - 'version': '8.0.1.3.0', - 'category': 'Intrastat', - 'license': 'AGPL-3', - 'summary': 'Base module for Intrastat reporting', - 'author': 'Akretion,Odoo Community Association (OCA)', - 'website': 'http://www.akretion.com', - 'depends': ['base_vat'], - 'conflicts': ['report_intrastat'], - 'data': [ - 'data/country_data.xml', - 'views/product_template.xml', - 'views/res_partner.xml', - 'views/res_country.xml', - 'views/account_tax.xml', - 'views/res_company.xml', - 'views/intrastat.xml', - ], - 'demo': [ - 'demo/intrastat_demo.xml', - ], - 'installable': True, -} diff --git a/intrastat_base/data/country_data.xml b/intrastat_base/data/country_data.xml index c77f548..3c75a3a 100644 --- a/intrastat_base/data/country_data.xml +++ b/intrastat_base/data/country_data.xml @@ -1,90 +1,89 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/intrastat_base/demo/intrastat_demo.xml b/intrastat_base/demo/intrastat_demo.xml index 422afa8..f53d397 100644 --- a/intrastat_base/demo/intrastat_demo.xml +++ b/intrastat_base/demo/intrastat_demo.xml @@ -1,57 +1,27 @@ - - - + FR58441019213 - - BE0828696437 - True - - - - BE0443167858 - True - - BE0884025633 True - - True - - - - True - - - - True - - - - True - - Shipping costs - SHIP + SHIP service 30 True - - + diff --git a/intrastat_base/models/__init__.py b/intrastat_base/models/__init__.py index a571f6a..fa36185 100644 --- a/intrastat_base/models/__init__.py +++ b/intrastat_base/models/__init__.py @@ -4,4 +4,5 @@ from . import res_country from . import product_template from . import account_tax from . import res_company +from . import account_config_settings from . import intrastat_common diff --git a/intrastat_base/models/account_config_settings.py b/intrastat_base/models/account_config_settings.py new file mode 100644 index 0000000..78a9fca --- /dev/null +++ b/intrastat_base/models/account_config_settings.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# © 2017 Akretion (Alexis de Lattre ) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models, fields + + +class AccountConfigSettings(models.TransientModel): + _inherit = 'account.config.settings' + + intrastat_remind_user_ids = fields.Many2many( + related='company_id.intrastat_remind_user_ids') diff --git a/intrastat_base/models/account_tax.py b/intrastat_base/models/account_tax.py index e11db59..f9997fc 100644 --- a/intrastat_base/models/account_tax.py +++ b/intrastat_base/models/account_tax.py @@ -1,26 +1,8 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Intrastat base module for Odoo -# Copyright (C) 2011-2014 Akretion (http://www.akretion.com). -# @author Alexis de Lattre -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2011-2016 Akretion (http://www.akretion.com). +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import models, fields +from odoo import models, fields class AccountTax(models.Model): diff --git a/intrastat_base/models/intrastat_common.py b/intrastat_base/models/intrastat_common.py index ff49c96..de3b04b 100644 --- a/intrastat_base/models/intrastat_common.py +++ b/intrastat_base/models/intrastat_common.py @@ -1,27 +1,9 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Intrastat base module for Odoo -# Copyright (C) 2010-2014 Akretion (http://www.akretion.com/). -# @author Alexis de Lattre -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2010-2016 Akretion (Alexis de Lattre ) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import models, fields, api, tools, _ -from openerp.exceptions import Warning as UserError +from odoo import models, fields, api, tools, _ +from odoo.exceptions import UserError import logging logger = logging.getLogger(__name__) diff --git a/intrastat_base/models/product_template.py b/intrastat_base/models/product_template.py index 07e0b2b..71cb987 100644 --- a/intrastat_base/models/product_template.py +++ b/intrastat_base/models/product_template.py @@ -1,27 +1,9 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Intrastat base module for Odoo -# Copyright (C) 2010-2014 Akretion (http://www.akretion.com/) -# @author Alexis de Lattre -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2010-2016 Akretion (Alexis de Lattre ) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import models, fields, api, _ -from openerp.exceptions import ValidationError +from odoo import models, fields, api, _ +from odoo.exceptions import ValidationError class ProductTemplate(models.Model): diff --git a/intrastat_base/models/res_company.py b/intrastat_base/models/res_company.py index 291d846..5d4a4e7 100644 --- a/intrastat_base/models/res_company.py +++ b/intrastat_base/models/res_company.py @@ -1,27 +1,9 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Intrastat base module for Odoo -# Copyright (C) 2013-2014 Akretion (http://www.akretion.com) -# @author Alexis de Lattre -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2013-2017 Akretion (Alexis de Lattre ) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import models, fields, api, _ -from openerp.exceptions import ValidationError +from odoo import models, fields, api, _ +from odoo.exceptions import ValidationError class ResCompany(models.Model): @@ -30,7 +12,7 @@ class ResCompany(models.Model): intrastat_remind_user_ids = fields.Many2many( 'res.users', column1='company_id', column2='user_id', string="Users Receiving the Intrastat Reminder", - help="List of OpenERP users who will receive a notification to " + help="List of Odoo users who will receive a notification to " "remind them about the Intrastat declaration.") intrastat_email_list = fields.Char( compute='_compute_intrastat_email_list', diff --git a/intrastat_base/models/res_country.py b/intrastat_base/models/res_country.py index 8703f10..19f34f2 100644 --- a/intrastat_base/models/res_country.py +++ b/intrastat_base/models/res_country.py @@ -1,26 +1,8 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Intrastat base module for Odoo -# Copyright (C) 2011-2014 Akretion (http://www.akretion.com). -# @author Alexis de Lattre -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2011-2014 Akretion (Alexis de Lattre ) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import models, fields +from odoo import models, fields class ResCountry(models.Model): diff --git a/intrastat_base/views/account_config_settings.xml b/intrastat_base/views/account_config_settings.xml new file mode 100644 index 0000000..c890c40 --- /dev/null +++ b/intrastat_base/views/account_config_settings.xml @@ -0,0 +1,23 @@ + + + + + + + intrastat.account.config.settings.form + account.config.settings + + + + + + + + + + + + diff --git a/intrastat_base/views/account_tax.xml b/intrastat_base/views/account_tax.xml index d38cee6..a1e72cd 100644 --- a/intrastat_base/views/account_tax.xml +++ b/intrastat_base/views/account_tax.xml @@ -1,13 +1,10 @@ - - - + @@ -15,11 +12,10 @@ account.tax - + - - + diff --git a/intrastat_base/views/intrastat.xml b/intrastat_base/views/intrastat.xml index 73762d0..cc5a186 100644 --- a/intrastat_base/views/intrastat.xml +++ b/intrastat_base/views/intrastat.xml @@ -1,18 +1,16 @@ - - - + + parent="account.menu_finance_reports" sequence="50"/> @@ -32,5 +30,4 @@
-
- + diff --git a/intrastat_base/views/product_template.xml b/intrastat_base/views/product_template.xml index 1f4f73f..6440407 100644 --- a/intrastat_base/views/product_template.xml +++ b/intrastat_base/views/product_template.xml @@ -1,13 +1,11 @@ - - - + + intrastat.base.product.template.form @@ -16,6 +14,8 @@ + @@ -24,5 +24,5 @@ - - + + diff --git a/intrastat_base/views/res_company.xml b/intrastat_base/views/res_company.xml deleted file mode 100644 index 0565f00..0000000 --- a/intrastat_base/views/res_company.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - intrastat.company.form - res.company - - - - - - - - - - - - - - - diff --git a/intrastat_base/views/res_country.xml b/intrastat_base/views/res_country.xml index ac0f6f6..e9dec05 100644 --- a/intrastat_base/views/res_country.xml +++ b/intrastat_base/views/res_country.xml @@ -1,12 +1,11 @@ - - - + + @@ -46,5 +45,4 @@ - - + diff --git a/intrastat_base/views/res_partner.xml b/intrastat_base/views/res_partner.xml index 6184e8c..7a9dfeb 100644 --- a/intrastat_base/views/res_partner.xml +++ b/intrastat_base/views/res_partner.xml @@ -1,13 +1,11 @@ - - - + @@ -24,5 +22,4 @@
- - + From a74f5cfc4f2bbfb7b9679c256bd390c9cbfab31f Mon Sep 17 00:00:00 2001 From: Kumar Aberer Date: Fri, 9 Mar 2018 16:29:05 +0100 Subject: [PATCH 17/44] [MIG] intrastat_base: Migration to 11.0 --- intrastat_base/README.rst | 1 + intrastat_base/__manifest__.py | 9 +++--- intrastat_base/models/__init__.py | 2 +- intrastat_base/models/intrastat_common.py | 6 ++-- ...fig_settings.py => res_config_settings.py} | 5 ++-- .../views/account_config_settings.xml | 23 -------------- intrastat_base/views/res_config_settings.xml | 30 +++++++++++++++++++ 7 files changed, 43 insertions(+), 33 deletions(-) rename intrastat_base/models/{account_config_settings.py => res_config_settings.py} (65%) delete mode 100644 intrastat_base/views/account_config_settings.xml create mode 100644 intrastat_base/views/res_config_settings.xml diff --git a/intrastat_base/README.rst b/intrastat_base/README.rst index 65531ec..09a4328 100644 --- a/intrastat_base/README.rst +++ b/intrastat_base/README.rst @@ -62,6 +62,7 @@ Contributors * Alexis de Lattre, Akretion * Luc De Meyer, Noviat +* Kumar Aberer, brain-tec AG Maintainer ---------- diff --git a/intrastat_base/__manifest__.py b/intrastat_base/__manifest__.py index c30463a..ba5a0f1 100644 --- a/intrastat_base/__manifest__.py +++ b/intrastat_base/__manifest__.py @@ -1,16 +1,17 @@ # -*- coding: utf-8 -*- # © 2011-2016 Akretion (http://www.akretion.com) +# © 2018 brain-tec AG (Kumar Aberer ) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { 'name': 'Intrastat Reporting Base', - 'version': '10.0.1.0.0', + 'version': '11.0.1.0.0', 'category': 'Intrastat', 'license': 'AGPL-3', 'summary': 'Base module for Intrastat reporting', - 'author': 'Akretion,Odoo Community Association (OCA)', + 'author': 'Akretion,Odoo Community Association (OCA), brain-tec AG', 'website': 'http://www.akretion.com', - 'depends': ['base_vat'], + 'depends': ['base_vat', 'account'], 'conflicts': ['report_intrastat'], 'data': [ 'data/country_data.xml', @@ -18,7 +19,7 @@ 'views/res_partner.xml', 'views/res_country.xml', 'views/account_tax.xml', - 'views/account_config_settings.xml', + 'views/res_config_settings.xml', 'views/intrastat.xml', ], 'demo': [ diff --git a/intrastat_base/models/__init__.py b/intrastat_base/models/__init__.py index fa36185..b659505 100644 --- a/intrastat_base/models/__init__.py +++ b/intrastat_base/models/__init__.py @@ -4,5 +4,5 @@ from . import res_country from . import product_template from . import account_tax from . import res_company -from . import account_config_settings +from . import res_config_settings from . import intrastat_common diff --git a/intrastat_base/models/intrastat_common.py b/intrastat_base/models/intrastat_common.py index de3b04b..9508d80 100644 --- a/intrastat_base/models/intrastat_common.py +++ b/intrastat_base/models/intrastat_common.py @@ -57,14 +57,14 @@ class IntrastatCommon(models.AbstractModel): def _check_xml_schema(self, xml_string, xsd_file): '''Validate the XML file against the XSD''' from lxml import etree - from StringIO import StringIO + from io import StringIO xsd_etree_obj = etree.parse( tools.file_open(xsd_file)) official_schema = etree.XMLSchema(xsd_etree_obj) try: t = etree.parse(StringIO(xml_string)) official_schema.assertValid(t) - except Exception, e: + except Exception as e: # if the validation of the XSD fails, we arrive here logger = logging.getLogger(__name__) logger.warning( @@ -115,7 +115,7 @@ class IntrastatCommon(models.AbstractModel): 'nodestroy': True, 'target': 'current', 'res_id': attach_id, - } + } return action @api.multi diff --git a/intrastat_base/models/account_config_settings.py b/intrastat_base/models/res_config_settings.py similarity index 65% rename from intrastat_base/models/account_config_settings.py rename to intrastat_base/models/res_config_settings.py index 78a9fca..3457b8a 100644 --- a/intrastat_base/models/account_config_settings.py +++ b/intrastat_base/models/res_config_settings.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- # © 2017 Akretion (Alexis de Lattre ) +# © 2018 brain-tec AG (Kumar Aberer ) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import models, fields -class AccountConfigSettings(models.TransientModel): - _inherit = 'account.config.settings' +class ResConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' intrastat_remind_user_ids = fields.Many2many( related='company_id.intrastat_remind_user_ids') diff --git a/intrastat_base/views/account_config_settings.xml b/intrastat_base/views/account_config_settings.xml deleted file mode 100644 index c890c40..0000000 --- a/intrastat_base/views/account_config_settings.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - intrastat.account.config.settings.form - account.config.settings - - - - - - - - - - - - diff --git a/intrastat_base/views/res_config_settings.xml b/intrastat_base/views/res_config_settings.xml new file mode 100644 index 0000000..cb9fd76 --- /dev/null +++ b/intrastat_base/views/res_config_settings.xml @@ -0,0 +1,30 @@ + + + + + + + intrastat.res.config.settings.form + res.config.settings + + + +

Intrastat

+
+
+
+
+
+
+
+
+
+ + +
From deb2f0f6626be584c07ccd465c7347a43a0e5271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Valyi?= Date: Fri, 27 Jul 2018 22:45:04 -0300 Subject: [PATCH 18/44] [IMP] *: removed utf-8 headers, changed icon and site * company model test, country model test as in v8 * png logo instead of svg, removed Python 2 utf-8 headers --- intrastat_base/README.rst | 4 ++-- intrastat_base/__init__.py | 1 - intrastat_base/__manifest__.py | 5 ++--- intrastat_base/models/__init__.py | 2 -- intrastat_base/models/account_tax.py | 1 - intrastat_base/models/intrastat_common.py | 1 - intrastat_base/models/product_template.py | 1 - intrastat_base/models/res_company.py | 1 - intrastat_base/models/res_config_settings.py | 1 - intrastat_base/models/res_country.py | 1 - intrastat_base/tests/__init__.py | 1 + intrastat_base/tests/test_all.py | 22 +++++++++++++++++++ product_harmonized_system/README.rst | 2 +- product_harmonized_system/__init__.py | 2 -- product_harmonized_system/__manifest__.py | 1 - product_harmonized_system/models/__init__.py | 2 -- product_harmonized_system/models/hs_code.py | 1 - .../models/product_category.py | 1 - .../models/product_template.py | 1 - 19 files changed, 28 insertions(+), 23 deletions(-) create mode 100644 intrastat_base/tests/__init__.py create mode 100644 intrastat_base/tests/test_all.py diff --git a/intrastat_base/README.rst b/intrastat_base/README.rst index 09a4328..2dece29 100644 --- a/intrastat_base/README.rst +++ b/intrastat_base/README.rst @@ -1,4 +1,4 @@ -.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg +.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 @@ -43,7 +43,7 @@ It adds a tab *Intrastat* on the company form view. .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/227/10.0 + :target: https://runbot.odoo-community.org/runbot/227/11.0 Bug Tracker =========== diff --git a/intrastat_base/__init__.py b/intrastat_base/__init__.py index a0fdc10..0650744 100644 --- a/intrastat_base/__init__.py +++ b/intrastat_base/__init__.py @@ -1,2 +1 @@ -# -*- coding: utf-8 -*- from . import models diff --git a/intrastat_base/__manifest__.py b/intrastat_base/__manifest__.py index ba5a0f1..d584ab2 100644 --- a/intrastat_base/__manifest__.py +++ b/intrastat_base/__manifest__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2011-2016 Akretion (http://www.akretion.com) # © 2018 brain-tec AG (Kumar Aberer ) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). @@ -9,8 +8,8 @@ 'category': 'Intrastat', 'license': 'AGPL-3', 'summary': 'Base module for Intrastat reporting', - 'author': 'Akretion,Odoo Community Association (OCA), brain-tec AG', - 'website': 'http://www.akretion.com', + 'author': 'Akretion,Odoo Community Association (OCA)', + 'website': 'https://github.com/OCA/intrastat', 'depends': ['base_vat', 'account'], 'conflicts': ['report_intrastat'], 'data': [ diff --git a/intrastat_base/models/__init__.py b/intrastat_base/models/__init__.py index b659505..68e2955 100644 --- a/intrastat_base/models/__init__.py +++ b/intrastat_base/models/__init__.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - from . import res_country from . import product_template from . import account_tax diff --git a/intrastat_base/models/account_tax.py b/intrastat_base/models/account_tax.py index f9997fc..2235255 100644 --- a/intrastat_base/models/account_tax.py +++ b/intrastat_base/models/account_tax.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2011-2016 Akretion (http://www.akretion.com). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). diff --git a/intrastat_base/models/intrastat_common.py b/intrastat_base/models/intrastat_common.py index 9508d80..ba508de 100644 --- a/intrastat_base/models/intrastat_common.py +++ b/intrastat_base/models/intrastat_common.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2010-2016 Akretion (Alexis de Lattre ) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). diff --git a/intrastat_base/models/product_template.py b/intrastat_base/models/product_template.py index 71cb987..a0725f8 100644 --- a/intrastat_base/models/product_template.py +++ b/intrastat_base/models/product_template.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2010-2016 Akretion (Alexis de Lattre ) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). diff --git a/intrastat_base/models/res_company.py b/intrastat_base/models/res_company.py index 5d4a4e7..4b110f0 100644 --- a/intrastat_base/models/res_company.py +++ b/intrastat_base/models/res_company.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2013-2017 Akretion (Alexis de Lattre ) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). diff --git a/intrastat_base/models/res_config_settings.py b/intrastat_base/models/res_config_settings.py index 3457b8a..4191666 100644 --- a/intrastat_base/models/res_config_settings.py +++ b/intrastat_base/models/res_config_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2017 Akretion (Alexis de Lattre ) # © 2018 brain-tec AG (Kumar Aberer ) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/intrastat_base/models/res_country.py b/intrastat_base/models/res_country.py index 19f34f2..9b4868c 100644 --- a/intrastat_base/models/res_country.py +++ b/intrastat_base/models/res_country.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2011-2014 Akretion (Alexis de Lattre ) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). diff --git a/intrastat_base/tests/__init__.py b/intrastat_base/tests/__init__.py new file mode 100644 index 0000000..7836283 --- /dev/null +++ b/intrastat_base/tests/__init__.py @@ -0,0 +1 @@ +from . import test_all diff --git a/intrastat_base/tests/test_all.py b/intrastat_base/tests/test_all.py new file mode 100644 index 0000000..fbc91ac --- /dev/null +++ b/intrastat_base/tests/test_all.py @@ -0,0 +1,22 @@ +from odoo.tests.common import TransactionCase + + +class TestIntrastatBase(TransactionCase): + """Tests for this module""" + + def test_10_countries(self): + # check if only EU countries have the 'intrastat' bit set + france = self.env.ref('base.fr') + self.assertTrue(france.intrastat) + brazil = self.env.ref('base.br') + self.assertFalse(brazil.intrastat) + + def test_20_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])] + }) + # then check if intrastat_email_list contains the email of the user + self.assertEquals(demo_company.intrastat_email_list, demo_user.email) diff --git a/product_harmonized_system/README.rst b/product_harmonized_system/README.rst index 521168d..a89dae6 100644 --- a/product_harmonized_system/README.rst +++ b/product_harmonized_system/README.rst @@ -1,4 +1,4 @@ -.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 diff --git a/product_harmonized_system/__init__.py b/product_harmonized_system/__init__.py index cde864b..0650744 100644 --- a/product_harmonized_system/__init__.py +++ b/product_harmonized_system/__init__.py @@ -1,3 +1 @@ -# -*- coding: utf-8 -*- - from . import models diff --git a/product_harmonized_system/__manifest__.py b/product_harmonized_system/__manifest__.py index 8239ab6..67fe66b 100644 --- a/product_harmonized_system/__manifest__.py +++ b/product_harmonized_system/__manifest__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2018 brain-tec AG (http://www.braintec-group.com) # © 2011-2016 Akretion (http://www.akretion.com) # © 2009-2016 Noviat (http://www.noviat.com) diff --git a/product_harmonized_system/models/__init__.py b/product_harmonized_system/models/__init__.py index 2d9638e..cd4fd51 100644 --- a/product_harmonized_system/models/__init__.py +++ b/product_harmonized_system/models/__init__.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - from . import hs_code from . import product_category from . import product_template diff --git a/product_harmonized_system/models/hs_code.py b/product_harmonized_system/models/hs_code.py index b24f964..1866862 100644 --- a/product_harmonized_system/models/hs_code.py +++ b/product_harmonized_system/models/hs_code.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2011-2016 Akretion (http://www.akretion.com) # © 2009-2016 Noviat (http://www.noviat.com) # @author Alexis de Lattre diff --git a/product_harmonized_system/models/product_category.py b/product_harmonized_system/models/product_category.py index 6f6233e..6af907a 100644 --- a/product_harmonized_system/models/product_category.py +++ b/product_harmonized_system/models/product_category.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2011-2016 Akretion (http://www.akretion.com) # © 2009-2016 Noviat (http://www.noviat.com) # @author Alexis de Lattre diff --git a/product_harmonized_system/models/product_template.py b/product_harmonized_system/models/product_template.py index 8893f39..0603079 100644 --- a/product_harmonized_system/models/product_template.py +++ b/product_harmonized_system/models/product_template.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2011-2016 Akretion (http://www.akretion.com) # © 2009-2016 Noviat (http://www.noviat.com) # @author Alexis de Lattre From 518745f6e6bf6a2c397f31ae63e879c1d3d2acfb Mon Sep 17 00:00:00 2001 From: oca-travis Date: Wed, 8 Aug 2018 15:27:31 +0000 Subject: [PATCH 19/44] [UPD] Update intrastat_base.pot --- intrastat_base/i18n/intrastat_base.pot | 148 ++++++++++++++++--------- 1 file changed, 95 insertions(+), 53 deletions(-) diff --git a/intrastat_base/i18n/intrastat_base.pot b/intrastat_base/i18n/intrastat_base.pot index fdc6996..e9e9889 100644 --- a/intrastat_base/i18n/intrastat_base.pot +++ b/intrastat_base/i18n/intrastat_base.pot @@ -4,10 +4,8 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" +"Project-Id-Version: Odoo Server 11.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-05-27 18:43+0000\n" -"PO-Revision-Date: 2015-05-27 18:43+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -16,23 +14,19 @@ msgstr "" "Plural-Forms: \n" #. module: intrastat_base -#: help:product.template,is_accessory_cost:0 +#: 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 msgid "Activate this option for shipping costs, packaging costs and all services related to the sale of products. This option is used for Intrastat reports." msgstr "" #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:165 +#: code:addons/intrastat_base/models/intrastat_common.py:154 #, python-format msgid "Cannot delete the declaration %s because it is in Done state" msgstr "" #. module: intrastat_base -#: view:res.company:intrastat_base.view_company_form -msgid "Common Intrastat Settings" -msgstr "" - -#. module: intrastat_base -#: model:ir.model,name:intrastat_base.model_report_intrastat_common +#: model:ir.model,name:intrastat_base.model_intrastat_common msgid "Common functions for intrastat reports for products " msgstr "" @@ -42,7 +36,7 @@ msgid "Companies" msgstr "" #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:68 +#: code:addons/intrastat_base/models/intrastat_common.py:33 #, python-format msgid "Company not yet set on intrastat report." msgstr "" @@ -53,83 +47,126 @@ msgid "Country" msgstr "" #. module: intrastat_base -#: view:res.country:intrastat_base.view_country_search -#: field:res.country,intrastat:0 +#: 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_intrastat_common_display_name +#: model:ir.model.fields,field_description:intrastat_base.field_intrastat_result_view_display_name +msgid "Display Name" +msgstr "" + +#. module: intrastat_base +#: model:ir.model.fields,field_description:intrastat_base.field_res_country_intrastat +#: model:ir.ui.view,arch_db:intrastat_base.res_country_view_search msgid "EU Country" msgstr "" #. module: intrastat_base -#: field:product.template,exclude_from_intrastat:0 -msgid "Exclude from Intrastat reports" -msgstr "" - -#. module: intrastat_base -#: field:account.tax,exclude_from_intrastat_if_present:0 +#: model:ir.model.fields,field_description:intrastat_base.field_account_tax_exclude_from_intrastat_if_present msgid "Exclude invoice line from intrastat if this tax is present" msgstr "" #. module: intrastat_base -#: field:report.intrastat.common,id:0 +#: 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 msgid "ID" msgstr "" #. module: intrastat_base -#: help:product.template,exclude_from_intrastat:0 -msgid "If set to True, the product or service will not be taken into account for Intrastat Product or Service reports. So you should leave this field to False unless you have a very good reason." -msgstr "" - -#. module: intrastat_base -#: help:account.tax,exclude_from_intrastat_if_present:0 +#: model:ir.model.fields,help:intrastat_base.field_account_tax_exclude_from_intrastat_if_present msgid "If this tax is present on an invoice line, this invoice line will be skipped when generating Intrastat Product or Service lines from invoices." msgstr "" #. module: intrastat_base -#: view:product.template:intrastat_base.product_template_form_view +#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root +#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_config_root +#: model:ir.ui.view,arch_db:intrastat_base.view_intrastat_res_config_settings +msgid "Intrastat" +msgstr "" + +#. module: intrastat_base +#: model:ir.ui.view,arch_db:intrastat_base.product_template_form_view msgid "Intrastat Properties" msgstr "" #. module: intrastat_base -#: model:ir.ui.menu,name:intrastat_base.menu_intrastat_base_root -msgid "Intrastat Reporting" +#: model:ir.ui.view,arch_db:intrastat_base.intrastat_result_view_form +msgid "Intrastat Result View" msgstr "" #. module: intrastat_base -#: view:res.company:intrastat_base.view_company_form -msgid "Intrastat Settings" -msgstr "" - -#. module: intrastat_base -#: field:product.template,is_accessory_cost:0 +#: 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 msgid "Is accessory cost" msgstr "" #. module: intrastat_base -#: help:res.company,intrastat_remind_user_ids:0 -msgid "List of OpenERP users who will receive a notification to remind them about the Intrastat declaration." +#: 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 +msgid "Last Modified on" msgstr "" #. module: intrastat_base -#: code:addons/intrastat_base/company.py:55 +#: 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 +msgid "List of Odoo users who will receive a notification to remind them about the Intrastat declaration." +msgstr "" + +#. module: intrastat_base +#: model:ir.model.fields,field_description:intrastat_base.field_res_company_intrastat_email_list +msgid "List of emails of Users Receiving the Intrastat Reminder" +msgstr "" + +#. module: intrastat_base +#: code:addons/intrastat_base/models/res_company.py:38 #, python-format 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:ir.ui.view,arch_db:intrastat_base.intrastat_result_view_form +msgid "Ok" +msgstr "" + #. module: intrastat_base #: model:ir.model,name:intrastat_base.model_product_template msgid "Product Template" msgstr "" #. module: intrastat_base -#: view:res.country:intrastat_base.view_country_search +#: model:ir.ui.view,arch_db:intrastat_base.res_country_view_search msgid "Search Countries" msgstr "" #. module: intrastat_base -#: help:res.country,intrastat:0 +#: model:ir.model.fields,help:intrastat_base.field_res_country_intrastat msgid "Set to True for all European Union countries." msgstr "" #. module: intrastat_base +#: model:product.product,name:intrastat_base.shipping_costs_exclude #: model:product.template,name:intrastat_base.shipping_costs_exclude_product_template msgid "Shipping costs" msgstr "" @@ -140,43 +177,48 @@ msgid "Tax" msgstr "" #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:84 +#: code:addons/intrastat_base/models/intrastat_common.py:51 #, python-format msgid "The VAT number is not set for the partner '%s'." msgstr "" #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:76 +#: code:addons/intrastat_base/models/intrastat_common.py:41 #, python-format msgid "The company currency must be 'EUR', but is currently '%s'." msgstr "" #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:72 +#: code:addons/intrastat_base/models/intrastat_common.py:37 #, python-format msgid "The country is not set on the company '%s'." msgstr "" #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:105 +#: code:addons/intrastat_base/models/intrastat_common.py:74 #, python-format msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s." msgstr "" #. module: intrastat_base -#: code:addons/intrastat_base/product.py:51 +#: code:addons/intrastat_base/models/product_template.py:23 #, python-format msgid "The option 'Is accessory cost?' should only be activated on 'Service' products. You have activated this option for the product '%s' which is of type '%s'" msgstr "" #. module: intrastat_base -#: code:addons/intrastat_base/intrastat_common.py:62 -#, python-format -msgid "The start date must be the first day of the month" -msgstr "" - -#. module: intrastat_base -#: field:res.company,intrastat_remind_user_ids:0 +#: model:ir.model.fields,field_description:intrastat_base.field_res_company_intrastat_remind_user_ids +#: model:ir.model.fields,field_description:intrastat_base.field_res_config_settings_intrastat_remind_user_ids msgid "Users Receiving the Intrastat Reminder" msgstr "" +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_intrastat_result_view +msgid "intrastat.result.view" +msgstr "" + +#. module: intrastat_base +#: model:ir.model,name:intrastat_base.model_res_config_settings +msgid "res.config.settings" +msgstr "" + From c99dfdbe2eadf3879c4849cab0bcab7c8ff4e644 Mon Sep 17 00:00:00 2001 From: OCA Git Bot Date: Thu, 9 Aug 2018 04:53:07 +0200 Subject: [PATCH 20/44] [ADD] setup.py --- setup/_metapackage/VERSION.txt | 2 +- setup/_metapackage/setup.py | 5 +++-- setup/intrastat_base/odoo/addons/intrastat_base | 1 + setup/intrastat_base/setup.cfg | 2 ++ setup/intrastat_base/setup.py | 6 ++++++ 5 files changed, 13 insertions(+), 3 deletions(-) create mode 120000 setup/intrastat_base/odoo/addons/intrastat_base create mode 100644 setup/intrastat_base/setup.cfg create mode 100644 setup/intrastat_base/setup.py diff --git a/setup/_metapackage/VERSION.txt b/setup/_metapackage/VERSION.txt index 5e5ecaa..f0e9184 100644 --- a/setup/_metapackage/VERSION.txt +++ b/setup/_metapackage/VERSION.txt @@ -1 +1 @@ -11.0.20190514.0 \ No newline at end of file +11.0.20180821.0 \ No newline at end of file diff --git a/setup/_metapackage/setup.py b/setup/_metapackage/setup.py index ac16924..a3ed0e0 100644 --- a/setup/_metapackage/setup.py +++ b/setup/_metapackage/setup.py @@ -4,10 +4,11 @@ with open('VERSION.txt', 'r') as f: version = f.read().strip() setuptools.setup( - name="odoo11-addons-oca-intrastat-extrastat", - description="Meta package for oca-intrastat-extrastat Odoo addons", + name="odoo11-addons-oca-intrastat", + description="Meta package for oca-intrastat Odoo addons", version=version, install_requires=[ + 'odoo11-addon-intrastat_base', 'odoo11-addon-product_harmonized_system', ], classifiers=[ diff --git a/setup/intrastat_base/odoo/addons/intrastat_base b/setup/intrastat_base/odoo/addons/intrastat_base new file mode 120000 index 0000000..74df3f8 --- /dev/null +++ b/setup/intrastat_base/odoo/addons/intrastat_base @@ -0,0 +1 @@ +../../../../intrastat_base \ No newline at end of file diff --git a/setup/intrastat_base/setup.cfg b/setup/intrastat_base/setup.cfg new file mode 100644 index 0000000..3c6e79c --- /dev/null +++ b/setup/intrastat_base/setup.cfg @@ -0,0 +1,2 @@ +[bdist_wheel] +universal=1 diff --git a/setup/intrastat_base/setup.py b/setup/intrastat_base/setup.py new file mode 100644 index 0000000..28c57bb --- /dev/null +++ b/setup/intrastat_base/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From 7d57f7285a87c25083f7c5ce828c4087949b84d3 Mon Sep 17 00:00:00 2001 From: Luc De Meyer Date: Tue, 26 Jun 2018 17:28:55 +0200 Subject: [PATCH 21/44] [FIX] product_harmonized_system: fix get_hs_code_recurively --- product_harmonized_system/__manifest__.py | 6 +++--- product_harmonized_system/models/hs_code.py | 6 +++--- .../models/product_category.py | 2 +- .../models/product_template.py | 20 ++++++++++++------- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/product_harmonized_system/__manifest__.py b/product_harmonized_system/__manifest__.py index 67fe66b..052d3b9 100644 --- a/product_harmonized_system/__manifest__.py +++ b/product_harmonized_system/__manifest__.py @@ -1,6 +1,6 @@ -# © 2018 brain-tec AG (http://www.braintec-group.com) -# © 2011-2016 Akretion (http://www.akretion.com) -# © 2009-2016 Noviat (http://www.noviat.com) +# Copyright 2018 brain-tec AG (http://www.braintec-group.com) +# Copyright 2011-2016 Akretion (http://www.akretion.com) +# Copyright 2009-2016 Noviat (http://www.noviat.com) # @author Kumar Aberer # @author Alexis de Lattre # @author Luc de Meyer diff --git a/product_harmonized_system/models/hs_code.py b/product_harmonized_system/models/hs_code.py index 1866862..1b0d158 100644 --- a/product_harmonized_system/models/hs_code.py +++ b/product_harmonized_system/models/hs_code.py @@ -19,13 +19,13 @@ class HSCode(models.Model): "available from the World Customs Organisation, see " "http://www.wcoomd.org") description = fields.Char( - 'Description', translate=True, + translate=True, help="Short text description of the H.S. category") display_name = fields.Char( - compute='_compute_display_name_field', string="Display Name", + compute='_compute_display_name_field', store=True, readonly=True) local_code = fields.Char( - string='Local Code', required=True, + required=True, help="Code used for the national Import/Export declaration. " "The national code starts with the 6 digits of the H.S. and often " "has a few additional digits to extend the H.S. code.") diff --git a/product_harmonized_system/models/product_category.py b/product_harmonized_system/models/product_category.py index 6af907a..884f2aa 100644 --- a/product_harmonized_system/models/product_category.py +++ b/product_harmonized_system/models/product_category.py @@ -25,5 +25,5 @@ class ProductCategory(models.Model): elif self.parent_id: res = self.parent_id.get_hs_code_recursively() else: - res = None + res = self.env['hs.code'] return res diff --git a/product_harmonized_system/models/product_template.py b/product_harmonized_system/models/product_template.py index 0603079..b890656 100644 --- a/product_harmonized_system/models/product_template.py +++ b/product_harmonized_system/models/product_template.py @@ -22,13 +22,19 @@ class ProductTemplate(models.Model): help="Country of origin of the product i.e. product " "'made in ____'.") + +class ProductProduct(models.Model): + _inherit = 'product.product' + @api.multi def get_hs_code_recursively(self): - self.ensure_one() - if self.hs_code_id: - res = self.hs_code_id - elif self.categ_id: - res = self.categ_id.get_hs_code_recursively() + res = self.env['hs.code'] + if not self: + return res else: - res = None - return res + self.ensure_one() + if self.hs_code_id: + res = self.hs_code_id + elif self.categ_id: + res = self.categ_id.get_hs_code_recursively() + return res From 1453da351d765e4ca2e430b7ae541afae3a05158 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Mon, 20 Aug 2018 20:00:06 +0000 Subject: [PATCH 22/44] [UPD] Update product_harmonized_system.pot --- product_harmonized_system/i18n/product_harmonized_system.pot | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/product_harmonized_system/i18n/product_harmonized_system.pot b/product_harmonized_system/i18n/product_harmonized_system.pot index d4202ea..388dc7a 100644 --- a/product_harmonized_system/i18n/product_harmonized_system.pot +++ b/product_harmonized_system/i18n/product_harmonized_system.pot @@ -132,6 +132,11 @@ msgstr "" msgid "Printed circuits" msgstr "" +#. module: product_harmonized_system +#: model:ir.model,name:product_harmonized_system.model_product_product +msgid "Product" +msgstr "" + #. module: product_harmonized_system #: model:ir.model.fields,field_description:product_harmonized_system.field_hs_code_product_categ_ids #: model:ir.ui.view,arch_db:product_harmonized_system.hs_code_view_form From 91b062e5ccb45507c61eb56a20fbc71597ecd3fb Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Fri, 28 Nov 2014 23:51:23 +0100 Subject: [PATCH 23/44] [ADD] intrastat_product Rename report.intrastat.product to l10n.fr.report.intrastat.product (same for service and for lines) + migration scripts Rename field country_id to origin_country_id (TODO : write mig script) and move this field from l10n_fr_intrastat_product to intrastat_product Move intrastat_code and uom_id of report.intrastat.code from l10n_fr_intrastat_product to intrastat_product, as discussed with Luc de Meyer Use display_name instead of an inherit of name_get (better use of new API) Inherit write and create of intrastat codes to remove spaces (patch by Luc De Meyer from Noviat) Add O2M fields from intrastat code to products and product categs --- intrastat_product/__init__.py | 23 +++ intrastat_product/__openerp__.py | 45 ++++++ intrastat_product/i18n/intrastat_product.pot | 122 ++++++++++++++++ intrastat_product/intrastat.py | 131 ++++++++++++++++++ intrastat_product/intrastat_demo.xml | 88 ++++++++++++ intrastat_product/intrastat_view.xml | 101 ++++++++++++++ .../security/ir.model.access.csv | 3 + 7 files changed, 513 insertions(+) create mode 100644 intrastat_product/__init__.py create mode 100644 intrastat_product/__openerp__.py create mode 100644 intrastat_product/i18n/intrastat_product.pot create mode 100644 intrastat_product/intrastat.py create mode 100644 intrastat_product/intrastat_demo.xml create mode 100644 intrastat_product/intrastat_view.xml create mode 100644 intrastat_product/security/ir.model.access.csv diff --git a/intrastat_product/__init__.py b/intrastat_product/__init__.py new file mode 100644 index 0000000..64a3431 --- /dev/null +++ b/intrastat_product/__init__.py @@ -0,0 +1,23 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Intrastat product module for OpenERP +# Copyright (C) 2011-2014 Akretion (http://www.akretion.com) +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from . import intrastat diff --git a/intrastat_product/__openerp__.py b/intrastat_product/__openerp__.py new file mode 100644 index 0000000..6224d37 --- /dev/null +++ b/intrastat_product/__openerp__.py @@ -0,0 +1,45 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Intrastat Product module for Odoo +# Copyright (C) 2011-2015 Akretion (http://www.akretion.com) +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +{ + 'name': 'Intrastat Product', + 'version': '1.1', + 'category': 'Localisation/Report Intrastat', + 'license': 'AGPL-3', + 'summary': 'Base module for Intrastat Product', + 'description': """ +This module contains the common objects for the Intrastat Product. +This module is country-independant. + +This module has been written by Alexis de Lattre from Akretion + + """, + 'author': 'Akretion', + 'website': 'http://www.akretion.com', + 'depends': ['intrastat_base'], + 'data': [ + 'intrastat_view.xml', + 'security/ir.model.access.csv', + ], + 'demo': ['intrastat_demo.xml'], + 'installable': True, +} diff --git a/intrastat_product/i18n/intrastat_product.pot b/intrastat_product/i18n/intrastat_product.pot new file mode 100644 index 0000000..15505ac --- /dev/null +++ b/intrastat_product/i18n/intrastat_product.pot @@ -0,0 +1,122 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * intrastat_product +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-11-28 22:48+0000\n" +"PO-Revision-Date: 2014-11-28 22:48+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: intrastat_product +#: help:product.category,intrastat_id:0 +msgid "Code from the Harmonised System. If this code is not set on the product itself, it will be read here, on the related product category." +msgstr "" + +#. module: intrastat_product +#: help:product.template,intrastat_id:0 +msgid "Code from the Harmonised System. Nomenclature is available from the World Customs Organisation, see http://www.wcoomd.org/. Some countries have made their own extensions to this nomenclature." +msgstr "" + +#. module: intrastat_product +#: field:report.intrastat.code,create_uid:0 +msgid "Created by" +msgstr "" + +#. module: intrastat_product +#: field:report.intrastat.code,create_date:0 +msgid "Created on" +msgstr "" + +#. module: intrastat_product +#: field:report.intrastat.code,description:0 +msgid "Description" +msgstr "" + +#. module: intrastat_product +#: help:report.intrastat.code,name:0 +msgid "Full length Harmonized System code (digits only). Full list is available from the World Customs Organisation, see http://www.wcoomd.org" +msgstr "" + +#. module: intrastat_product +#: model:ir.model,name:intrastat_product.model_report_intrastat_code +msgid "H.S. Code" +msgstr "" + +#. module: intrastat_product +#: field:report.intrastat.code,name:0 +msgid "H.S. code" +msgstr "" + +#. module: intrastat_product +#: code:addons/intrastat_product/intrastat.py:56 +#, python-format +msgid "H.S. codes should only contain digits. It is not the case of H.S. code '%s'." +msgstr "" + +#. module: intrastat_product +#: field:report.intrastat.code,id:0 +msgid "ID" +msgstr "" + +#. module: intrastat_product +#: model:ir.actions.act_window,name:intrastat_product.product_intrastat_code_act +#: model:ir.ui.menu,name:intrastat_product.product_intrastat_code_menu +#: field:product.category,intrastat_id:0 +#: field:product.template,intrastat_id:0 +#: view:report.intrastat.code:intrastat_product.product_intrastat_code_form +msgid "Intrastat Code" +msgstr "" + +#. module: intrastat_product +#: view:report.intrastat.code:intrastat_product.product_intrastat_code_tree +msgid "Intrastat Codes" +msgstr "" + +#. module: intrastat_product +#: view:product.category:intrastat_product.product_category_form_view +msgid "Intrastat Properties" +msgstr "" + +#. module: intrastat_product +#: field:report.intrastat.code,write_uid:0 +msgid "Last Updated by" +msgstr "" + +#. module: intrastat_product +#: field:report.intrastat.code,write_date:0 +msgid "Last Updated on" +msgstr "" + +#. module: intrastat_product +#: model:ir.model,name:intrastat_product.model_product_category +msgid "Product Category" +msgstr "" + +#. module: intrastat_product +#: model:ir.model,name:intrastat_product.model_product_template +msgid "Product Template" +msgstr "" + +#. module: intrastat_product +#: view:report.intrastat.code:intrastat_product.product_intrastat_code_search +msgid "Search Intrastat Codes" +msgstr "" + +#. module: intrastat_product +#: help:report.intrastat.code,description:0 +msgid "Short text description of the H.S. category" +msgstr "" + +#. module: intrastat_product +#: sql_constraint:report.intrastat.code:0 +msgid "This H.S. code already exists in Odoo !" +msgstr "" + diff --git a/intrastat_product/intrastat.py b/intrastat_product/intrastat.py new file mode 100644 index 0000000..efbfe37 --- /dev/null +++ b/intrastat_product/intrastat.py @@ -0,0 +1,131 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Intrastat Product module for OpenERP +# Copyright (C) 2004-2009 Tiny SPRL (http://tiny.be) +# Copyright (C) 2010-2014 Akretion (http://www.akretion.com) +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields, api, _ +from openerp.exceptions import ValidationError + + +class ReportIntrastatCode(models.Model): + _name = "report.intrastat.code" + _description = "H.S. Code" + _order = "name" + _rec_name = "display_name" + + @api.one + @api.depends('name', 'description') + def _compute_display_name(self): + display_name = self.name or '' + if self.description: + display_name += ' ' + self.description + self.display_name = display_name + + name = fields.Char( + string='H.S. code', + help="Full length Harmonized System code (digits only). Full list is " + "available from the World Customs Organisation, see " + "http://www.wcoomd.org") + description = fields.Char( + 'Description', help="Short text description of the H.S. category") + display_name = fields.Char( + compute='_compute_display_name', string="Display Name", readonly=True) + intrastat_code = fields.Char( + string='European Intrastat Code', size=9, required=True, + help="Code used for the Intrastat declaration. Must be part " + "of the 'Combined Nomenclature' (CN), cf " + "http://en.wikipedia.org/wiki/Combined_Nomenclature" + "Must have 8 digits with sometimes a 9th digit.") + intrastat_uom_id = fields.Many2one( + 'product.uom', string='UoM for Intrastat Report', + help="Select the unit of measure if one is required for " + "this particular Intrastat Code (other than the weight in Kg). " + "If no particular unit of measure is required, leave empty.") + active = fields.Boolean(default=True) + product_categ_ids = fields.One2many( + 'product.category', 'intrastat_id', string='Product Categories') + product_tmpl_ids = fields.One2many( + 'product.template', 'intrastat_id', string='Products') + + @api.constrains('name', 'intrastat_code') + def _hs_code(self): + if self.name and not self.name.isdigit(): + raise ValidationError( + _("H.S. codes should only contain digits. It is not the case " + "of H.S. code '%s'.") % self.name) + if self.intrastat_code and not self.intrastat_code.isdigit(): + raise ValidationError( + _("The field Intrastat Code should only contain digits. " + "It is not the case of Intrastat Code '%s'.") + % self.intrastat_code) + if self.intrastat_code and len(self.intrastat_code) not in (8, 9): + raise ValidationError( + _("The field Intrastat Code should " + "contain 8 or 9 digits. It is not the case of " + "Intrastat Code '%s'.") + % self.intrastat_code) + + _sql_constraints = [( + 'hs_code_uniq', + 'unique(name)', + 'This H.S. code already exists in Odoo !' + )] + + @api.model + @api.returns('self', lambda value: value.id) + def create(self, vals): + if vals.get('intrastat_code'): + vals['intrastat_code'] = vals['intrastat_code'].replace(' ', '') + return super(ReportIntrastatCode, self).create(vals) + + @api.multi + def write(self, vals): + if vals.get('intrastat_code'): + vals['intrastat_code'] = vals['intrastat_code'].replace(' ', '') + return super(ReportIntrastatCode, self).write(vals) + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + intrastat_id = fields.Many2one( + 'report.intrastat.code', string='Intrastat Code', + help="Code from the Harmonised System. Nomenclature is " + "available from the World Customs Organisation, see " + "http://www.wcoomd.org/. Some countries have made their own " + "extensions to this nomenclature.") + origin_country_id = fields.Many2one( + 'res.country', string='Country of Origin', + help="Country of origin of the product i.e. product " + "'made in ____'. If you have different countries of origin " + "depending on the supplier from which you purchased the product, " + "leave this field empty and use the equivalent field on the " + "'product supplier info' form.") + + +class ProductCategory(models.Model): + _inherit = "product.category" + + intrastat_id = fields.Many2one( + 'report.intrastat.code', string='Intrastat Code', + help="Code from the Harmonised System. If this code is not " + "set on the product itself, it will be read here, on the " + "related product category.") diff --git a/intrastat_product/intrastat_demo.xml b/intrastat_product/intrastat_demo.xml new file mode 100644 index 0000000..b5ae41b --- /dev/null +++ b/intrastat_product/intrastat_demo.xml @@ -0,0 +1,88 @@ + + + + + + + + + 84715000 + 84715000 + + Automatic data-processing machines (computers) + + + + 84717050 + 84717050 + + Storage units + + + + 85340090 + 85340090 + Printed circuits + + + + + + 5 + + + + + + 6 + + + + + + 6.5 + + + + + + 0.5 + + + + + + 0.5 + + + + + + 0.5 + + + + + + 0.7 + + + + + + 0.8 + + + + + + 2 + + + + + diff --git a/intrastat_product/intrastat_view.xml b/intrastat_product/intrastat_view.xml new file mode 100644 index 0000000..b62c280 --- /dev/null +++ b/intrastat_product/intrastat_view.xml @@ -0,0 +1,101 @@ + + + + + + + + + + intrastat.product.template.form + product.template + + + + + + + + + + + + intrastat.product.category.form + product.category + + + + + + + + + + + + + intrastat.product.intrastat.code.search + report.intrastat.code + + + + + + + + + + intrastat.product.intrastat.code.tree + report.intrastat.code + + + + + + + + + + + + + fr.intrastat.product.intrastat.code.form + report.intrastat.code + +
+ + + + + + + + + + + + + +
+
+
+ + + + Intrastat Code + report.intrastat.code + tree,form + + + + + +
+
diff --git a/intrastat_product/security/ir.model.access.csv b/intrastat_product/security/ir.model.access.csv new file mode 100644 index 0000000..1708adf --- /dev/null +++ b/intrastat_product/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_report_intrastat_code_sale_manager,Full access on report.intrastat.code to sale manager,model_report_intrastat_code,base.group_sale_manager,1,1,1,1 +access_report_intrastat_code_employee,Read access on report.intrastat.code to employee,model_report_intrastat_code,base.group_user,1,0,0,0 From aa9074d62fca07a19fae8d18362e9bf69e3e45ae Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Fri, 15 May 2015 11:46:46 +0200 Subject: [PATCH 24/44] display_name must be stored as it is used as _rec_name, otherwise we cant, for instance, import files with name_search --- intrastat_product/intrastat.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/intrastat_product/intrastat.py b/intrastat_product/intrastat.py index efbfe37..5242514 100644 --- a/intrastat_product/intrastat.py +++ b/intrastat_product/intrastat.py @@ -47,7 +47,8 @@ class ReportIntrastatCode(models.Model): description = fields.Char( 'Description', help="Short text description of the H.S. category") display_name = fields.Char( - compute='_compute_display_name', string="Display Name", readonly=True) + compute='_compute_display_name', string="Display Name", readonly=True, + store=True) intrastat_code = fields.Char( string='European Intrastat Code', size=9, required=True, help="Code used for the Intrastat declaration. Must be part " From 7fdc83230af3e0a2194e41e78d7aeaaa2f354eda Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Wed, 27 May 2015 21:32:43 +0200 Subject: [PATCH 25/44] [IMP] intrastat_product: Several things: * Update README.rst and translation files * Add index=True on some fields on which we often search, as suggested by Yannick * Remove description in __openerp__.py * Move ACL from l10n_fr_intrastat_product module to intrastat_product module * Large code re-engineering following the Akretion-Noviat code sprint on intrastat This code has been written both by Luc de Meyer and myself. * Add first draft of code to generate decl lines --- intrastat_product/README.rst | 41 + intrastat_product/__init__.py | 24 +- intrastat_product/__openerp__.py | 30 +- intrastat_product/account_invoice.py | 88 +++ intrastat_product/account_invoice_view.xml | 44 ++ .../data/intrastat_transport_mode.xml | 53 ++ intrastat_product/data/intrastat_unit.xml | 125 +++ intrastat_product/i18n/intrastat_product.pot | 70 +- intrastat_product/intrastat.py | 182 +++-- intrastat_product/intrastat_declaration.py | 724 ++++++++++++++++++ .../intrastat_declaration_view.xml | 177 +++++ intrastat_product/intrastat_demo.xml | 77 +- intrastat_product/intrastat_view.xml | 266 +++++-- intrastat_product/res_company.py | 67 ++ intrastat_product/res_company_view.xml | 21 + .../security/intrastat_security.xml | 12 + .../security/ir.model.access.csv | 11 +- intrastat_product/stock.py | 40 + intrastat_product/stock_view.xml | 28 + 19 files changed, 1793 insertions(+), 287 deletions(-) create mode 100644 intrastat_product/README.rst create mode 100644 intrastat_product/account_invoice.py create mode 100644 intrastat_product/account_invoice_view.xml create mode 100644 intrastat_product/data/intrastat_transport_mode.xml create mode 100644 intrastat_product/data/intrastat_unit.xml create mode 100644 intrastat_product/intrastat_declaration.py create mode 100644 intrastat_product/intrastat_declaration_view.xml create mode 100644 intrastat_product/res_company.py create mode 100644 intrastat_product/res_company_view.xml create mode 100644 intrastat_product/security/intrastat_security.xml create mode 100644 intrastat_product/stock.py create mode 100644 intrastat_product/stock_view.xml diff --git a/intrastat_product/README.rst b/intrastat_product/README.rst new file mode 100644 index 0000000..455c358 --- /dev/null +++ b/intrastat_product/README.rst @@ -0,0 +1,41 @@ +Intrastat Product Module +======================== + +This module contains common objects and fields for the Intrastat Product reporting, such as the *H.S. codes* (if you are not familiar with H.S. codes, read `Wikipedia `) and the *country of origin* on the products. + +It should be used in combination with country-specific Intrastat Product reporting modules +such as: + +- *l10n_fr_intrastat_product*: + the module for the *Déclaration d'Echange de Biens* (DEB) for France + +These country-specific modules can be found in the OCA localization for those countries. + +Installation +============ + +WARNING: +This module conflicts with the module *report_intrastat* from the official addons. +If you have already installed the module *report_intrastat*, +you should uninstall it before installing this module. + +Credits +======= + +Contributors +------------ + +* Alexis de Lattre, Akretion + +Maintainer +---------- + +.. image:: http://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: http://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. + +To contribute to this module, please visit http://odoo-community.org. diff --git a/intrastat_product/__init__.py b/intrastat_product/__init__.py index 64a3431..063edb0 100644 --- a/intrastat_product/__init__.py +++ b/intrastat_product/__init__.py @@ -1,23 +1,7 @@ # -*- encoding: utf-8 -*- -############################################################################## -# -# Intrastat product module for OpenERP -# Copyright (C) 2011-2014 Akretion (http://www.akretion.com) -# @author Alexis de Lattre -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +from . import res_company from . import intrastat +from . import intrastat_declaration +from . import stock +from . import account_invoice diff --git a/intrastat_product/__openerp__.py b/intrastat_product/__openerp__.py index 6224d37..7a593e8 100644 --- a/intrastat_product/__openerp__.py +++ b/intrastat_product/__openerp__.py @@ -3,7 +3,9 @@ # # Intrastat Product module for Odoo # Copyright (C) 2011-2015 Akretion (http://www.akretion.com) +# Copyright (C) 2015 Noviat (http://www.noviat.com) # @author Alexis de Lattre +# @author Luc de Meyer # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -22,23 +24,27 @@ { 'name': 'Intrastat Product', - 'version': '1.1', - 'category': 'Localisation/Report Intrastat', + 'version': '1.3', + 'category': 'Intrastat', 'license': 'AGPL-3', 'summary': 'Base module for Intrastat Product', - 'description': """ -This module contains the common objects for the Intrastat Product. -This module is country-independant. - -This module has been written by Alexis de Lattre from Akretion - - """, - 'author': 'Akretion', - 'website': 'http://www.akretion.com', - 'depends': ['intrastat_base'], + 'author': 'Akretion, Noviat, Odoo Community Association (OCA)', + 'depends': [ + 'intrastat_base', + 'product_harmonized_system', + 'stock', + ], + 'conflicts': ['report_intrastat'], 'data': [ 'intrastat_view.xml', + 'intrastat_declaration_view.xml', + 'res_company_view.xml', + 'account_invoice_view.xml', + 'stock_view.xml', + 'security/intrastat_security.xml', 'security/ir.model.access.csv', + 'data/intrastat_transport_mode.xml', + 'data/intrastat_unit.xml', ], 'demo': ['intrastat_demo.xml'], 'installable': True, diff --git a/intrastat_product/account_invoice.py b/intrastat_product/account_invoice.py new file mode 100644 index 0000000..3179012 --- /dev/null +++ b/intrastat_product/account_invoice.py @@ -0,0 +1,88 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2012-2015 Noviat nv/sa (www.noviat.com) +# Copyright (C) 2015 Akretion (http://www.akretion.com) +# @author Luc de Meyer +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields, api + + +class AccountInvoice(models.Model): + _inherit = 'account.invoice' + + @api.model + def _default_intrastat_transaction(self): + """ placeholder for localisation modules """ + return self.env['intrastat.transaction'].browse([]) + + intrastat_transaction_id = fields.Many2one( + 'intrastat.transaction', string='Intrastat Transaction Type', + default=_default_intrastat_transaction, ondelete='restrict', + help="Intrastat nature of transaction") + intrastat_transport_id = fields.Many2one( + 'intrastat.transport_mode', string='Intrastat Transport Mode', + ondelete='restrict') + src_dest_country_id = fields.Many2one( + 'res.country', string='Origin/Destination Country', + ondelete='restrict') + intrastat_country = fields.Boolean( + related='src_dest_country_id.intrastat', + store=True, string='Intrastat Country', readonly=True) + intrastat = fields.Char( + string='Intrastat Declaration', + related='company_id.intrastat', store=True, readonly=True) + + @api.multi + def onchange_partner_id( + self, type, partner_id, date_invoice=False, + payment_term=False, partner_bank_id=False, company_id=False): + res = super(AccountInvoice, self).onchange_partner_id( + type, partner_id, date_invoice=date_invoice, + payment_term=payment_term, partner_bank_id=partner_bank_id, + company_id=company_id) + if partner_id: + partner = self.env['res.partner'].browse(partner_id) + res['value']['src_dest_country_id'] = partner.country_id.id + return res + + +class AccountInvoiceLine(models.Model): + _inherit = 'account.invoice.line' + + hs_code_id = fields.Many2one( + 'hs.code', string='Intrastat Code', ondelete='restrict') + + @api.multi + def product_id_change( + self, product, uom_id, qty=0, name='', type='out_invoice', + partner_id=False, fposition_id=False, price_unit=False, + currency_id=False, company_id=None): + res = super(AccountInvoiceLine, self).product_id_change( + product, uom_id, qty=qty, name=name, type=type, + partner_id=partner_id, fposition_id=fposition_id, + price_unit=price_unit, currency_id=currency_id, + company_id=company_id) + + if product: + product = self.env['product.product'].browse(product) + hs_code = product.get_hs_code_recursively() + if hs_code: + res['value']['hs_code_id'] = hs_code.id + return res diff --git a/intrastat_product/account_invoice_view.xml b/intrastat_product/account_invoice_view.xml new file mode 100644 index 0000000..cccb557 --- /dev/null +++ b/intrastat_product/account_invoice_view.xml @@ -0,0 +1,44 @@ + + + + + + intrastat.invoice.form + account.invoice + + + + + + + + + + + + + + + + intrastat.invoice.supplier.form + account.invoice + + + + + + + + + + + + + + + + diff --git a/intrastat_product/data/intrastat_transport_mode.xml b/intrastat_product/data/intrastat_transport_mode.xml new file mode 100644 index 0000000..4b4d245 --- /dev/null +++ b/intrastat_product/data/intrastat_transport_mode.xml @@ -0,0 +1,53 @@ + + + + + + 1 + Sea + Sea Transport (including wagons, motor vehicles, trailers, semi-trailers and lighters on board of a ship) + + + 2 + Rail + Railway transport (including lorries on railway wagons) + + + 3 + Road + Road Transport + + + 4 + Air + Air Transport + + + 5 + Post + Postal consignments + + + 7 + Fixed installations + Fixed transport installations (e.g. pipelines, high-tension cables) + + + + 8 + Inland waterway + Inland waterway transport + + + 9 + Own propulsion + Own propulsion (imported or exported means of transport crossing the border under their own power, e.g. aircraft, lorries, boats, etc.) + + + + + + + + + diff --git a/intrastat_product/data/intrastat_unit.xml b/intrastat_product/data/intrastat_unit.xml new file mode 100644 index 0000000..a6fbaff --- /dev/null +++ b/intrastat_product/data/intrastat_unit.xml @@ -0,0 +1,125 @@ + + + + + + + + c/k + Carats - 1 metric carat = 2 × 10exp(–4) kg + + + ce/el + Number of cells + + + ct/l + Carrying capacity in tonnes + + + g + Gram + + + + gi F/S + Gram of fissile isotopes + + + kg H2O2 + Kilogram of hydrogen peroxide + + + kg K2O + Kilogram of potassium oxide + + + kg KOH + Kilogram of potassium hydroxide (caustic potash) + + + kg met.am. + Kilogram of methylamines + + + kg N + Kilogram of nitrogen + + + kg NaOH + Kilogram of sodium hydroxide (caustic soda) + + + kg/net eda + Kilogram drained net weight + + + kg P2O5 + Kilogram of diphosphorus pentaoxide + + + kg 90 pct sdt + Kilogram of substance 90 % dry + + + kg U + Kilogram of uranium + + + 1000 kWh + Thousand kilowatt hours + + + l + Litre + + + + 1000 l + Thousand litres + + + l alc. 100 pct + Litre pure (100 %) alcohol + + + m + Metre + + + + m2 + Square metre + + + m3 + Cubic metre + + + 1000 m3 + Thousand cubic metres + + + pa + Number of pairs + + + items + Number of items + + + + 100 items + Hundred items + + + 1000 items + Thousand items + + + TJ + Terajoule (gross calorific value) + + + + diff --git a/intrastat_product/i18n/intrastat_product.pot b/intrastat_product/i18n/intrastat_product.pot index 15505ac..6b1f00f 100644 --- a/intrastat_product/i18n/intrastat_product.pot +++ b/intrastat_product/i18n/intrastat_product.pot @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 8.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-11-28 22:48+0000\n" -"PO-Revision-Date: 2014-11-28 22:48+0000\n" +"POT-Creation-Date: 2015-05-27 18:43+0000\n" +"PO-Revision-Date: 2015-05-27 18:43+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -15,6 +15,11 @@ msgstr "" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" +#. module: intrastat_product +#: field:report.intrastat.code,active:0 +msgid "Active" +msgstr "" + #. module: intrastat_product #: help:product.category,intrastat_id:0 msgid "Code from the Harmonised System. If this code is not set on the product itself, it will be read here, on the related product category." @@ -25,6 +30,21 @@ msgstr "" msgid "Code from the Harmonised System. Nomenclature is available from the World Customs Organisation, see http://www.wcoomd.org/. Some countries have made their own extensions to this nomenclature." msgstr "" +#. module: intrastat_product +#: help:report.intrastat.code,intrastat_code:0 +msgid "Code used for the Intrastat declaration. Must be part of the 'Combined Nomenclature' (CN), cf http://en.wikipedia.org/wiki/Combined_NomenclatureMust have 8 digits with sometimes a 9th digit." +msgstr "" + +#. module: intrastat_product +#: field:product.template,origin_country_id:0 +msgid "Country of Origin" +msgstr "" + +#. module: intrastat_product +#: help:product.template,origin_country_id:0 +msgid "Country of origin of the product i.e. product 'made in ____'. If you have different countries of origin depending on the supplier from which you purchased the product, leave this field empty and use the equivalent field on the 'product supplier info' form." +msgstr "" + #. module: intrastat_product #: field:report.intrastat.code,create_uid:0 msgid "Created by" @@ -40,6 +60,16 @@ msgstr "" msgid "Description" msgstr "" +#. module: intrastat_product +#: field:report.intrastat.code,display_name:0 +msgid "Display Name" +msgstr "" + +#. module: intrastat_product +#: field:report.intrastat.code,intrastat_code:0 +msgid "European Intrastat Code" +msgstr "" + #. module: intrastat_product #: help:report.intrastat.code,name:0 msgid "Full length Harmonized System code (digits only). Full list is available from the World Customs Organisation, see http://www.wcoomd.org" @@ -56,7 +86,7 @@ msgid "H.S. code" msgstr "" #. module: intrastat_product -#: code:addons/intrastat_product/intrastat.py:56 +#: code:addons/intrastat_product/intrastat.py:73 #, python-format msgid "H.S. codes should only contain digits. It is not the case of H.S. code '%s'." msgstr "" @@ -95,6 +125,12 @@ msgstr "" msgid "Last Updated on" msgstr "" +#. module: intrastat_product +#: view:report.intrastat.code:intrastat_product.product_intrastat_code_form +#: field:report.intrastat.code,product_categ_ids:0 +msgid "Product Categories" +msgstr "" + #. module: intrastat_product #: model:ir.model,name:intrastat_product.model_product_category msgid "Product Category" @@ -105,18 +141,46 @@ msgstr "" msgid "Product Template" msgstr "" +#. module: intrastat_product +#: view:report.intrastat.code:intrastat_product.product_intrastat_code_form +#: field:report.intrastat.code,product_tmpl_ids:0 +msgid "Products" +msgstr "" + #. module: intrastat_product #: view:report.intrastat.code:intrastat_product.product_intrastat_code_search msgid "Search Intrastat Codes" msgstr "" +#. module: intrastat_product +#: help:report.intrastat.code,intrastat_uom_id:0 +msgid "Select the unit of measure if one is required for this particular Intrastat Code (other than the weight in Kg). If no particular unit of measure is required, leave empty." +msgstr "" + #. module: intrastat_product #: help:report.intrastat.code,description:0 msgid "Short text description of the H.S. category" msgstr "" +#. module: intrastat_product +#: code:addons/intrastat_product/intrastat.py:82 +#, python-format +msgid "The field Intrastat Code should contain 8 or 9 digits. It is not the case of Intrastat Code '%s'." +msgstr "" + +#. module: intrastat_product +#: code:addons/intrastat_product/intrastat.py:77 +#, python-format +msgid "The field Intrastat Code should only contain digits. It is not the case of Intrastat Code '%s'." +msgstr "" + #. module: intrastat_product #: sql_constraint:report.intrastat.code:0 msgid "This H.S. code already exists in Odoo !" msgstr "" +#. module: intrastat_product +#: field:report.intrastat.code,intrastat_uom_id:0 +msgid "UoM for Intrastat Report" +msgstr "" + diff --git a/intrastat_product/intrastat.py b/intrastat_product/intrastat.py index 5242514..b87953a 100644 --- a/intrastat_product/intrastat.py +++ b/intrastat_product/intrastat.py @@ -1,10 +1,11 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Intrastat Product module for OpenERP -# Copyright (C) 2004-2009 Tiny SPRL (http://tiny.be) -# Copyright (C) 2010-2014 Akretion (http://www.akretion.com) +# Intrastat Product module for Odoo +# Copyright (C) 2011-2015 Akretion (http://www.akretion.com) +# Copyright (C) 2015 Noviat (http://www.noviat.com) # @author Alexis de Lattre +# @author Luc de Meyer # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -25,108 +26,97 @@ from openerp import models, fields, api, _ from openerp.exceptions import ValidationError -class ReportIntrastatCode(models.Model): - _name = "report.intrastat.code" - _description = "H.S. Code" - _order = "name" - _rec_name = "display_name" - - @api.one - @api.depends('name', 'description') - def _compute_display_name(self): - display_name = self.name or '' - if self.description: - display_name += ' ' + self.description - self.display_name = display_name +class IntrastatUnit(models.Model): + _name = 'intrastat.unit' + _description = 'Intrastat Supplementary Units' name = fields.Char( - string='H.S. code', - help="Full length Harmonized System code (digits only). Full list is " - "available from the World Customs Organisation, see " - "http://www.wcoomd.org") + string='Name', required=True) description = fields.Char( - 'Description', help="Short text description of the H.S. category") - display_name = fields.Char( - compute='_compute_display_name', string="Display Name", readonly=True, - store=True) - intrastat_code = fields.Char( - string='European Intrastat Code', size=9, required=True, - help="Code used for the Intrastat declaration. Must be part " - "of the 'Combined Nomenclature' (CN), cf " - "http://en.wikipedia.org/wiki/Combined_Nomenclature" - "Must have 8 digits with sometimes a 9th digit.") - intrastat_uom_id = fields.Many2one( - 'product.uom', string='UoM for Intrastat Report', - help="Select the unit of measure if one is required for " - "this particular Intrastat Code (other than the weight in Kg). " - "If no particular unit of measure is required, leave empty.") - active = fields.Boolean(default=True) - product_categ_ids = fields.One2many( - 'product.category', 'intrastat_id', string='Product Categories') - product_tmpl_ids = fields.One2many( - 'product.template', 'intrastat_id', string='Products') + string='Description', required=True) + uom_id = fields.Many2one( + 'product.uom', string='Regular UoM', + help="Select the regular Unit of Measure of Odoo that corresponds " + "to this Intrastat Supplementary Unit.") + active = fields.Boolean( + string='Active', default=True) - @api.constrains('name', 'intrastat_code') + +class HSCode(models.Model): + _inherit = "hs.code" + + intrastat_unit_id = fields.Many2one( + 'intrastat.unit', string='Intrastat Supplementary Unit') + + @api.constrains('local_code') def _hs_code(self): - if self.name and not self.name.isdigit(): - raise ValidationError( - _("H.S. codes should only contain digits. It is not the case " - "of H.S. code '%s'.") % self.name) - if self.intrastat_code and not self.intrastat_code.isdigit(): - raise ValidationError( - _("The field Intrastat Code should only contain digits. " - "It is not the case of Intrastat Code '%s'.") - % self.intrastat_code) - if self.intrastat_code and len(self.intrastat_code) not in (8, 9): - raise ValidationError( - _("The field Intrastat Code should " - "contain 8 or 9 digits. It is not the case of " - "Intrastat Code '%s'.") - % self.intrastat_code) + if self.company_id.country_id.intrastat: + if not self.local_code.isdigit(): + raise ValidationError( + _("Intrastat Codes should only contain digits. " + "This is not the case for code '%s'.") + % self.local_code) + if len(self.local_code) != 8: + raise ValidationError( + _("Intrastat Codes should " + "contain 8 digits. This is not the case for " + "Intrastat Code '%s' which has %d digits.") + % (self.local_code, len(self.local_code))) + + +class IntrastatTransaction(models.Model): + _name = 'intrastat.transaction' + _description = "Intrastat Transaction" + _order = 'code' + _rec_name = 'display_name' + + @api.one + @api.depends('code', 'description') + def _compute_display_name(self): + display_name = self.code + if self.description: + display_name += ' ' + self.description + self.display_name = len(display_name) > 55 \ + and display_name[:55] + '...' \ + or display_name + + code = fields.Char(string='Code', required=True) + description = fields.Text(string='Description') + display_name = fields.Char( + compute='_compute_display_name', string="Display Name", readonly=True) + company_id = fields.Many2one( + 'res.company', string='Company', + default=lambda self: self.env['res.company']._company_default_get( + 'intrastat.transaction')) _sql_constraints = [( - 'hs_code_uniq', - 'unique(name)', - 'This H.S. code already exists in Odoo !' - )] - - @api.model - @api.returns('self', lambda value: value.id) - def create(self, vals): - if vals.get('intrastat_code'): - vals['intrastat_code'] = vals['intrastat_code'].replace(' ', '') - return super(ReportIntrastatCode, self).create(vals) - - @api.multi - def write(self, vals): - if vals.get('intrastat_code'): - vals['intrastat_code'] = vals['intrastat_code'].replace(' ', '') - return super(ReportIntrastatCode, self).write(vals) + 'intrastat_transaction_code_unique', + 'UNIQUE(code, company_id)', + 'Code must be unique.')] -class ProductTemplate(models.Model): - _inherit = "product.template" +class IntrastatTransportMode(models.Model): + _name = 'intrastat.transport_mode' + _description = "Intrastat Transport Mode" + _rec_name = 'display_name' + _order = 'code' - intrastat_id = fields.Many2one( - 'report.intrastat.code', string='Intrastat Code', - help="Code from the Harmonised System. Nomenclature is " - "available from the World Customs Organisation, see " - "http://www.wcoomd.org/. Some countries have made their own " - "extensions to this nomenclature.") - origin_country_id = fields.Many2one( - 'res.country', string='Country of Origin', - help="Country of origin of the product i.e. product " - "'made in ____'. If you have different countries of origin " - "depending on the supplier from which you purchased the product, " - "leave this field empty and use the equivalent field on the " - "'product supplier info' form.") + @api.one + @api.depends('name', 'code') + def _display_name(self): + print "display_name self=", self + print "self.code=", self.code + print "self.name=", self.name + self.display_name = '%s. %s' % (self.code, self.name) + display_name = fields.Char( + string='Display Name', compute='_display_name', store=True, + readonly=True) + code = fields.Char(string='Code', required=True) + name = fields.Char(string='Name', required=True, translate=True) + description = fields.Char(string='Description', translate=True) -class ProductCategory(models.Model): - _inherit = "product.category" - - intrastat_id = fields.Many2one( - 'report.intrastat.code', string='Intrastat Code', - help="Code from the Harmonised System. If this code is not " - "set on the product itself, it will be read here, on the " - "related product category.") + _sql_constraints = [( + 'intrastat_transport_code_unique', + 'UNIQUE(code)', + 'Code must be unique.')] diff --git a/intrastat_product/intrastat_declaration.py b/intrastat_product/intrastat_declaration.py new file mode 100644 index 0000000..9f4f731 --- /dev/null +++ b/intrastat_product/intrastat_declaration.py @@ -0,0 +1,724 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Intrastat Product module for Odoo +# Copyright (C) 2011-2015 Akretion (http://www.akretion.com) +# Copyright (C) 2011-2015 Noviat (http://www.noviat.com) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields, api, _ +from openerp.exceptions import Warning, RedirectWarning, ValidationError +import openerp.addons.decimal_precision as dp +from datetime import datetime, date +from dateutil.relativedelta import relativedelta +import logging + +_logger = logging.getLogger(__name__) + + +class IntrastatProductDeclaration(models.Model): + _name = 'intrastat.product.declaration' + _description = "Intrastat Product Report Base Object" + _rec_name = 'year_month' + _inherit = ['mail.thread', 'intrastat.common'] + _order = 'year_month desc, type, revision' + _track = { + 'state': { + 'intrastat_product.declaration_done': + lambda self, cr, uid, obj, ctx=None: obj['state'] == 'done', + } + } + + @api.model + def _get_type(self): + res = [] + company = self.env.user.company_id + arrivals = company.intrastat_arrivals + dispatches = company.intrastat_dispatches + if arrivals != 'exempt': + res.append(('arrivals', _('Declaration for Arrivals'))) + if dispatches != 'exempt': + res.append(('dispatches', _('Declaration for Dispatches'))) + return res + + @api.model + def _get_reporting_level(self): + return [ + ('standard', _('Standard')), + ('extended', _('Extended'))] + + @api.onchange('type') + def _onchange_type(self): + if self.type == 'arrivals': + self.reporting_level = \ + self.company_id.intrastat_arrivals == 'extended' \ + and 'extended' or 'standard' + if self.type == 'dispatches': + self.reporting_level = \ + self.company_id.intrastat_dispatches == 'extended' \ + and 'extended' or 'standard' + + @api.model + def _get_company(self): + return self.env.user.company_id + + @api.model + def _get_year(self): + if datetime.now().month == 1: + return datetime.now().year - 1 + else: + return datetime.now().year + + @api.model + def _get_month(self): + if datetime.now().month == 1: + return 12 + else: + return datetime.now().month - 1 + + @api.model + def _get_action(self): + return [ + ('replace', 'Replace'), + ('append', 'Append'), + ('nihil', 'Nihil')] + + @api.model + def _get_default_action(self): + return 'replace' + + company_id = fields.Many2one( + 'res.company', string='Company', readonly=True, + default=lambda self: self.env['res.company']._company_default_get( + 'intrastat.product.declaration')) + year = fields.Integer( + string='Year', required=True, + default=_get_year) + month = fields.Selection([ + (1, '01'), + (2, '02'), + (3, '03'), + (4, '04'), + (5, '05'), + (6, '06'), + (7, '07'), + (8, '08'), + (9, '09'), + (10, '10'), + (11, '11'), + (12, '12') + ], string='Month', required=True, + default=_get_month) + year_month = fields.Char( + compute='_compute_year_month', string='Month', readonly=True, + track_visibility='always', store=True, + help="Year and month of the declaration.") + type = fields.Selection( + '_get_type', string='Type', required=True, + states={'done': [('readonly', True)]}, + track_visibility='always', help="Select the declaration type.") + action = fields.Selection( + '_get_action', + string='Action', required=True, + default=_get_default_action, + states={'done': [('readonly', True)]}, + track_visibility='onchange') + revision = fields.Integer( + string='Revision', default=1, + states={'done': [('readonly', True)]}, + help="Used to keep track of changes") + computation_line_ids = fields.One2many( + 'intrastat.product.computation.line', + 'parent_id', string='Intrastat Product Computation Lines', + states={'done': [('readonly', True)]}) + declaration_line_ids = fields.One2many( + 'intrastat.product.declaration.line', + 'parent_id', string='Intrastat Product Declaration Lines', + states={'done': [('readonly', True)]}) + num_decl_lines = fields.Integer( + compute='_compute_numbers', string='Number of Declaration Lines', + store=True, track_visibility='onchange') + total_amount = fields.Float( + compute='_compute_numbers', digits=dp.get_precision('Account'), + string='Total Amount', store=True, + help="Total amount in company currency of the declaration.") + currency_id = fields.Many2one( + 'res.currency', related='company_id.currency_id', readonly=True, + string='Currency') + state = fields.Selection([ + ('draft', 'Draft'), + ('done', 'Done'), + ], string='State', readonly=True, track_visibility='onchange', + 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( + '_get_reporting_level', + string='Reporting Level') + valid = fields.Boolean( + compute='_check_validity', + string='Valid') + + @api.one + @api.constrains('year') + def _check_year(self): + s = str(self.year) + if len(s) != 4 or s[0] != '2': + raise ValidationError( + _("Invalid Year !")) + + _sql_constraints = [ + ('date_uniq', + 'unique(year_month, company_id, type)', + "A declaration of the same type already exists for this month !" + "\nYou should update the existing declaration " + "or change the revision number of this one."), + ] + + @api.one + @api.depends('year', 'month') + def _compute_year_month(self): + if self.year and self.month: + self.year_month = '-'.join( + [str(self.year), format(self.month, '02')]) + + @api.one + @api.depends('month') + def _check_validity(self): + """ TO DO: logic based upon computation lines """ + self.valid = True + + @api.one + @api.returns('self', lambda value: value.id) + def copy(self, default=None): + default = default or {} + default['revision'] = self.revision + 1 + return super(IntrastatProductDeclaration, self).copy(default) + + def _company_warning(self, msg): + action = self.env.ref('base.action_res_company_form') + raise RedirectWarning( + msg, action.id, + _('Go to company configuration screen')) + + def _get_partner_country(self, inv_line): + country = inv_line.invoice_id.intrastat_country_id \ + or inv_line.invoice_id.partner_id.country_id + if not country.intrastat: + country = False + elif country == self.company_id.country_id: + country = False + return country + + def _get_intrastat_transaction(self, inv_line): + if inv_line.invoice_id.intrastat_transaction_id: + tr = inv_line.invoice_id.intrastat_transaction_id.code + else: + tr = self.env.ref( + 'l10n_be_intrastat_advanced.intrastat_transaction_1') + return tr + + def _get_region(self, inv_line): + """ + Logic copied from standard addons, l10n_be_intrastat module: + If purchase, comes from purchase order, linked to a location, + which is linked to the warehouse. + + If sales, the sale order is linked to the warehouse. + If sales, from a delivery order, linked to a location, + which is linked to the warehouse. + If none found, get the company one. + """ + region = False + if inv_line.invoice_id.type in ('in_invoice', 'in_refund'): + po_lines = self.env['purchase.order.line'].search( + [('invoice_lines', 'in', inv_line.id)]) + if po_lines: + po = po_lines.order_id + region = self.env['stock.warehouse'].get_region_from_location( + po.location_id) + elif inv_line.invoice_id.type in ('out_invoice', 'out_refund'): + so_lines = self.env['sale.order.line'].search( + [('invoice_lines', 'in', inv_line.id)]) + if so_lines: + so = so_lines.order_id + region = so.warehouse_id.region_id + if not region: + if self.company_id.intrastat_region_id: + region = self.company_id.intrastat_region_id + else: + msg = _( + "The Intrastat Region of the Company is not set, " + "please configure it first.") + self._company_warning(msg) + return region + + def _get_weight_and_supplunits(self, inv_line): + line_qty = inv_line.quantity + product = inv_line.product_id + invoice = inv_line.invoice_id + intrastat_unit_id = inv_line.intrastat_id.intrastat_unit_id + source_uom = inv_line.uos_id + weight_uom_categ = self._uom_refs['weight_uom_categ'] + kg_uom = self._uom_refs['kg_uom'] + pce_uom_categ = self._uom_refs['pce_uom_categ'] + pce_uom = self._uom_refs['pce_uom'] + weight = suppl_unit_qty = 0.0 + + if not source_uom: + note = "\n" + _( + "Missing unit of measure on the line with %d " + "product(s) '%s' on invoice '%s'." + ) % (line_qty, product.name, invoice.number) + note += "\n" + _( + "Please adjust this line manually.") + self._note += note + return weight, suppl_unit_qty + + if intrastat_unit_id: + target_uom = intrastat_unit_id.uom_id + if not target_uom: + note = "\n" + _( + "Conversion from Intrastat Supplementary Unit '%s' to " + "Unit of Measure is not implemented yet." + ) % intrastat_unit_id.name + note += "\n" + _( + "Please correct the Intrastat Supplementary Unit " + "settingsand regenerate the lines or adjust the lines " + "with Intrastat Code '%s' manually" + ) % intrastat_code + self._note += note + return weight, suppl_unit_qty + if target_uom.categ_id == source_uom.category_id: + suppl_unit_qty = self.env['product.uom']._compute_qty_obj( + source_uom, line_qty, target_uom) + else: + note = "\n" + _( + "Conversion from unit of measure '%s' to '%s' " + "is not implemented yet." + ) % (source_uom.name, target_uom.name) + note += "\n" + _( + "Please correct the unit of measure settings and " + "regenerate the lines or adjust the impacted " + "lines manually") + self._note += note + return weight, suppl_unit_qty + + else: + if source_uom == kg_uom: + weight = line_qty + elif source_uom.category_id == weight_uom_categ: + weight = self.env['product.uom']._compute_qty_obj( + source_uom, line_qty, kg_uom) + elif source_uom.category_id == pce_uom_categ: + if not product.weight_net: + note = "\n" + _( + "Missing net weight on product '%s'." + ) % product.name + note += "\n" + _( + "Please correct the product record and regenerate " + "the lines or adjust the impacted lines manually") + self._note += note + return weight, suppl_unit_qty + if source_uom == pce_uom: + weight = product.weight_net * line_qty + else: + # Here, I suppose that, on the product, the + # weight is per PCE and not per uom_id + weight = product.weight_net * \ + self.env['product.uom']._compute_qty_obj( + source_uom, line_qty, pce_uom) + else: + note = "\n" + _( + "Conversion from unit of measure '%s' to 'Kg' " + "is not implemented yet." + ) % source_uom.name + note += "\n" + _( + "Please correct the unit of measure settings and " + "regenerate the lines or adjust the impacted lines " + "manually") + self._note += note + return weight, suppl_unit_qty + + return weight, suppl_unit_qty + + def _get_amount(self, inv_line): + invoice = inv_line.invoice_id + amount = inv_line.price_subtotal + if invoice.currency_id.name != 'EUR': + amount = self.env['res.currency'].with_context( + date=invoice.date_invoice).compute( + invoice.currency_id, + self.company_id.currency_id, + amount) + return amount + + def _get_transport(self, inv_line): + transport = inv_line.invoice.transport_mode_id \ + or self.company_id.intrastat_transport_id + if not transport: + msg = _( + "The default Intrastat Transport Mode " + "of the Company is not set, " + "please configure it first.") + self._company_warning(msg) + return transport + + def _get_incoterm(self, inv_line): + incoterm = inv_line.invoice.incoterm_id \ + or self.company_id.incoterm_id + if not incoterm: + msg = _( + "The default Incoterm " + "of the Company is not set, " + "please configure it first.") + self._company_warning(msg) + return incoterm + + def _gather_invoices(self): + + decl_lines = [] + start_date = date(self.year, self.month, 1) + end_date = start_date + relativedelta(day=1, months=+1, days=-1) + + invoices = self.env['account.invoice'].search([ + ('date_invoice', '>=', start_date), + ('date_invoice', '<=', end_date), + ('state', 'in', ['open', 'paid']), + ('intrastat_country', '=', True), + ('company_id', '=', self.company_id.id)]) + + for invoice in invoices: + + if self.type == 'arrivals': + if invoice.type in ['out_invoice', 'in_refund']: + continue + else: + if invoice.type in ['in_invoice', 'out_refund']: + continue + + for inv_line in invoice.invoice_line: + + intrastat = inv_line.intrastat_id + if not intrastat: + continue + if not inv_line.quantity: + continue + + partner_country = self._get_partner_country(inv_line) + if not partner_country: + continue + + intrastat_transaction = \ + self._get_intrastat_transaction(inv_line) + + region = self._get_region(inv_line) + + weight, suppl_unit_qty = self._get_weight_and_supplunits( + inv_line) + + amount_company_currency = self._get_amount(inv_line) + + line_vals = { + 'parent_id': self.id, + 'invoice_line_id': inv_line.id, + 'partner_country_id': partner_country.id, + 'product_id': inv_line.product_id.id, + 'intrastat_code_id': intrastat.id, + 'weight': weight, + 'suppl_unit_qty': suppl_unit_qty, + 'amount_company_currency': amount_company_currency, + 'transaction_id': intrastat_transaction.id, + 'region_id': region.id, + 'extended': self._extended, + } + + # extended declaration + if self._extended: + transport = self._get_transport(inv_line) + incoterm = self._get_incoterm(inv_line) + line_vals.update({ + 'transport_id': transport.id, + 'incoterm_id': incoterm.id, + }) + + decl_lines.append((0, 0, line_vals)) + + return decl_lines + + @api.multi + def action_gather(self): + self.ensure_one() + self._note = '' + self._uom_refs = { + 'weight_uom_categ': self.env.ref('product.product_uom_categ_kgm'), + 'kg_uom': self.env.ref('product.product_uom_kgm'), + 'pce_uom_categ': self.env.ref('product.product_uom_categ_unit'), + 'pce_uom': self.env.ref('product.product_uom_unit') + } + if ( + self.type == 'arrivals' and + self.company_id.intrastat_arrivals == 'extended') or ( + self.type == 'dispatches' and + self.company_id.intrastat_dispatches == 'extended'): + self._extended = True + else: + self._extended = False + + decl_lines_init = [(6, 0, [])] + decl_lines = decl_lines_init[:] + + decl_lines += self._gather_invoices() + + if decl_lines == decl_lines_init: + self.action = 'nihil' + note = "\n" + \ + _("No records found for the selected period !") + '\n' + \ + _("The Declaration Action has been set to 'nihil'.") + self._note += note + + # To DO: add check on tax cases 46, 48, 84, 86 + + self.write({'intrastat_line_ids': decl_lines}) + + if self._note: + note_header = '\n\n>>> ' + str(date.today()) + '\n' + self.note = (self.note or '') + note_header + self._note + result_view = self.env.ref( + 'l10n_be_intrastat_advanced.intrastat_result_view') + return { + 'name': _("Generate lines from invoices: results"), + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'intrastat.result.view', + 'view_id': result_view.id, + 'target': 'new', + 'context': dict(self._context, note=self._note), + 'type': 'ir.actions.act_window', + } + + return True + + @api.model + def group_line_hashcode(self, computation_line): + hashcode = "%s-%s-%s-%s-%s" % ( + computation_line.src_dest_country_id.id or False, + computation_line.hs_code or False, + computation_line.intrastat_unit_id.id or False, + computation_line.transaction_id.id or False, + computation_line.transport_id.id or False + ) + return hashcode + + @api.multi + def generate_declaration(self): + """ generate declaration lines """ + self.ensure_one() + assert self.valid, 'Computation lines are not valid' + # Delete existing declaration lines + self.declaration_line_ids.unlink() + # Regenerate declaration lines from computation lines + dl_group = {} + for cl in self.computation_line_ids: + hashcode = self.group_line_hashcode(cl) + if hashcode in dl_group: + dl_group[hashcode].append(cl) + else: + dl_group[hashcode] = [cl] + ipdlo = self.pool['intrastat.product.declaration.line'] + for cl_lines in dl_group.values(): + vals = ipdlo._prepare_declaration_line(cl_lines) + declaration_line = ipdlo.create(vals) + cl_lines.write({'declaration_line_id': declaration_line.id}) + return True + + +class IntrastatProductComputationLine(models.Model): + _name = 'intrastat.product.computation.line' + _description = "Intrastat Product Computataion Lines" + + parent_id = fields.Many2one( + 'intrastat.product.declaration', + string='Intrastat Product Declaration', + ondelete='cascade', readonly=True) + company_id = fields.Many2one( + 'res.company', related='parent_id.company_id', + string="Company", readonly=True) + company_currency_id = fields.Many2one( + 'res.currency', related='company_id.currency_id', + string="Company currency", readonly=True) + type = fields.Selection( + related='parent_id.type', + string='Type', + readonly=True) + reporting_level = fields.Selection( + related='parent_id.reporting_level', + string='Reporting Level', + readonly=True) + valid = fields.Boolean( + compute='_check_validity', + string='Valid') + invoice_line_id = fields.Many2one( + 'account.invoice.line', string='Invoice Line', readonly=True) + invoice_id = fields.Many2one( + 'account.invoice', related='invoice_line_id.invoice_id', + string='Invoice', readonly=True) + declaration_line_id = fields.Many2one( + 'intrastat.product.declaration.line', + string='Declaration Line', readonly=True) + src_dest_country_id = fields.Many2one( + 'res.country', string='Country', + help="Country of Origin/Destination", + domain=[('intrastat', '=', True)]) + product_id = fields.Many2one( + 'product.product', related='invoice_line_id.product_id', + string='Product', readonly=True) + hs_code_id = fields.Many2one( + 'hs.code', string='Intrastat Code') + intrastat_unit_id = fields.Many2one( + 'intrastat.unit', related='hs_code_id.intrastat_unit_id', + string='Suppl. Unit', readonly=True, + help="Intrastat Supplementary Unit") + weight = fields.Float( + string='Weight (Kg)', + digits=dp.get_precision('Stock Weight')) + suppl_unit_qty = fields.Float( + string='Suppl. Unit Qty', + digits=dp.get_precision('Product Unit of Measure'), + help="Supplementary Units Quantity") + amount_company_currency = fields.Float( + string='Fiscal Value', + digits=dp.get_precision('Account'), required=True, + help="Amount in company currency to write in the declaration. " + "Amount in company currency = amount in invoice currency " + "converted to company currency with the rate of the invoice date.") + transaction_id = fields.Many2one( + 'intrastat.transaction', + string='Intrastat Transaction') + # extended declaration + transport_id = fields.Many2one( + 'intrastat.transport_mode', + string='Transport Mode') + + @api.one + @api.depends('transport_id') + def _check_validity(self): + """ TO DO: logic based upon fields """ + self.valid = True + + @api.onchange('product_id') + def _onchange_product(self): + self.weight = 0.0 + self.suppl_unit_qty = 0.0 + self.intrastat_code_id = False + self.intrastat_unit_id = False + if self.product_id: + self.intrastat_code_id = self.product_id.intrastat_id + self.intrastat_unit_id =\ + self.product_id.intrastat_id.intrastat_unit_id + if not self.intrastat_unit_id: + self.weight = self.product_id.weight_net + + +class IntrastatProductDeclarationLine(models.Model): + _name = 'intrastat.product.declaration.line' + _description = "Intrastat Product Declaration Lines" + + parent_id = fields.Many2one( + 'intrastat.product.declaration', + string='Intrastat Product Declaration', + ondelete='cascade', readonly=True) + company_id = fields.Many2one( + 'res.company', related='parent_id.company_id', + string="Company", readonly=True) + company_currency_id = fields.Many2one( + 'res.currency', related='company_id.currency_id', + string="Company currency", readonly=True) + type = fields.Selection( + related='parent_id.type', + string='Type', + readonly=True) + reporting_level = fields.Selection( + related='parent_id.reporting_level', + string='Reporting Level', + readonly=True) + computation_line_ids = fields.One2many( + 'intrastat.product.computation.line', 'declaration_line_id', + string='Computation Lines', readonly=True) + src_dest_country_id = fields.Many2one( + 'res.country', string='Country', + help="Country of Origin/Destination", + domain=[('intrastat', '=', True)]) + hs_code_id = fields.Many2one( + 'hs.code', + string='Intrastat Code') + intrastat_unit_id = fields.Many2one( + 'intrastat.unit', related='hs_code_id.intrastat_unit_id', + string='Suppl. Unit', readonly=True, + help="Intrastat Supplementary Unit") + weight = fields.Integer( + string='Weight (Kg)') + suppl_unit_qty = fields.Integer( + string='Suppl. Unit Qty', + help="Supplementary Units Quantity") + amount_company_currency = fields.Integer( + string='Fiscal Value', + help="Amount in company currency to write in the declaration. " + "Amount in company currency = amount in invoice currency " + "converted to company currency with the rate of the invoice date.") + transaction_id = fields.Many2one( + 'intrastat.transaction', + string='Intrastat Transaction') + # extended declaration + transport_id = fields.Many2one( + 'intrastat.transport_mode', + string='Transport Mode') + + @api.model + def _prepare_grouped_fields(computation_line, fields_to_sum): + vals = { + 'src_dest_country_id': computation_line.src_dest_country_id.id, + 'intrastat_unit_id': computation_line.intrastat_unit_id.id, + 'hs_code': computation_line.hs_code_id.local_code, + 'transaction_id': computation_line.transaction_id.id, + 'transport_id': computation_line.transport_id.id, + 'parent_id': computation_line.parent_id.id, + } + for field in fields_to_sum: + vals[field] = 0.0 + return vals + + def _fields_to_sum(): + fields_to_sum = [ + 'weight', + 'suppl_unit_qty', + 'amount_company_currency', + ] + return fields_to_sum + + @api.model + def _prepare_declaration_line(self, computation_lines): + fields_to_sum = self._fields_to_sum() + vals = self._prepare_grouped_fields( + computation_lines[0], fields_to_sum) + for computation_line in computation_lines: + for field in fields_to_sum: + vals[field] += computation_line[field] + return vals diff --git a/intrastat_product/intrastat_declaration_view.xml b/intrastat_product/intrastat_declaration_view.xml new file mode 100644 index 0000000..100eb93 --- /dev/null +++ b/intrastat_product/intrastat_declaration_view.xml @@ -0,0 +1,177 @@ + + + + + + intrastat.product.declaration.form + intrastat.product.declaration + +
+
+
+ +
+

+

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+
+ + + + Intrastat Product Declaration Validated + intrastat.product.declaration + + Intrastat Product Declaration Validated + + + + intrastat.product.tree + intrastat.product.declaration + + + + + + + + + + + + + + + intrastat.product.search + intrastat.product.declaration + + + + + + + + + + + + + + + + intrastat.product.graph + intrastat.product.declaration + + + + + + + + + + + Intrastat Product Declaration + intrastat.product.declaration + tree,form,graph + + + + + +
+
diff --git a/intrastat_product/intrastat_demo.xml b/intrastat_product/intrastat_demo.xml index b5ae41b..61b1c39 100644 --- a/intrastat_product/intrastat_demo.xml +++ b/intrastat_product/intrastat_demo.xml @@ -1,7 +1,7 @@ @@ -9,80 +9,13 @@ - - 84715000 - 84715000 - - Automatic data-processing machines (computers) + + - - 84717050 - 84717050 - - Storage units + + - - 85340090 - 85340090 - Printed circuits - - - - - - 5 - - - - - - 6 - - - - - - 6.5 - - - - - - 0.5 - - - - - - 0.5 - - - - - - 0.5 - - - - - - 0.7 - - - - - - 0.8 - - - - - - 2 - - - diff --git a/intrastat_product/intrastat_view.xml b/intrastat_product/intrastat_view.xml index b62c280..c61fc61 100644 --- a/intrastat_product/intrastat_view.xml +++ b/intrastat_product/intrastat_view.xml @@ -1,101 +1,203 @@ - + - - - intrastat.product.template.form - product.template - - - - - + + + + + + intrastat.hs.code.tree + hs.code + + + + - - + + - - - intrastat.product.category.form - product.category - - - - - - - - - + + + intrastat.hs.code.form + hs.code + + + + + + + - - - intrastat.product.intrastat.code.search - report.intrastat.code - - - - - - - - - - intrastat.product.intrastat.code.tree - report.intrastat.code - - + + + intrastat.unit.form + intrastat.unit + +
+ - - + - - - - - - - fr.intrastat.product.intrastat.code.form - report.intrastat.code - - - - - - - - - - - - - - - + +
-
-
+
+
- - - Intrastat Code - report.intrastat.code - tree,form - + + intrastat.unit.tree + intrastat.unit + + + + + + + + - - + + intrastat.unit.search + intrastat.unit + + + + + + + + + -
+ + + Supplementary Units + intrastat.unit + tree,form + + + + + + + intrastat.transaction_form + intrastat.transaction + +
+ + + + + +
+
+
+ + + intrastat.transaction_tree + intrastat.transaction + + + + + + + + + + + intrastat.transaction.mode.search + intrastat.transaction + + + + + + + + + + + + Transaction Types + intrastat.transaction + tree,form + + + + + + + + intrastat.transport.mode.form + intrastat.transport_mode + +
+ + + + + +
+
+
+ + + intrastat.transport.mode.tree + intrastat.transport_mode + + + + + + + + + + + intrastat.transport.mode.search + intrastat.transport_mode + + + + + + + + + Transport Modes + intrastat.transport_mode + tree,form + + + + +
diff --git a/intrastat_product/res_company.py b/intrastat_product/res_company.py new file mode 100644 index 0000000..65e0e3f --- /dev/null +++ b/intrastat_product/res_company.py @@ -0,0 +1,67 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2012-2015 Noviat nv/sa (www.noviat.com) +# Copyright (C) 2015 Akretion (http://www.akretion.com) +# @author Luc de Meyer +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields, api + + +class ResCompany(models.Model): + _inherit = 'res.company' + + @api.model + def _intrastat_arrivals(self): + return [ + ('exempt', 'Exempt'), + ('standard', 'Standard'), + ('extended', 'Extended')] + + @api.model + def _intrastat_dispatches(self): + return [ + ('exempt', 'Exempt'), + ('standard', 'Standard'), + ('extended', 'Extended')] + + @api.one + @api.depends('intrastat_arrivals', 'intrastat_dispatches') + def _compute_intrastat(self): + if self.intrastat_arrivals == 'exempt' \ + and self.intrastat_dispatches == 'exempt': + self.intrastat = 'exempt' + elif self.intrastat_arrivals == 'extended' \ + or self.intrastat_dispatches == 'extended': + self.intrastat = 'extended' + else: + self.intrastat = 'standard' + + intrastat_arrivals = fields.Selection( + '_intrastat_arrivals', string='Arrivals', + default='extended', required=True) + intrastat_dispatches = fields.Selection( + '_intrastat_arrivals', string='Dispatches', + default='extended', required=True) + intrastat_transport_id = fields.Many2one( + 'intrastat.transport_mode', + string='Default Transport Mode', ondelete='restrict') + intrastat = fields.Char( + string='Intrastat Declaration', store=True, readonly=True, + compute='_compute_intrastat') diff --git a/intrastat_product/res_company_view.xml b/intrastat_product/res_company_view.xml new file mode 100644 index 0000000..9761cb4 --- /dev/null +++ b/intrastat_product/res_company_view.xml @@ -0,0 +1,21 @@ + + + + + + intrastat.company.form + res.company + + + + + + + + + + + + + diff --git a/intrastat_product/security/intrastat_security.xml b/intrastat_product/security/intrastat_security.xml new file mode 100644 index 0000000..cd4f161 --- /dev/null +++ b/intrastat_product/security/intrastat_security.xml @@ -0,0 +1,12 @@ + + + + + + Intrastat Transaction Company rule + + ['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])] + + + + diff --git a/intrastat_product/security/ir.model.access.csv b/intrastat_product/security/ir.model.access.csv index 1708adf..bd6835f 100644 --- a/intrastat_product/security/ir.model.access.csv +++ b/intrastat_product/security/ir.model.access.csv @@ -1,3 +1,10 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_report_intrastat_code_sale_manager,Full access on report.intrastat.code to sale manager,model_report_intrastat_code,base.group_sale_manager,1,1,1,1 -access_report_intrastat_code_employee,Read access on report.intrastat.code to employee,model_report_intrastat_code,base.group_user,1,0,0,0 +access_intrastat_unit_read,Read access on Intrastat Supplementary Units to everybody,model_intrastat_unit,,1,0,0,0 +access_intrastat_unit_full,Full access on Intrastat Supplementary Units to Finance manager,model_intrastat_unit,account.group_account_manager,1,1,1,1 +access_intrastat_transaction_read,Read access on Intrastat Transaction Types to everybody,model_intrastat_transaction,,1,0,0,0 +access_intrastat_transaction_full,Full access on Intrastat Transaction Types to Finance manager,model_intrastat_transaction,account.group_account_manager,1,1,1,1 +access_intrastat_transport_mode_read,Read access on Intrastat Transport Modes to everybody,model_intrastat_transport_mode,,1,0,0,0 +access_intrastat_transport_mode_full,Full access on Intrastat Transport Modes to Finance manager,model_intrastat_transport_mode,account.group_account_manager,1,1,1,1 +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 diff --git a/intrastat_product/stock.py b/intrastat_product/stock.py new file mode 100644 index 0000000..c97cf75 --- /dev/null +++ b/intrastat_product/stock.py @@ -0,0 +1,40 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2010-2015 Akretion (http://www.akretion.com) +# @author Alexis de Lattre +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields, api + + +class StockPicking(models.Model): + _inherit = "stock.picking" + + intrastat_transport_id = fields.Many2one( + 'intrastat.transport_mode', string='Transport Mode', + help="This information is used in Intrastat reports") + intrastat = fields.Char(related='company_id.intrastat') + + @api.model + def _create_invoice_from_picking(self, picking, vals): + '''Copy transport and department from picking to invoice''' + vals['intrastat_transport_id'] = picking.intrastat_transport_id.id + if picking.partner_id and picking.partner_id.country_id: + vals['src_dest_country_id'] = picking.partner_id.country_id.id + return super(StockPicking, self)._create_invoice_from_picking( + picking, vals) diff --git a/intrastat_product/stock_view.xml b/intrastat_product/stock_view.xml new file mode 100644 index 0000000..80ce61e --- /dev/null +++ b/intrastat_product/stock_view.xml @@ -0,0 +1,28 @@ + + + + + + + + + + intrastat.product.picking.form + stock.picking + + + + + + + + + + + From d05d444664dcfeb26bb12e88a08e56832ba015ba Mon Sep 17 00:00:00 2001 From: Luc De Meyer Date: Sat, 25 Jul 2015 17:18:44 +0200 Subject: [PATCH 26/44] [IMP] intrastat_product: major update intrastat V3 modules * add region to intrastat_product --- intrastat_product/README.rst | 81 ++++++- intrastat_product/__init__.py | 6 +- intrastat_product/__openerp__.py | 21 +- .../{ => demo}/intrastat_demo.xml | 0 intrastat_product/intrastat.py | 122 ----------- intrastat_product/intrastat_view.xml | 203 ----------------- intrastat_product/models/__init__.py | 11 + .../{ => models}/account_invoice.py | 32 ++- intrastat_product/models/hs_code.py | 48 ++++ .../intrastat_product_declaration.py} | 206 ++++++++++-------- intrastat_product/models/intrastat_region.py | 43 ++++ .../models/intrastat_transaction.py | 56 +++++ .../models/intrastat_transport_mode.py | 49 +++++ intrastat_product/models/intrastat_unit.py | 41 ++++ intrastat_product/{ => models}/res_company.py | 46 ++-- .../{stock.py => models/stock_picking.py} | 5 +- intrastat_product/models/stock_warehouse.py | 42 ++++ .../security/intrastat_security.xml | 6 + .../security/ir.model.access.csv | 2 + .../account_invoice.xml} | 8 + intrastat_product/views/hs_code.xml | 45 ++++ .../intrastat_product_declaration.xml} | 41 ++-- intrastat_product/views/intrastat_region.xml | 46 ++++ .../views/intrastat_transaction.xml | 68 ++++++ .../views/intrastat_transport_mode.xml | 64 ++++++ intrastat_product/views/intrastat_unit.xml | 70 ++++++ .../res_company.xml} | 3 + .../stock_picking.xml} | 0 intrastat_product/views/stock_warehouse.xml | 17 ++ 29 files changed, 907 insertions(+), 475 deletions(-) rename intrastat_product/{ => demo}/intrastat_demo.xml (100%) delete mode 100644 intrastat_product/intrastat.py delete mode 100644 intrastat_product/intrastat_view.xml create mode 100644 intrastat_product/models/__init__.py rename intrastat_product/{ => models}/account_invoice.py (81%) create mode 100644 intrastat_product/models/hs_code.py rename intrastat_product/{intrastat_declaration.py => models/intrastat_product_declaration.py} (87%) create mode 100644 intrastat_product/models/intrastat_region.py create mode 100644 intrastat_product/models/intrastat_transaction.py create mode 100644 intrastat_product/models/intrastat_transport_mode.py create mode 100644 intrastat_product/models/intrastat_unit.py rename intrastat_product/{ => models}/res_company.py (76%) rename intrastat_product/{stock.py => models/stock_picking.py} (89%) create mode 100644 intrastat_product/models/stock_warehouse.py rename intrastat_product/{account_invoice_view.xml => views/account_invoice.xml} (82%) create mode 100644 intrastat_product/views/hs_code.xml rename intrastat_product/{intrastat_declaration_view.xml => views/intrastat_product_declaration.xml} (82%) create mode 100644 intrastat_product/views/intrastat_region.xml create mode 100644 intrastat_product/views/intrastat_transaction.xml create mode 100644 intrastat_product/views/intrastat_transport_mode.xml create mode 100644 intrastat_product/views/intrastat_unit.xml rename intrastat_product/{res_company_view.xml => views/res_company.xml} (73%) rename intrastat_product/{stock_view.xml => views/stock_picking.xml} (100%) create mode 100644 intrastat_product/views/stock_warehouse.xml diff --git a/intrastat_product/README.rst b/intrastat_product/README.rst index 455c358..1ad1510 100644 --- a/intrastat_product/README.rst +++ b/intrastat_product/README.rst @@ -1,3 +1,8 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +======================== Intrastat Product Module ======================== @@ -8,6 +13,8 @@ such as: - *l10n_fr_intrastat_product*: the module for the *Déclaration d'Echange de Biens* (DEB) for France +- *l10n_be_intrastat_product*: + the module for the Intrastat Product Declaration for Belgium These country-specific modules can be found in the OCA localization for those countries. @@ -15,10 +22,74 @@ Installation ============ WARNING: + This module conflicts with the module *report_intrastat* from the official addons. If you have already installed the module *report_intrastat*, you should uninstall it before installing this module. + +Usage +===== + +This module is used in combination with the country-specific +localization module(s). + +Coding guidelines for localization module: +------------------------------------------ + +We recommend to start by copying an existing module, e.g. l10n_be_intrastat_product +and adapt the code for the specific needs of your country. + +* Declaration Object + + Create a new class as follows: + + .. code-block:: python + + class L10nCcIntrastatProductDeclaration(models.Model): + _name = 'l10n.cc.intrastat.product.declaration' + _description = "Intrastat Product Declaration for YourCountry" + _inherit = ['intrastat.product.declaration', 'mail.thread'] + + whereby cc = your country code + +* Computation & Declaration Lines + + Create also new objects inheriting from the Computation and Declaration Line Objects + so that you can add methods or customise the methods from the base modules (make a PR when + the customization or new method is required for multiple countries). + + Adapt also the parent_id fields of the newly created objects + (cf. l10n_be_intrastat_product as example). + +* XML Files: Menu, Action, Views + + Cf. l10n_be_istrastat_product as example, replace "be" by your Country Code. + + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/91/8.0 + + +Known issues / Roadmap +====================== + +Work is in progress to migrate the existing l10n_fr_intrastat_product module +to this new reporting framework, cf. Alexis de Lattre, Akretion . + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed feedback `here `_. + + Credits ======= @@ -26,16 +97,20 @@ Contributors ------------ * Alexis de Lattre, Akretion +* Luc De Meyer, Noviat + Maintainer ---------- -.. image:: http://odoo-community.org/logo.png +.. image:: https://odoo-community.org/logo.png :alt: Odoo Community Association - :target: http://odoo-community.org + :target: https://odoo-community.org This module is maintained by the OCA. -OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. To contribute to this module, please visit http://odoo-community.org. diff --git a/intrastat_product/__init__.py b/intrastat_product/__init__.py index 063edb0..21ff7c2 100644 --- a/intrastat_product/__init__.py +++ b/intrastat_product/__init__.py @@ -1,7 +1,3 @@ # -*- encoding: utf-8 -*- -from . import res_company -from . import intrastat -from . import intrastat_declaration -from . import stock -from . import account_invoice +from . import models diff --git a/intrastat_product/__openerp__.py b/intrastat_product/__openerp__.py index 7a593e8..b9576da 100644 --- a/intrastat_product/__openerp__.py +++ b/intrastat_product/__openerp__.py @@ -3,7 +3,7 @@ # # Intrastat Product module for Odoo # Copyright (C) 2011-2015 Akretion (http://www.akretion.com) -# Copyright (C) 2015 Noviat (http://www.noviat.com) +# Copyright (C) 2009-2015 Noviat (http://www.noviat.com) # @author Alexis de Lattre # @author Luc de Meyer # @@ -24,7 +24,7 @@ { 'name': 'Intrastat Product', - 'version': '1.3', + 'version': '1.4', 'category': 'Intrastat', 'license': 'AGPL-3', 'summary': 'Base module for Intrastat Product', @@ -36,16 +36,21 @@ ], 'conflicts': ['report_intrastat'], 'data': [ - 'intrastat_view.xml', - 'intrastat_declaration_view.xml', - 'res_company_view.xml', - 'account_invoice_view.xml', - 'stock_view.xml', + 'views/hs_code.xml', + 'views/intrastat_region.xml', + 'views/intrastat_unit.xml', + 'views/intrastat_transaction.xml', + 'views/intrastat_transport_mode.xml', + 'views/intrastat_product_declaration.xml', + 'views/res_company.xml', + 'views/account_invoice.xml', + 'views/stock_picking.xml', + 'views/stock_warehouse.xml', 'security/intrastat_security.xml', 'security/ir.model.access.csv', 'data/intrastat_transport_mode.xml', 'data/intrastat_unit.xml', ], - 'demo': ['intrastat_demo.xml'], + 'demo': ['demo/intrastat_demo.xml'], 'installable': True, } diff --git a/intrastat_product/intrastat_demo.xml b/intrastat_product/demo/intrastat_demo.xml similarity index 100% rename from intrastat_product/intrastat_demo.xml rename to intrastat_product/demo/intrastat_demo.xml diff --git a/intrastat_product/intrastat.py b/intrastat_product/intrastat.py deleted file mode 100644 index b87953a..0000000 --- a/intrastat_product/intrastat.py +++ /dev/null @@ -1,122 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Intrastat Product module for Odoo -# Copyright (C) 2011-2015 Akretion (http://www.akretion.com) -# Copyright (C) 2015 Noviat (http://www.noviat.com) -# @author Alexis de Lattre -# @author Luc de Meyer -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp import models, fields, api, _ -from openerp.exceptions import ValidationError - - -class IntrastatUnit(models.Model): - _name = 'intrastat.unit' - _description = 'Intrastat Supplementary Units' - - name = fields.Char( - string='Name', required=True) - description = fields.Char( - string='Description', required=True) - uom_id = fields.Many2one( - 'product.uom', string='Regular UoM', - help="Select the regular Unit of Measure of Odoo that corresponds " - "to this Intrastat Supplementary Unit.") - active = fields.Boolean( - string='Active', default=True) - - -class HSCode(models.Model): - _inherit = "hs.code" - - intrastat_unit_id = fields.Many2one( - 'intrastat.unit', string='Intrastat Supplementary Unit') - - @api.constrains('local_code') - def _hs_code(self): - if self.company_id.country_id.intrastat: - if not self.local_code.isdigit(): - raise ValidationError( - _("Intrastat Codes should only contain digits. " - "This is not the case for code '%s'.") - % self.local_code) - if len(self.local_code) != 8: - raise ValidationError( - _("Intrastat Codes should " - "contain 8 digits. This is not the case for " - "Intrastat Code '%s' which has %d digits.") - % (self.local_code, len(self.local_code))) - - -class IntrastatTransaction(models.Model): - _name = 'intrastat.transaction' - _description = "Intrastat Transaction" - _order = 'code' - _rec_name = 'display_name' - - @api.one - @api.depends('code', 'description') - def _compute_display_name(self): - display_name = self.code - if self.description: - display_name += ' ' + self.description - self.display_name = len(display_name) > 55 \ - and display_name[:55] + '...' \ - or display_name - - code = fields.Char(string='Code', required=True) - description = fields.Text(string='Description') - display_name = fields.Char( - compute='_compute_display_name', string="Display Name", readonly=True) - company_id = fields.Many2one( - 'res.company', string='Company', - default=lambda self: self.env['res.company']._company_default_get( - 'intrastat.transaction')) - - _sql_constraints = [( - 'intrastat_transaction_code_unique', - 'UNIQUE(code, company_id)', - 'Code must be unique.')] - - -class IntrastatTransportMode(models.Model): - _name = 'intrastat.transport_mode' - _description = "Intrastat Transport Mode" - _rec_name = 'display_name' - _order = 'code' - - @api.one - @api.depends('name', 'code') - def _display_name(self): - print "display_name self=", self - print "self.code=", self.code - print "self.name=", self.name - self.display_name = '%s. %s' % (self.code, self.name) - - display_name = fields.Char( - string='Display Name', compute='_display_name', store=True, - readonly=True) - code = fields.Char(string='Code', required=True) - name = fields.Char(string='Name', required=True, translate=True) - description = fields.Char(string='Description', translate=True) - - _sql_constraints = [( - 'intrastat_transport_code_unique', - 'UNIQUE(code)', - 'Code must be unique.')] diff --git a/intrastat_product/intrastat_view.xml b/intrastat_product/intrastat_view.xml deleted file mode 100644 index c61fc61..0000000 --- a/intrastat_product/intrastat_view.xml +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - - - - - - - intrastat.hs.code.tree - hs.code - - - - - - - - - - - intrastat.hs.code.form - hs.code - - - - - - - - - - - intrastat.unit.form - intrastat.unit - -
- - - - - - -
-
-
- - - intrastat.unit.tree - intrastat.unit - - - - - - - - - - - intrastat.unit.search - intrastat.unit - - - - - - - - - - - - - Supplementary Units - intrastat.unit - tree,form - - - - - - - intrastat.transaction_form - intrastat.transaction - -
- - - - - -
-
-
- - - intrastat.transaction_tree - intrastat.transaction - - - - - - - - - - - intrastat.transaction.mode.search - intrastat.transaction - - - - - - - - - - - - Transaction Types - intrastat.transaction - tree,form - - - - - - - - intrastat.transport.mode.form - intrastat.transport_mode - -
- - - - - -
-
-
- - - intrastat.transport.mode.tree - intrastat.transport_mode - - - - - - - - - - - intrastat.transport.mode.search - intrastat.transport_mode - - - - - - - - - Transport Modes - intrastat.transport_mode - tree,form - - - - -
-
diff --git a/intrastat_product/models/__init__.py b/intrastat_product/models/__init__.py new file mode 100644 index 0000000..66c0d7b --- /dev/null +++ b/intrastat_product/models/__init__.py @@ -0,0 +1,11 @@ +# -*- encoding: utf-8 -*- +from . import account_invoice +from . import hs_code +from . import intrastat_product_declaration +from . import intrastat_region +from . import intrastat_transaction +from . import intrastat_transport_mode +from . import intrastat_unit +from . import res_company +from . import stock_picking +from . import stock_warehouse diff --git a/intrastat_product/account_invoice.py b/intrastat_product/models/account_invoice.py similarity index 81% rename from intrastat_product/account_invoice.py rename to intrastat_product/models/account_invoice.py index 3179012..74f713a 100644 --- a/intrastat_product/account_invoice.py +++ b/intrastat_product/models/account_invoice.py @@ -1,10 +1,11 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Copyright (c) 2012-2015 Noviat nv/sa (www.noviat.com) -# Copyright (C) 2015 Akretion (http://www.akretion.com) -# @author Luc de Meyer +# Intrastat Product module for Odoo +# Copyright (C) 2011-2015 Akretion (http://www.akretion.com) +# Copyright (C) 2009-2015 Noviat (http://www.noviat.com) # @author Alexis de Lattre +# @author Luc de Meyer # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -13,11 +14,11 @@ # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see . # ############################################################################## @@ -27,14 +28,14 @@ from openerp import models, fields, api class AccountInvoice(models.Model): _inherit = 'account.invoice' - @api.model - def _default_intrastat_transaction(self): - """ placeholder for localisation modules """ - return self.env['intrastat.transaction'].browse([]) - + incoterm_id = fields.Many2one( + 'stock.incoterms', string='Incoterm', + help="International Commercial Terms are a series of predefined " + "commercial terms used in international transactions.") intrastat_transaction_id = fields.Many2one( 'intrastat.transaction', string='Intrastat Transaction Type', - default=_default_intrastat_transaction, ondelete='restrict', + default=lambda self: self._default_intrastat_transaction(), + ondelete='restrict', help="Intrastat nature of transaction") intrastat_transport_id = fields.Many2one( 'intrastat.transport_mode', string='Intrastat Transport Mode', @@ -49,6 +50,11 @@ class AccountInvoice(models.Model): string='Intrastat Declaration', related='company_id.intrastat', store=True, readonly=True) + @api.model + def _default_intrastat_transaction(self): + """ placeholder for localisation modules """ + return self.env['intrastat.transaction'].browse([]) + @api.multi def onchange_partner_id( self, type, partner_id, date_invoice=False, @@ -82,7 +88,9 @@ class AccountInvoiceLine(models.Model): if product: product = self.env['product.product'].browse(product) - hs_code = product.get_hs_code_recursively() + hs_code = product.product_tmpl_id.get_hs_code_recursively() if hs_code: res['value']['hs_code_id'] = hs_code.id + else: + res['value']['hs_code_id'] = False return res diff --git a/intrastat_product/models/hs_code.py b/intrastat_product/models/hs_code.py new file mode 100644 index 0000000..6e23770 --- /dev/null +++ b/intrastat_product/models/hs_code.py @@ -0,0 +1,48 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Intrastat Product module for Odoo +# Copyright (C) 2011-2015 Akretion (http://www.akretion.com) +# Copyright (C) 2009-2015 Noviat (http://www.noviat.com) +# @author Alexis de Lattre +# @author Luc de Meyer +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields, api, _ +from openerp.exceptions import ValidationError + + +class HSCode(models.Model): + _inherit = "hs.code" + + intrastat_unit_id = fields.Many2one( + 'intrastat.unit', string='Intrastat Supplementary Unit') + + @api.constrains('local_code') + def _hs_code(self): + if self.company_id.country_id.intrastat: + if not self.local_code.isdigit(): + raise ValidationError( + _("Intrastat Codes should only contain digits. " + "This is not the case for code '%s'.") + % self.local_code) + if len(self.local_code) != 8: + raise ValidationError( + _("Intrastat Codes should " + "contain 8 digits. This is not the case for " + "Intrastat Code '%s' which has %d digits.") + % (self.local_code, len(self.local_code))) diff --git a/intrastat_product/intrastat_declaration.py b/intrastat_product/models/intrastat_product_declaration.py similarity index 87% rename from intrastat_product/intrastat_declaration.py rename to intrastat_product/models/intrastat_product_declaration.py index 9f4f731..4dfc52b 100644 --- a/intrastat_product/intrastat_declaration.py +++ b/intrastat_product/models/intrastat_product_declaration.py @@ -3,7 +3,9 @@ # # Intrastat Product module for Odoo # Copyright (C) 2011-2015 Akretion (http://www.akretion.com) -# Copyright (C) 2011-2015 Noviat (http://www.noviat.com) +# Copyright (C) 2009-2015 Noviat (http://www.noviat.com) +# @author Alexis de Lattre +# @author Luc de Meyer # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -21,12 +23,11 @@ ############################################################################## from openerp import models, fields, api, _ -from openerp.exceptions import Warning, RedirectWarning, ValidationError +from openerp.exceptions import RedirectWarning, ValidationError, Warning import openerp.addons.decimal_precision as dp from datetime import datetime, date from dateutil.relativedelta import relativedelta import logging - _logger = logging.getLogger(__name__) @@ -105,6 +106,10 @@ class IntrastatProductDeclaration(models.Model): 'res.company', string='Company', readonly=True, default=lambda self: self.env['res.company']._company_default_get( 'intrastat.product.declaration')) + 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.") year = fields.Integer( string='Year', required=True, default=_get_year) @@ -186,12 +191,19 @@ class IntrastatProductDeclaration(models.Model): _sql_constraints = [ ('date_uniq', - 'unique(year_month, company_id, type)', + 'unique(year_month, company_id, type, revision)', "A declaration of the same type already exists for this month !" "\nYou should update the existing declaration " "or change the revision number of this one."), ] + @api.one + @api.depends('company_id') + def _compute_company_country_code(self): + if self.company_id: + self.company_country_code = \ + self.company_id.country_id.code.lower() + @api.one @api.depends('year', 'month') def _compute_year_month(self): @@ -219,7 +231,7 @@ class IntrastatProductDeclaration(models.Model): _('Go to company configuration screen')) def _get_partner_country(self, inv_line): - country = inv_line.invoice_id.intrastat_country_id \ + country = inv_line.invoice_id.src_dest_country_id \ or inv_line.invoice_id.partner_id.country_id if not country.intrastat: country = False @@ -228,53 +240,13 @@ class IntrastatProductDeclaration(models.Model): return country def _get_intrastat_transaction(self, inv_line): - if inv_line.invoice_id.intrastat_transaction_id: - tr = inv_line.invoice_id.intrastat_transaction_id.code - else: - tr = self.env.ref( - 'l10n_be_intrastat_advanced.intrastat_transaction_1') - return tr - - def _get_region(self, inv_line): - """ - Logic copied from standard addons, l10n_be_intrastat module: - If purchase, comes from purchase order, linked to a location, - which is linked to the warehouse. - - If sales, the sale order is linked to the warehouse. - If sales, from a delivery order, linked to a location, - which is linked to the warehouse. - If none found, get the company one. - """ - region = False - if inv_line.invoice_id.type in ('in_invoice', 'in_refund'): - po_lines = self.env['purchase.order.line'].search( - [('invoice_lines', 'in', inv_line.id)]) - if po_lines: - po = po_lines.order_id - region = self.env['stock.warehouse'].get_region_from_location( - po.location_id) - elif inv_line.invoice_id.type in ('out_invoice', 'out_refund'): - so_lines = self.env['sale.order.line'].search( - [('invoice_lines', 'in', inv_line.id)]) - if so_lines: - so = so_lines.order_id - region = so.warehouse_id.region_id - if not region: - if self.company_id.intrastat_region_id: - region = self.company_id.intrastat_region_id - else: - msg = _( - "The Intrastat Region of the Company is not set, " - "please configure it first.") - self._company_warning(msg) - return region + return inv_line.invoice_id.intrastat_transaction_id def _get_weight_and_supplunits(self, inv_line): line_qty = inv_line.quantity product = inv_line.product_id invoice = inv_line.invoice_id - intrastat_unit_id = inv_line.intrastat_id.intrastat_unit_id + intrastat_unit_id = inv_line.hs_code_id.intrastat_unit_id source_uom = inv_line.uos_id weight_uom_categ = self._uom_refs['weight_uom_categ'] kg_uom = self._uom_refs['kg_uom'] @@ -303,10 +275,10 @@ class IntrastatProductDeclaration(models.Model): "Please correct the Intrastat Supplementary Unit " "settingsand regenerate the lines or adjust the lines " "with Intrastat Code '%s' manually" - ) % intrastat_code + ) % inv_line.hs_code_id.local_code self._note += note return weight, suppl_unit_qty - if target_uom.categ_id == source_uom.category_id: + if target_uom.category_id == source_uom.category_id: suppl_unit_qty = self.env['product.uom']._compute_qty_obj( source_uom, line_qty, target_uom) else: @@ -370,8 +342,41 @@ class IntrastatProductDeclaration(models.Model): amount) return amount + def _get_region(self, inv_line): + """ + Logic copied from standard addons, l10n_be_intrastat module: + + If purchase, comes from purchase order, linked to a location, + which is linked to the warehouse. + + If sales, the sale order is linked to the warehouse. + If sales, from a delivery order, linked to a location, + which is linked to the warehouse. + + If none found, get the company one. + """ + region = False + if inv_line.invoice_id.type in ('in_invoice', 'in_refund'): + po_lines = self.env['purchase.order.line'].search( + [('invoice_lines', 'in', inv_line.id)]) + if po_lines: + po = po_lines.order_id + region = self.env['stock.warehouse'].get_region_from_location( + po.location_id) + elif inv_line.invoice_id.type in ('out_invoice', 'out_refund'): + so_lines = self.env['sale.order.line'].search( + [('invoice_lines', 'in', inv_line.id)]) + if so_lines: + so = so_lines.order_id + region = so.warehouse_id.region_id + if not region: + if self.company_id.intrastat_region_id: + region = self.company_id.intrastat_region_id + return region + + def _get_transport(self, inv_line): - transport = inv_line.invoice.transport_mode_id \ + transport = inv_line.invoice_id.intrastat_transport_id \ or self.company_id.intrastat_transport_id if not transport: msg = _( @@ -382,8 +387,8 @@ class IntrastatProductDeclaration(models.Model): return transport def _get_incoterm(self, inv_line): - incoterm = inv_line.invoice.incoterm_id \ - or self.company_id.incoterm_id + incoterm = inv_line.invoice_id.incoterm_id \ + or self.company_id.intrastat_incoterm_id if not incoterm: msg = _( "The default Incoterm " @@ -392,9 +397,13 @@ class IntrastatProductDeclaration(models.Model): self._company_warning(msg) return incoterm + def _update_computation_line_vals(self, inv_line, line_vals): + """ placeholder for localization modules """ + pass + def _gather_invoices(self): - decl_lines = [] + lines = [] start_date = date(self.year, self.month, 1) end_date = start_date + relativedelta(day=1, months=+1, days=-1) @@ -416,7 +425,7 @@ class IntrastatProductDeclaration(models.Model): for inv_line in invoice.invoice_line: - intrastat = inv_line.intrastat_id + intrastat = inv_line.hs_code_id if not intrastat: continue if not inv_line.quantity: @@ -429,8 +438,6 @@ class IntrastatProductDeclaration(models.Model): intrastat_transaction = \ self._get_intrastat_transaction(inv_line) - region = self._get_region(inv_line) - weight, suppl_unit_qty = self._get_weight_and_supplunits( inv_line) @@ -439,33 +446,32 @@ class IntrastatProductDeclaration(models.Model): line_vals = { 'parent_id': self.id, 'invoice_line_id': inv_line.id, - 'partner_country_id': partner_country.id, + 'src_dest_country_id': partner_country.id, 'product_id': inv_line.product_id.id, - 'intrastat_code_id': intrastat.id, + 'hs_code_id': intrastat.id, 'weight': weight, 'suppl_unit_qty': suppl_unit_qty, 'amount_company_currency': amount_company_currency, 'transaction_id': intrastat_transaction.id, - 'region_id': region.id, - 'extended': self._extended, } # extended declaration if self._extended: transport = self._get_transport(inv_line) - incoterm = self._get_incoterm(inv_line) line_vals.update({ 'transport_id': transport.id, - 'incoterm_id': incoterm.id, }) - decl_lines.append((0, 0, line_vals)) + self._update_computation_line_vals(inv_line, line_vals) - return decl_lines + lines.append((line_vals)) + + return lines @api.multi def action_gather(self): self.ensure_one() + self._check_generate_lines() self._note = '' self._uom_refs = { 'weight_uom_categ': self.env.ref('product.product_uom_categ_kgm'), @@ -482,27 +488,23 @@ class IntrastatProductDeclaration(models.Model): else: self._extended = False - decl_lines_init = [(6, 0, [])] - decl_lines = decl_lines_init[:] + self.computation_line_ids.unlink() + lines = self._gather_invoices() - decl_lines += self._gather_invoices() - - if decl_lines == decl_lines_init: + if not lines: self.action = 'nihil' note = "\n" + \ _("No records found for the selected period !") + '\n' + \ _("The Declaration Action has been set to 'nihil'.") self._note += note - - # To DO: add check on tax cases 46, 48, 84, 86 - - self.write({'intrastat_line_ids': decl_lines}) + else: + self.write({'computation_line_ids': [(0, 0, x) for x in lines]}) if self._note: note_header = '\n\n>>> ' + str(date.today()) + '\n' - self.note = (self.note or '') + note_header + self._note + self.note = note_header + self._note + (self.note or '') result_view = self.env.ref( - 'l10n_be_intrastat_advanced.intrastat_result_view') + 'intrastat_base.intrastat_result_view_form') return { 'name': _("Generate lines from invoices: results"), 'view_type': 'form', @@ -518,12 +520,13 @@ class IntrastatProductDeclaration(models.Model): @api.model def group_line_hashcode(self, computation_line): - hashcode = "%s-%s-%s-%s-%s" % ( + hashcode = "%s-%s-%s-%s-%s-%s" % ( computation_line.src_dest_country_id.id or False, - computation_line.hs_code or False, + computation_line.hs_code_id.id or False, computation_line.intrastat_unit_id.id or False, computation_line.transaction_id.id or False, - computation_line.transport_id.id or False + computation_line.transport_id.id or False, + computation_line.region_id.id or False ) return hashcode @@ -542,13 +545,38 @@ class IntrastatProductDeclaration(models.Model): dl_group[hashcode].append(cl) else: dl_group[hashcode] = [cl] - ipdlo = self.pool['intrastat.product.declaration.line'] + ipdl = self.declaration_line_ids for cl_lines in dl_group.values(): - vals = ipdlo._prepare_declaration_line(cl_lines) - declaration_line = ipdlo.create(vals) - cl_lines.write({'declaration_line_id': declaration_line.id}) + vals = ipdl._prepare_declaration_line(cl_lines) + declaration_line = ipdl.create(vals) + for cl in cl_lines: + cl.write({'declaration_line_id': declaration_line.id}) return True + @api.multi + def generate_xml(self): + """ generate the INTRASTAT Declaration XML file """ + self.ensure_one() + self._check_generate_xml() + self._unlink_attachments() + xml_string = self._generate_xml() + if xml_string: + attach_id = self._attach_xml_file( + xml_string, '%s_%s' % (self.type, self.revision)) + return self._open_attach_view(attach_id) + else: + raise Warning( + _("Programming Error."), + _("No XML File has been generated.")) + + @api.multi + def done(self): + self.write({'state': 'done'}) + + @api.multi + def back2draft(self): + self.write({'state': 'draft'}) + class IntrastatProductComputationLine(models.Model): _name = 'intrastat.product.computation.line' @@ -612,7 +640,11 @@ class IntrastatProductComputationLine(models.Model): transaction_id = fields.Many2one( 'intrastat.transaction', string='Intrastat Transaction') + region_id = fields.Many2one( + 'intrastat.region', string='Intrastat Region') # extended declaration + incoterm_id = fields.Many2one( + 'stock.incoterms', string='Incoterm') transport_id = fields.Many2one( 'intrastat.transport_mode', string='Transport Mode') @@ -686,17 +718,21 @@ class IntrastatProductDeclarationLine(models.Model): transaction_id = fields.Many2one( 'intrastat.transaction', string='Intrastat Transaction') + region_id = fields.Many2one( + 'intrastat.region', string='Intrastat Region') # extended declaration + incoterm_id = fields.Many2one( + 'stock.incoterms', string='Incoterm') transport_id = fields.Many2one( 'intrastat.transport_mode', string='Transport Mode') @api.model - def _prepare_grouped_fields(computation_line, fields_to_sum): + def _prepare_grouped_fields(self, computation_line, fields_to_sum): vals = { 'src_dest_country_id': computation_line.src_dest_country_id.id, 'intrastat_unit_id': computation_line.intrastat_unit_id.id, - 'hs_code': computation_line.hs_code_id.local_code, + 'hs_code_id': computation_line.hs_code_id.id, 'transaction_id': computation_line.transaction_id.id, 'transport_id': computation_line.transport_id.id, 'parent_id': computation_line.parent_id.id, @@ -705,7 +741,7 @@ class IntrastatProductDeclarationLine(models.Model): vals[field] = 0.0 return vals - def _fields_to_sum(): + def _fields_to_sum(self): fields_to_sum = [ 'weight', 'suppl_unit_qty', diff --git a/intrastat_product/models/intrastat_region.py b/intrastat_product/models/intrastat_region.py new file mode 100644 index 0000000..3d1333e --- /dev/null +++ b/intrastat_product/models/intrastat_region.py @@ -0,0 +1,43 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Odoo, Open Source Management Solution +# +# Copyright (c) 2009-2015 Noviat nv/sa (www.noviat.com). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields + + +class IntrastatRegion(models.Model): + _name = 'intrastat.region' + _description = "Intrastat Region" + + code = fields.Char(string='Code', required=True) + country_id = fields.Many2one( + 'res.country', string='Country', required=True) + name = fields.Char(string='Name', translate=True) + description = fields.Char(string='Description') + company_id = fields.Many2one( + 'res.company', string='Company', + default=lambda self: self.env['res.company']._company_default_get( + 'intrastat.region')) + + _sql_constraints = [ + ('intrastat_region_code_unique', + 'UNIQUE(code, country_id)', + 'Code must be unique.')] diff --git a/intrastat_product/models/intrastat_transaction.py b/intrastat_product/models/intrastat_transaction.py new file mode 100644 index 0000000..3734fa6 --- /dev/null +++ b/intrastat_product/models/intrastat_transaction.py @@ -0,0 +1,56 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Intrastat Product module for Odoo +# Copyright (C) 2011-2015 Akretion (http://www.akretion.com) +# Copyright (C) 2009-2015 Noviat (http://www.noviat.com) +# @author Alexis de Lattre +# @author Luc de Meyer +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields, api + + +class IntrastatTransaction(models.Model): + _name = 'intrastat.transaction' + _description = "Intrastat Transaction" + _order = 'code' + _rec_name = 'display_name' + + code = fields.Char(string='Code', required=True) + description = fields.Text(string='Description') + display_name = fields.Char( + compute='_compute_display_name', string="Display Name", readonly=True) + company_id = fields.Many2one( + 'res.company', string='Company', + default=lambda self: self.env['res.company']._company_default_get( + 'intrastat.transaction')) + + @api.one + @api.depends('code', 'description') + def _compute_display_name(self): + display_name = self.code + if self.description: + display_name += ' ' + self.description + self.display_name = len(display_name) > 55 \ + and display_name[:55] + '...' \ + or display_name + + _sql_constraints = [( + 'intrastat_transaction_code_unique', + 'UNIQUE(code, company_id)', + 'Code must be unique.')] diff --git a/intrastat_product/models/intrastat_transport_mode.py b/intrastat_product/models/intrastat_transport_mode.py new file mode 100644 index 0000000..6157459 --- /dev/null +++ b/intrastat_product/models/intrastat_transport_mode.py @@ -0,0 +1,49 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Intrastat Product module for Odoo +# Copyright (C) 2011-2015 Akretion (http://www.akretion.com) +# Copyright (C) 2009-2015 Noviat (http://www.noviat.com) +# @author Alexis de Lattre +# @author Luc de Meyer +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields, api + + +class IntrastatTransportMode(models.Model): + _name = 'intrastat.transport_mode' + _description = "Intrastat Transport Mode" + _rec_name = 'display_name' + _order = 'code' + + display_name = fields.Char( + string='Display Name', compute='_display_name', store=True, + readonly=True) + code = fields.Char(string='Code', required=True) + name = fields.Char(string='Name', required=True, translate=True) + description = fields.Char(string='Description', translate=True) + + @api.one + @api.depends('name', 'code') + def _display_name(self): + self.display_name = '%s. %s' % (self.code, self.name) + + _sql_constraints = [( + 'intrastat_transport_code_unique', + 'UNIQUE(code)', + 'Code must be unique.')] diff --git a/intrastat_product/models/intrastat_unit.py b/intrastat_product/models/intrastat_unit.py new file mode 100644 index 0000000..65a86f2 --- /dev/null +++ b/intrastat_product/models/intrastat_unit.py @@ -0,0 +1,41 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Intrastat Product module for Odoo +# Copyright (C) 2011-2015 Akretion (http://www.akretion.com) +# Copyright (C) 2009-2015 Noviat (http://www.noviat.com) +# @author Alexis de Lattre +# @author Luc de Meyer +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields + + +class IntrastatUnit(models.Model): + _name = 'intrastat.unit' + _description = 'Intrastat Supplementary Units' + + name = fields.Char( + string='Name', required=True) + description = fields.Char( + string='Description', required=True) + uom_id = fields.Many2one( + 'product.uom', string='Regular UoM', + help="Select the regular Unit of Measure of Odoo that corresponds " + "to this Intrastat Supplementary Unit.") + active = fields.Boolean( + string='Active', default=True) diff --git a/intrastat_product/res_company.py b/intrastat_product/models/res_company.py similarity index 76% rename from intrastat_product/res_company.py rename to intrastat_product/models/res_company.py index 65e0e3f..f3d4c9b 100644 --- a/intrastat_product/res_company.py +++ b/intrastat_product/models/res_company.py @@ -1,10 +1,11 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Copyright (c) 2012-2015 Noviat nv/sa (www.noviat.com) -# Copyright (C) 2015 Akretion (http://www.akretion.com) -# @author Luc de Meyer +# Intrastat Product module for Odoo +# Copyright (C) 2011-2015 Akretion (http://www.akretion.com) +# Copyright (C) 2009-2015 Noviat (http://www.noviat.com) # @author Alexis de Lattre +# @author Luc de Meyer # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -13,11 +14,11 @@ # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see . # ############################################################################## @@ -27,6 +28,28 @@ from openerp import models, fields, api class ResCompany(models.Model): _inherit = 'res.company' + intrastat_incoterm_id = fields.Many2one( + 'stock.incoterms', + string='Default incoterm for Intrastat', + help="International Commercial Terms are a series of " + "predefined commercial terms used in international " + "transactions.") + intrastat_arrivals = fields.Selection( + '_intrastat_arrivals', string='Arrivals', + default='extended', required=True) + intrastat_dispatches = fields.Selection( + '_intrastat_arrivals', string='Dispatches', + default='extended', required=True) + intrastat_transport_id = fields.Many2one( + 'intrastat.transport_mode', + string='Default Transport Mode', ondelete='restrict') + intrastat = fields.Char( + string='Intrastat Declaration', store=True, readonly=True, + compute='_compute_intrastat') + intrastat_region_id = fields.Many2one( + 'intrastat.region', + string='Default Intrastat region') + @api.model def _intrastat_arrivals(self): return [ @@ -52,16 +75,3 @@ class ResCompany(models.Model): self.intrastat = 'extended' else: self.intrastat = 'standard' - - intrastat_arrivals = fields.Selection( - '_intrastat_arrivals', string='Arrivals', - default='extended', required=True) - intrastat_dispatches = fields.Selection( - '_intrastat_arrivals', string='Dispatches', - default='extended', required=True) - intrastat_transport_id = fields.Many2one( - 'intrastat.transport_mode', - string='Default Transport Mode', ondelete='restrict') - intrastat = fields.Char( - string='Intrastat Declaration', store=True, readonly=True, - compute='_compute_intrastat') diff --git a/intrastat_product/stock.py b/intrastat_product/models/stock_picking.py similarity index 89% rename from intrastat_product/stock.py rename to intrastat_product/models/stock_picking.py index c97cf75..db97f5b 100644 --- a/intrastat_product/stock.py +++ b/intrastat_product/models/stock_picking.py @@ -1,8 +1,11 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Copyright (C) 2010-2015 Akretion (http://www.akretion.com) +# Intrastat Product module for Odoo +# Copyright (C) 2011-2015 Akretion (http://www.akretion.com) +# Copyright (C) 2009-2015 Noviat (http://www.noviat.com) # @author Alexis de Lattre +# @author Luc de Meyer # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as diff --git a/intrastat_product/models/stock_warehouse.py b/intrastat_product/models/stock_warehouse.py new file mode 100644 index 0000000..d766b61 --- /dev/null +++ b/intrastat_product/models/stock_warehouse.py @@ -0,0 +1,42 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Odoo, Open Source Management Solution +# +# Copyright (c) 2009-2015 Noviat nv/sa (www.noviat.com). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields + + +class StockWarehouse(models.Model): + _inherit = 'stock.warehouse' + + region_id = fields.Many2one( + 'intrastat.region', + string='Intrastat region') + + def get_region_from_location(self, location): + locations = location.search( + [('parent_left', '<=', location.parent_left), + ('parent_right', '>=', location.parent_right)]) + warehouses = self.search( + [('lot_stock_id', 'in', [x.id for x in locations]), + ('region_id', '!=', False)]) + if warehouses: + return warehouses[0].region_id + return None diff --git a/intrastat_product/security/intrastat_security.xml b/intrastat_product/security/intrastat_security.xml index cd4f161..e483225 100644 --- a/intrastat_product/security/intrastat_security.xml +++ b/intrastat_product/security/intrastat_security.xml @@ -8,5 +8,11 @@ ['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])] + + Intrastat Region Company rule + + ['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])] + + diff --git a/intrastat_product/security/ir.model.access.csv b/intrastat_product/security/ir.model.access.csv index bd6835f..4b06ab2 100644 --- a/intrastat_product/security/ir.model.access.csv +++ b/intrastat_product/security/ir.model.access.csv @@ -5,6 +5,8 @@ access_intrastat_transaction_read,Read access on Intrastat Transaction Types to access_intrastat_transaction_full,Full access on Intrastat Transaction Types to Finance manager,model_intrastat_transaction,account.group_account_manager,1,1,1,1 access_intrastat_transport_mode_read,Read access on Intrastat Transport Modes to everybody,model_intrastat_transport_mode,,1,0,0,0 access_intrastat_transport_mode_full,Full access on Intrastat Transport Modes to Finance manager,model_intrastat_transport_mode,account.group_account_manager,1,1,1,1 +access_intrastat_region_read,Read access on Intrastat Regions,model_intrastat_region,,1,0,0,0 +access_intrastat_region_full,Full access on Intrastat Regions,model_intrastat_region,account.group_account_manager,1,1,1,1 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 diff --git a/intrastat_product/account_invoice_view.xml b/intrastat_product/views/account_invoice.xml similarity index 82% rename from intrastat_product/account_invoice_view.xml rename to intrastat_product/views/account_invoice.xml index cccb557..709ebbb 100644 --- a/intrastat_product/account_invoice_view.xml +++ b/intrastat_product/views/account_invoice.xml @@ -7,6 +7,10 @@ account.invoice + + + @@ -26,6 +30,10 @@ account.invoice + + + diff --git a/intrastat_product/views/hs_code.xml b/intrastat_product/views/hs_code.xml new file mode 100644 index 0000000..f6e54f2 --- /dev/null +++ b/intrastat_product/views/hs_code.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + intrastat.hs.code.tree + hs.code + + + + + + + + + + + intrastat.hs.code.form + hs.code + + + + + + + + + + diff --git a/intrastat_product/intrastat_declaration_view.xml b/intrastat_product/views/intrastat_product_declaration.xml similarity index 82% rename from intrastat_product/intrastat_declaration_view.xml rename to intrastat_product/views/intrastat_product_declaration.xml index 100eb93..935a158 100644 --- a/intrastat_product/intrastat_declaration_view.xml +++ b/intrastat_product/views/intrastat_product_declaration.xml @@ -2,7 +2,7 @@ - + intrastat.product.declaration.form intrastat.product.declaration @@ -12,7 +12,13 @@ attrs="{'invisible': ['|', ('state', '!=', 'draft'), ('action', '=', 'nihil')]}" string="Generate lines from invoices" class="oe_highlight"/> -