From f0c45fbc67d3acb7096755f2085dba9a7e842f80 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Sun, 19 Jul 2015 14:24:56 +0200 Subject: [PATCH] Large code re-engineering following the Akretion-Noviat code sprint on intrastat This code has been written both by Luc de Meyer and myself. --- product_harmonized_system/README.rst | 48 ++++++ product_harmonized_system/__init__.py | 4 + product_harmonized_system/__openerp__.py | 41 +++++ product_harmonized_system/hs.py | 85 ++++++++++ product_harmonized_system/hs_view.xml | 67 ++++++++ product_harmonized_system/i18n/fr.po | 156 ++++++++++++++++++ .../i18n/product_harmonized_system.pot | 156 ++++++++++++++++++ product_harmonized_system/product.py | 73 ++++++++ product_harmonized_system/product_demo.xml | 92 +++++++++++ product_harmonized_system/product_view.xml | 40 +++++ .../security/ir.model.access.csv | 3 + .../security/product_hs_security.xml | 12 ++ 12 files changed, 777 insertions(+) create mode 100644 product_harmonized_system/README.rst create mode 100644 product_harmonized_system/__init__.py create mode 100644 product_harmonized_system/__openerp__.py create mode 100644 product_harmonized_system/hs.py create mode 100644 product_harmonized_system/hs_view.xml create mode 100644 product_harmonized_system/i18n/fr.po create mode 100644 product_harmonized_system/i18n/product_harmonized_system.pot create mode 100644 product_harmonized_system/product.py create mode 100644 product_harmonized_system/product_demo.xml create mode 100644 product_harmonized_system/product_view.xml create mode 100644 product_harmonized_system/security/ir.model.access.csv create mode 100644 product_harmonized_system/security/product_hs_security.xml diff --git a/product_harmonized_system/README.rst b/product_harmonized_system/README.rst new file mode 100644 index 0000000..52304f1 --- /dev/null +++ b/product_harmonized_system/README.rst @@ -0,0 +1,48 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :alt: License + +Harmonized System Codes (and National Codes) +============================================ + +This module contains the objects for Harmonised System Codes (H.S. codes). The full nomenclature is available from the `World Customs Organisation `. These code are usually required on the Proforma invoices that are attached to the packages that are shipped abroad. + +This module also handle the local/national extensions to the H.S. codes. The import of the full nomenclature is not provided by this module ; it should be provided by localization modules. + +You will also be able to configure the country of origin of a product, which is often required on the proforma invoice for the customs. + +This module should be usefull for all companies that export physical goods abroad. This module is also used by the Intrastat modules for the European Union, cf the *intrastat_product* module. + +Installation +============ + +This module is NOT compatible with the *report_intrastat* module from the official addons. + +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*). + +Credits +======= + +Author +------- + +* 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. + +To contribute to this module, please visit http://odoo-community.org. diff --git a/product_harmonized_system/__init__.py b/product_harmonized_system/__init__.py new file mode 100644 index 0000000..a64ddf0 --- /dev/null +++ b/product_harmonized_system/__init__.py @@ -0,0 +1,4 @@ +# -*- encoding: utf-8 -*- + +from . import hs +from . import product diff --git a/product_harmonized_system/__openerp__.py b/product_harmonized_system/__openerp__.py new file mode 100644 index 0000000..3575e46 --- /dev/null +++ b/product_harmonized_system/__openerp__.py @@ -0,0 +1,41 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# 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 . +# +############################################################################## + +{ + 'name': 'Product Harmonized System Codes', + 'version': '0.1', + 'category': 'Reporting', + 'license': 'AGPL-3', + 'summary': 'Base module for Product Import/Export reports', + 'author': 'Akretion, Noviat, Odoo Community Association (OCA)', + 'depends': ['product'], + 'conflicts': ['report_intrastat'], + 'data': [ + 'product_view.xml', + 'hs_view.xml', + 'security/product_hs_security.xml', + 'security/ir.model.access.csv', + ], + 'demo': ['product_demo.xml'], + 'installable': True, +} diff --git a/product_harmonized_system/hs.py b/product_harmonized_system/hs.py new file mode 100644 index 0000000..ea1e007 --- /dev/null +++ b/product_harmonized_system/hs.py @@ -0,0 +1,85 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# 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 + + +class HSCode(models.Model): + _name = "hs.code" + _description = "H.S. Code" + _order = "local_code" + _rec_name = "display_name" + + @api.one + @api.depends('local_code') + def _get_hs_code(self): + self.hs_code = self.local_code and self.local_code[:6] + + @api.one + @api.depends('local_code', 'description') + def _compute_display_name(self): + display_name = self.local_code + if self.description: + display_name += ' ' + self.description + self.display_name = display_name > 55 \ + and display_name[:55] + '...' \ + or display_name + + hs_code = fields.Char( + string='H.S. Code', compute='_get_hs_code', readonly=True, + help="Harmonized System code (6 digits). Full list is " + "available from the World Customs Organisation, see " + "http://www.wcoomd.org") + description = fields.Char( + 'Description', translate=True, + help="Short text description of the H.S. category") + display_name = fields.Char( + compute='_compute_display_name', string="Display Name", + store=True, readonly=True) + local_code = fields.Char( + string='Local Code', 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.") + active = fields.Boolean(default=True) + company_id = fields.Many2one( + 'res.company', string='Company', readonly=True, required=True, + default=lambda self: self.env['res.company']._company_default_get( + 'hs.code')) + + _sql_constraints = [ + ('local_code_company_uniq', 'unique(local_code, company_id)', + 'This code already exists for this company !'), + ] + + @api.model + def create(self, vals): + if vals.get('local_code'): + vals['local_code'] = vals['local_code'].replace(' ', '') + return super(HSCode, self).create(vals) + + @api.multi + def write(self, vals): + if vals.get('local_code'): + vals['local_code'] = vals['local_code'].replace(' ', '') + return super(HSCode, self).write(vals) diff --git a/product_harmonized_system/hs_view.xml b/product_harmonized_system/hs_view.xml new file mode 100644 index 0000000..0b9a2a7 --- /dev/null +++ b/product_harmonized_system/hs_view.xml @@ -0,0 +1,67 @@ + + + + + + + + + + hs.code.search + hs.code + + + + + + + + + + hs.code.tree + hs.code + + + + + + + + + + + + + hs.code.form + hs.code + +
+ + + + + + + +
+
+
+ + + + H.S. Codes + hs.code + tree,form + + + + + +
+
diff --git a/product_harmonized_system/i18n/fr.po b/product_harmonized_system/i18n/fr.po new file mode 100644 index 0000000..f8c57a1 --- /dev/null +++ b/product_harmonized_system/i18n/fr.po @@ -0,0 +1,156 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_harmonized_system +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-07-16 13:11+0000\n" +"PO-Revision-Date: 2015-07-16 13:11+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: product_harmonized_system +#: field:hs.code,active:0 +msgid "Active" +msgstr "Actif" + +#. module: product_harmonized_system +#: model:hs.code,description:product_harmonized_system.84715000 +msgid "Automatic data-processing machines (computers)" +msgstr "" + +#. module: product_harmonized_system +#: help:hs.code,local_code:0 +msgid "Code used for the national Import/Export declaration. e.g. Intrastat for the European Union" +msgstr "Code utilisé pour la déclaration nationale d'import/export, par exemple la DEB pour la France" + +#. module: product_harmonized_system +#: field:hs.code,company_id:0 +msgid "Company" +msgstr "Société" + +#. module: product_harmonized_system +#: field:product.template,origin_country_id:0 +msgid "Country of Origin" +msgstr "Pays d'origine" + +#. module: product_harmonized_system +#: 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: product_harmonized_system +#: field:hs.code,create_uid:0 +msgid "Created by" +msgstr "Créé par" + +#. module: product_harmonized_system +#: field:hs.code,create_date:0 +msgid "Created on" +msgstr "Créé le" + +#. module: product_harmonized_system +#: field:hs.code,description:0 +msgid "Description" +msgstr "Description" + +#. module: product_harmonized_system +#: field:hs.code,display_name:0 +msgid "Display Name" +msgstr "Nom affiché" + +#. module: product_harmonized_system +#: model:ir.model,name:product_harmonized_system.model_hs_code +#: field:product.category,hs_code_id:0 +#: field:product.template,hs_code_id:0 +msgid "H.S. Code" +msgstr "Code S.H." + +#. module: product_harmonized_system +#: view:hs.code:product_harmonized_system.hs_code_form +msgid "HS Code" +msgstr "Code S.H." + +#. module: product_harmonized_system +#: view:hs.code:product_harmonized_system.hs_code_tree +#: model:ir.actions.act_window,name:product_harmonized_system.hs_code_act +#: model:ir.ui.menu,name:product_harmonized_system.hs_code_menu +msgid "HS Codes" +msgstr "Codes S.H." + +#. module: product_harmonized_system +#: help:product.category,hs_code_id:0 +msgid "Harmonised System Code. If this code is not set on the product itself, it will be read here, on the related product category." +msgstr "" + +#. module: product_harmonized_system +#: help:product.template,hs_code_id:0 +msgid "Harmonised System Code. Nomenclature is available from the World Customs Organisation, see http://www.wcoomd.org/. You can leave this field empty and configure the H.S. code on the product category." +msgstr "" + +#. module: product_harmonized_system +#: field:hs.code,id:0 +msgid "ID" +msgstr "ID" + +#. module: product_harmonized_system +#: view:product.category:product_harmonized_system.product_category_form_view +msgid "Import/Export Properties" +msgstr "Propriétés pour l'import/export" + +#. module: product_harmonized_system +#: field:hs.code,write_uid:0 +msgid "Last Updated by" +msgstr "Dernière modification par" + +#. module: product_harmonized_system +#: field:hs.code,write_date:0 +msgid "Last Updated on" +msgstr "Dernière modification le" + +#. module: product_harmonized_system +#: field:hs.code,local_code:0 +msgid "Local Code" +msgstr "Code local" + +#. module: product_harmonized_system +#: model:hs.code,description:product_harmonized_system.85340090 +msgid "Printed circuits" +msgstr "" + +#. module: product_harmonized_system +#: model:ir.model,name:product_harmonized_system.model_product_category +msgid "Product Category" +msgstr "Catégorie d'articles" + +#. module: product_harmonized_system +#: model:ir.model,name:product_harmonized_system.model_product_template +msgid "Product Template" +msgstr "Modèle d'article" + +#. module: product_harmonized_system +#: view:hs.code:product_harmonized_system.hs_code_search +msgid "Search HS Codes" +msgstr "Recherche dans les codes S.H." + +#. module: product_harmonized_system +#: help:hs.code,description:0 +msgid "Short text description of the H.S. category" +msgstr "Courte description de la catégorie H.S." + +#. module: product_harmonized_system +#: model:hs.code,description:product_harmonized_system.84717050 +msgid "Storage units" +msgstr "" + +#. module: product_harmonized_system +#: sql_constraint:hs.code:0 +msgid "This code already exists for this company !" +msgstr "Ce code existe déjà pour cette société !" + diff --git a/product_harmonized_system/i18n/product_harmonized_system.pot b/product_harmonized_system/i18n/product_harmonized_system.pot new file mode 100644 index 0000000..b1389e9 --- /dev/null +++ b/product_harmonized_system/i18n/product_harmonized_system.pot @@ -0,0 +1,156 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_harmonized_system +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-07-16 13:10+0000\n" +"PO-Revision-Date: 2015-07-16 13:10+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: product_harmonized_system +#: field:hs.code,active:0 +msgid "Active" +msgstr "" + +#. module: product_harmonized_system +#: model:hs.code,description:product_harmonized_system.84715000 +msgid "Automatic data-processing machines (computers)" +msgstr "" + +#. module: product_harmonized_system +#: help:hs.code,local_code:0 +msgid "Code used for the national Import/Export declaration. e.g. Intrastat for the European Union" +msgstr "" + +#. module: product_harmonized_system +#: field:hs.code,company_id:0 +msgid "Company" +msgstr "" + +#. module: product_harmonized_system +#: field:product.template,origin_country_id:0 +msgid "Country of Origin" +msgstr "" + +#. module: product_harmonized_system +#: 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: product_harmonized_system +#: field:hs.code,create_uid:0 +msgid "Created by" +msgstr "" + +#. module: product_harmonized_system +#: field:hs.code,create_date:0 +msgid "Created on" +msgstr "" + +#. module: product_harmonized_system +#: field:hs.code,description:0 +msgid "Description" +msgstr "" + +#. module: product_harmonized_system +#: field:hs.code,display_name:0 +msgid "Display Name" +msgstr "" + +#. module: product_harmonized_system +#: model:ir.model,name:product_harmonized_system.model_hs_code +#: field:product.category,hs_code_id:0 +#: field:product.template,hs_code_id:0 +msgid "H.S. Code" +msgstr "" + +#. module: product_harmonized_system +#: view:hs.code:product_harmonized_system.hs_code_form +msgid "HS Code" +msgstr "" + +#. module: product_harmonized_system +#: view:hs.code:product_harmonized_system.hs_code_tree +#: model:ir.actions.act_window,name:product_harmonized_system.hs_code_act +#: model:ir.ui.menu,name:product_harmonized_system.hs_code_menu +msgid "HS Codes" +msgstr "" + +#. module: product_harmonized_system +#: help:product.category,hs_code_id:0 +msgid "Harmonised System Code. If this code is not set on the product itself, it will be read here, on the related product category." +msgstr "" + +#. module: product_harmonized_system +#: help:product.template,hs_code_id:0 +msgid "Harmonised System Code. Nomenclature is available from the World Customs Organisation, see http://www.wcoomd.org/. You can leave this field empty and configure the H.S. code on the product category." +msgstr "" + +#. module: product_harmonized_system +#: field:hs.code,id:0 +msgid "ID" +msgstr "" + +#. module: product_harmonized_system +#: view:product.category:product_harmonized_system.product_category_form_view +msgid "Import/Export Properties" +msgstr "" + +#. module: product_harmonized_system +#: field:hs.code,write_uid:0 +msgid "Last Updated by" +msgstr "" + +#. module: product_harmonized_system +#: field:hs.code,write_date:0 +msgid "Last Updated on" +msgstr "" + +#. module: product_harmonized_system +#: field:hs.code,local_code:0 +msgid "Local Code" +msgstr "" + +#. module: product_harmonized_system +#: model:hs.code,description:product_harmonized_system.85340090 +msgid "Printed circuits" +msgstr "" + +#. module: product_harmonized_system +#: model:ir.model,name:product_harmonized_system.model_product_category +msgid "Product Category" +msgstr "" + +#. module: product_harmonized_system +#: model:ir.model,name:product_harmonized_system.model_product_template +msgid "Product Template" +msgstr "" + +#. module: product_harmonized_system +#: view:hs.code:product_harmonized_system.hs_code_search +msgid "Search HS Codes" +msgstr "" + +#. module: product_harmonized_system +#: help:hs.code,description:0 +msgid "Short text description of the H.S. category" +msgstr "" + +#. module: product_harmonized_system +#: model:hs.code,description:product_harmonized_system.84717050 +msgid "Storage units" +msgstr "" + +#. module: product_harmonized_system +#: sql_constraint:hs.code:0 +msgid "This code already exists for this company !" +msgstr "" + diff --git a/product_harmonized_system/product.py b/product_harmonized_system/product.py new file mode 100644 index 0000000..2801a10 --- /dev/null +++ b/product_harmonized_system/product.py @@ -0,0 +1,73 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# 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 + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + hs_code_id = fields.Many2one( + 'hs.code', string='H.S. Code', + company_dependent=True, ondelete='restrict', + help="Harmonised System Code. Nomenclature is " + "available from the World Customs Organisation, see " + "http://www.wcoomd.org/. You can leave this field empty " + "and configure the H.S. code on the product category.") + origin_country_id = fields.Many2one( + 'res.country', string='Country of Origin', + help="Country of origin of the product i.e. product " + "'made in ____'.") + + @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() + else: + res = None + return res + + +class ProductCategory(models.Model): + _inherit = "product.category" + + hs_code_id = fields.Many2one( + 'hs.code', string='H.S. Code', + company_dependent=True, ondelete='restrict', + help="Harmonised System Code. If this code is not " + "set on the product itself, it will be read here, on the " + "related product category.") + + @api.multi + def get_hs_code_recursively(self): + self.ensure_one() + if self.hs_code_id: + res = self.hs_code_id + elif self.parent_id: + res = self.parent_id.get_hs_code_recursively() + else: + res = None + return res diff --git a/product_harmonized_system/product_demo.xml b/product_harmonized_system/product_demo.xml new file mode 100644 index 0000000..fc11a8b --- /dev/null +++ b/product_harmonized_system/product_demo.xml @@ -0,0 +1,92 @@ + + + + + + + + + 84715000 + Automatic data-processing machines (computers) + + + + 84717050 + Storage units + + + + 85340090 + Printed circuits + + + + + + 8 + 8.7 + + + + + + 0.5 + 1.1 + + + + + + 7.5 + 8.2 + + + + + + 0.45 + 0.7 + + + + + + 0.42 + 0.67 + + + + + + 0.52 + 0.75 + + + + + + 0.6 + 1.05 + + + + + + 0.65 + 1.1 + + + + + + 3.3 + 4.6 + + + + + diff --git a/product_harmonized_system/product_view.xml b/product_harmonized_system/product_view.xml new file mode 100644 index 0000000..7c15e95 --- /dev/null +++ b/product_harmonized_system/product_view.xml @@ -0,0 +1,40 @@ + + + + + + + + + + hs_code.product.template.form + product.template + + + + + + + + + + + + hs_code.product.category.form + product.category + + + + + + + + + + + + diff --git a/product_harmonized_system/security/ir.model.access.csv b/product_harmonized_system/security/ir.model.access.csv new file mode 100644 index 0000000..133a7cd --- /dev/null +++ b/product_harmonized_system/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_hs_code_sale_manager,Full access on hs.code to sale manager,model_hs_code,base.group_sale_manager,1,1,1,1 +access_hs_code_read,Read access on hs.code to everybody,model_hs_code,,1,0,0,0 diff --git a/product_harmonized_system/security/product_hs_security.xml b/product_harmonized_system/security/product_hs_security.xml new file mode 100644 index 0000000..fae60ac --- /dev/null +++ b/product_harmonized_system/security/product_hs_security.xml @@ -0,0 +1,12 @@ + + + + + + HS Code Company rule + + ['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])] + + + +