[MIG] intrastat_product: Migration to 11.0

* Small fixes in intrastat_base
* account_tax_template
This commit is contained in:
Luc De Meyer
2019-04-17 20:48:49 +02:00
committed by Pedro M. Baeza
parent 4dbfeecd09
commit 981ecf8575
42 changed files with 2044 additions and 572 deletions

View File

@@ -1,5 +1,6 @@
# © 2011-2016 Akretion (http://www.akretion.com)
# © 2018 brain-tec AG (Kumar Aberer <kumar.aberer@braintec-group.com>)
# Copyright 2011-2016 Akretion (http://www.akretion.com)
# Copyright 2018 brain-tec AG (Kumar Aberer <kumar.aberer@braintec-group.com>)
# Copyright 2009-2019 Noviat (http://www.noviat.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
@@ -8,7 +9,7 @@
'category': 'Intrastat',
'license': 'AGPL-3',
'summary': 'Base module for Intrastat reporting',
'author': 'Akretion,Odoo Community Association (OCA)',
'author': 'Akretion,Noviat,Odoo Community Association (OCA)',
'website': 'https://github.com/OCA/intrastat',
'depends': ['base_vat', 'account'],
'conflicts': ['report_intrastat'],

View File

@@ -20,7 +20,7 @@ msgid "Activate this option for shipping costs, packaging costs and all services
msgstr ""
#. module: intrastat_base
#: code:addons/intrastat_base/models/intrastat_common.py:154
#: code:addons/intrastat_base/models/intrastat_common.py:151
#, python-format
msgid "Cannot delete the declaration %s because it is in Done state"
msgstr ""
@@ -36,7 +36,7 @@ msgid "Companies"
msgstr ""
#. module: intrastat_base
#: code:addons/intrastat_base/models/intrastat_common.py:33
#: code:addons/intrastat_base/models/intrastat_common.py:39
#, python-format
msgid "Company not yet set on intrastat report."
msgstr ""
@@ -177,35 +177,29 @@ msgid "Tax"
msgstr ""
#. module: intrastat_base
#: code:addons/intrastat_base/models/intrastat_common.py:51
#: code:addons/intrastat_base/models/intrastat_common.py:52
#, python-format
msgid "The VAT number is not set for the partner '%s'."
msgstr ""
#. module: intrastat_base
#: 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/models/intrastat_common.py:37
#: code:addons/intrastat_base/models/intrastat_common.py:43
#, python-format
msgid "The country is not set on the company '%s'."
msgstr ""
#. module: intrastat_base
#: 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/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/models/intrastat_common.py:73
#, python-format
msgid "Unknown Error"
msgstr ""
#. module: intrastat_base
#: 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

View File

@@ -1,12 +1,16 @@
# © 2010-2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# Copyright 2010-2016 Akretion (<alexis.delattre@akretion.com>)
# Copyright 2009-2019 Noviat (http://www.noviat.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api, tools, _
from odoo.exceptions import UserError
import base64
from io import BytesIO
from lxml import etree
from sys import exc_info
from traceback import format_exception
import logging
from odoo import api, fields, models, tools, _
from odoo.exceptions import UserError
logger = logging.getLogger(__name__)
@@ -50,43 +54,40 @@ class IntrastatCommon(models.AbstractModel):
return True
@api.model
def _check_xml_schema(self, xml_etree, xsd_file):
def _check_xml_schema(self, xml_string, xsd_file):
'''Validate the XML file against the XSD'''
xsd_etree_obj = etree.parse(
tools.file_open(xsd_file))
tools.file_open(xsd_file, mode='rb'))
official_schema = etree.XMLSchema(xsd_etree_obj)
try:
official_schema.assertValid(xml_etree)
except Exception as e:
# if the validation of the XSD fails, we arrive here
logger = logging.getLogger(__name__)
t = etree.parse(BytesIO(xml_string))
official_schema.assertValid(t)
except (etree.XMLSchemaParseError, etree.DocumentInvalid) as e:
logger.warning(
"The XML file is invalid against the XML Schema Definition")
xml_string = etree.tostring(
xml_etree, pretty_print=True, encoding='UTF-8',
xml_declaration=True).decode()
logger.warning(xml_string)
logger.warning(e)
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. "
"Here is the error, which may give you an idea on the "
"cause of the problem : %s.")
% str(e))
return True
usererror = '%s\n\n%s' % (e.__class__.__name__, str(e))
raise UserError(usererror)
except Exception:
error = _("Unknown Error")
tb = ''.join(format_exception(*exc_info()))
error += '\n%s' % tb
logger.warning(error)
raise UserError(error)
@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
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.b64encode(xml_string),
'datas': base64.encodestring(xml_string),
'datas_fname': filename})
return attach.id

View File

@@ -1,7 +1,7 @@
# © 2010-2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# Copyright 2010-2016 Akretion (<alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api, _
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
@@ -19,8 +19,9 @@ class ProductTemplate(models.Model):
def _check_accessory_cost(self):
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))
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))

View File

@@ -1,7 +1,7 @@
# © 2013-2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# Copyright 2013-2017 Akretion (<alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api, _
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError

View File

@@ -1,8 +1,8 @@
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# © 2018 brain-tec AG (Kumar Aberer <kumar.aberer@braintec-group.com>)
# Copyright 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# Copyright 2018 brain-tec AG (Kumar Aberer <kumar.aberer@braintec-group.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import models, fields
from odoo import fields, models
class ResConfigSettings(models.TransientModel):

View File

@@ -1,7 +1,7 @@
# © 2011-2014 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# Copyright 2011-2014 Akretion (<alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields
from odoo import fields, models
class ResCountry(models.Model):

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -12,9 +12,9 @@
<field name="model">account.tax</field>
<field name="inherit_id" ref="account.view_tax_form"/>
<field name="arch" type="xml">
<group name="advanced_booleans" position="inside">
<field name="active" position="before">
<field name="exclude_from_intrastat_if_present"/>
</group>
</field>
</field>
</record>

View File

@@ -15,14 +15,13 @@
<xpath expr="//div[@id='recommended_apps']" position="after">
<h2>Intrastat</h2>
<div class="row mt16 o_settings_container" id="intrastat">
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="col-xs-12 col-md-12 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<div class="content-group" id="intrastat_content_grp">
<div class="row mt16">
<label for="intrastat_remind_user_ids" class="col-md-5 o_light_label"/>
<field name="intrastat_remind_user_ids" widget="many2many_tags"/>
</div>
</div>
<div class="row">
<label for="intrastat_remind_user_ids" class="col-md-5 o_light_label"/>
<field name="intrastat_remind_user_ids" widget="many2many_tags"/>
</div>
</div>
</div>
</div>

View File

@@ -1,3 +1,2 @@
# -*- coding: utf-8 -*-
from . import models
from . import report

View File

@@ -1,14 +1,13 @@
# -*- coding: utf-8 -*-
# © 2011-2017 Akretion (http://www.akretion.com)
# © 2009-2017 Noviat (http://www.noviat.com)
# © 2018 brain-tec AG (http://www.braintec-group.com)
# Copyright 2011-2017 Akretion (http://www.akretion.com)
# Copyright 2009-2019 Noviat (http://www.noviat.com)
# Copyright 2018 brain-tec AG (http://www.braintec-group.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Luc de Meyer <info@noviat.com>
# @author Kumar Aberer <kumar.aberer@braintec-group.com>
{
'name': 'Intrastat Product',
'version': '11.0.1.1.0',
'version': '11.0.1.2.0',
'category': 'Intrastat',
'license': 'AGPL-3',
'summary': 'Base module for Intrastat Product',
@@ -19,8 +18,9 @@
'product_harmonized_system',
'sale_stock',
'purchase',
'report_xlsx_helper',
],
'conflicts': ['report_intrastat'],
'excludes': ['report_intrastat'],
'data': [
'views/hs_code.xml',
'views/intrastat_region.xml',

View File

@@ -30,7 +30,6 @@
<field name="code">7</field>
<field name="name">Fixed installations</field>
<field name="description">Fixed transport installations (e.g. pipelines, high-tension cables)</field>
<field name="description"></field>
</record>
<record id="intrastat_transport_8" model="intrastat.transport_mode">
<field name="code">8</field>

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from . import res_company
from . import res_config_settings
from . import account_invoice

View File

@@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# © 2011-2017 Akretion (http://www.akretion.com)
# © 2009-2017 Noviat (http://www.noviat.com)
# Copyright 2011-2017 Akretion (http://www.akretion.com)
# Copyright 2009-2018 Noviat (http://www.noviat.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Luc de Meyer <info@noviat.com>
from odoo import models, fields, api
from odoo import api, fields, models
class AccountInvoice(models.Model):
@@ -13,31 +12,34 @@ class AccountInvoice(models.Model):
# in v10, the sale_stock module defines an incoterms_id
# Odoo v8 name: incoterm_id
intrastat_transaction_id = fields.Many2one(
'intrastat.transaction', string='Intrastat Transaction Type',
default=lambda self: self._default_intrastat_transaction_id(),
ondelete='restrict',
comodel_name='intrastat.transaction',
string='Intrastat Transaction Type',
ondelete='restrict', track_visibility='onchange',
help="Intrastat nature of transaction")
intrastat_transport_id = fields.Many2one(
'intrastat.transport_mode', string='Intrastat Transport Mode',
comodel_name='intrastat.transport_mode',
string='Intrastat Transport Mode',
ondelete='restrict')
src_dest_country_id = fields.Many2one(
'res.country', string='Origin/Destination Country',
comodel_name='res.country',
string='Origin/Destination Country',
compute='_compute_intrastat_country',
store=True,
store=True, compute_sudo=True,
help="Destination country for dispatches. Origin country for "
"arrivals.")
intrastat_country = fields.Boolean(
compute='_compute_intrastat_country',
store=True, string='Intrastat Country', readonly=True)
compute='_compute_intrastat_country', string='Intrastat Country',
store=True, readonly=True, compute_sudo=True)
src_dest_region_id = fields.Many2one(
'intrastat.region', string='Origin/Destination Region',
comodel_name='intrastat.region',
string='Origin/Destination Region',
default=lambda self: self._default_src_dest_region_id(),
help="Origin region for dispatches, destination region for "
"arrivals. This field is used for the Intrastat Declaration.",
ondelete='restrict')
intrastat = fields.Char(
string='Intrastat Declaration',
related='company_id.intrastat', readonly=True)
related='company_id.intrastat', readonly=True, compute_sudo=True)
@api.multi
@api.depends('partner_shipping_id.country_id', 'partner_id.country_id')
@@ -50,26 +52,10 @@ class AccountInvoice(models.Model):
inv.src_dest_country_id = country.id
inv.intrastat_country = country.intrastat
@api.model
def _default_intrastat_transaction_id(self):
rco = self.env['res.company']
company = rco._company_default_get()
inv_type = self._context.get('type')
if inv_type == 'out_invoice':
return company.intrastat_transaction_out_invoice
elif inv_type == 'out_refund':
return company.intrastat_transaction_out_refund
elif inv_type == 'in_invoice':
return company.intrastat_transaction_in_invoice
elif inv_type == 'in_refund':
return company.intrastat_transaction_in_refund
else:
return self.env['intrastat.transaction']
@api.model
def _default_src_dest_region_id(self):
rco = self.env['res.company']
company = rco._company_default_get()
company = rco._company_default_get('account.invoice')
return company.intrastat_region_id
@@ -77,7 +63,8 @@ class AccountInvoiceLine(models.Model):
_inherit = 'account.invoice.line'
hs_code_id = fields.Many2one(
'hs.code', string='Intrastat Code', ondelete='restrict')
comodel_name='hs.code',
string='Intrastat Code', ondelete='restrict')
@api.onchange('product_id')
def intrastat_product_id_change(self):

View File

@@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# © 2011-2017 Akretion (http://www.akretion.com)
# © 2009-2017 Noviat (http://www.noviat.com)
# Copyright 2011-2017 Akretion (http://www.akretion.com)
# Copyright 2009-2018 Noviat (http://www.noviat.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Luc de Meyer <info@noviat.com>
from odoo import models, fields, api, _
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
@@ -12,7 +11,8 @@ class HSCode(models.Model):
_inherit = "hs.code"
intrastat_unit_id = fields.Many2one(
'intrastat.unit', string='Intrastat Supplementary Unit')
comodel_name='intrastat.unit',
string='Intrastat Supplementary Unit')
@api.constrains('local_code')
def _hs_code(self):

View File

@@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# © 2011-2017 Akretion (http://www.akretion.com)
# © 2009-2017 Noviat (http://www.noviat.com)
# Copyright 2011-2017 Akretion (http://www.akretion.com)
# Copyright 2009-2018 Noviat (http://www.noviat.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Luc de Meyer <info@noviat.com>
from odoo import models, fields, api, _
from odoo import api, fields, models, _
from odoo.exceptions import RedirectWarning, ValidationError, UserError
import odoo.addons.decimal_precision as dp
from datetime import datetime, date
@@ -19,6 +18,114 @@ class IntrastatProductDeclaration(models.Model):
_rec_name = 'year_month'
_inherit = ['mail.thread', 'intrastat.common']
_order = 'year_month desc, type, revision'
_sql_constraints = [
('date_uniq',
'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.model
def _default_year(self):
if datetime.now().month == 1:
year = datetime.now().year - 1
else:
year = datetime.now().year
return str(year)
@api.model
def _default_month(self):
if datetime.now().month == 1:
return 12
else:
return datetime.now().month - 1
@api.model
def _default_action(self):
return 'replace'
company_id = fields.Many2one(
comodel_name='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.Char(
string='Year', required=True,
default=lambda self: self._default_year(),
states={'done': [('readonly', True)]})
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=lambda self: self._default_month(),
states={'done': [('readonly', True)]})
year_month = fields.Char(
compute='_compute_year_month', string='Period', readonly=True,
track_visibility='onchange', store=True,
help="Year and month of the declaration.")
type = fields.Selection(
selection='_get_type', string='Type', required=True,
states={'done': [('readonly', True)]},
track_visibility='onchange', help="Select the declaration type.")
action = fields.Selection(
selection='_get_action',
string='Action', required=True,
default=lambda self: self._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(
comodel_name='intrastat.product.computation.line',
inverse_name='parent_id',
string='Intrastat Product Computation Lines',
states={'done': [('readonly', True)]})
declaration_line_ids = fields.One2many(
comodel_name='intrastat.product.declaration.line',
inverse_name='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.Integer(
compute='_compute_numbers', string='Total Fiscal Amount', store=True,
help="Total fiscal 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(
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(
selection='_get_reporting_level',
string='Reporting Level',
states={'done': [('readonly', True)]})
valid = fields.Boolean(
compute='_compute_check_validity',
string='Valid')
@api.model
def _get_type(self):
@@ -38,6 +145,46 @@ class IntrastatProductDeclaration(models.Model):
('standard', _('Standard')),
('extended', _('Extended'))]
@api.model
def _get_action(self):
return [
('replace', 'Replace'),
('append', 'Append'),
('nihil', 'Nihil')]
@api.multi
@api.depends('company_id')
def _compute_company_country_code(self):
for this in self:
if this.company_id:
if not this.company_id.country_id:
raise ValidationError(
_("You must set company's country !"))
this.company_country_code = \
this.company_id.country_id.code.lower()
@api.multi
@api.depends('year', 'month')
def _compute_year_month(self):
for this in self:
if this.year and this.month:
this.year_month = '-'.join(
[this.year, format(this.month, '02')])
@api.multi
@api.depends('month')
def _compute_check_validity(self):
""" TO DO: logic based upon computation lines """
for this in self:
this.valid = True
@api.model
@api.constrains('year')
def _check_year(self):
for this in self:
if len(this.year) != 4 or this.year[0] != '2':
raise ValidationError(_("Invalid Year !"))
@api.onchange('type')
def _onchange_type(self):
if self.type == 'arrivals':
@@ -49,152 +196,6 @@ class IntrastatProductDeclaration(models.Model):
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, required=True,
default=lambda self: self.env['res.company']._company_default_get())
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,
states={'done': [('readonly', True)]})
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,
states={'done': [('readonly', True)]})
year_month = fields.Char(
compute='_compute_year_month', string='Period', readonly=True,
track_visibility='onchange', store=True,
help="Year and month of the declaration.")
type = fields.Selection(
'_get_type', string='Type', required=True,
states={'done': [('readonly', True)]},
track_visibility='onchange', 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.Integer(
compute='_compute_numbers', string='Total Fiscal Amount', store=True,
help="Total fiscal amount in company currency of the declaration.")
currency_id = fields.Many2one(
related='company_id.currency_id', readonly=True, string='Company 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',
states={'done': [('readonly', True)]})
valid = fields.Boolean(
compute='_check_validity',
string='Valid')
@api.constrains('year')
def _check_year(self):
for this in self:
s = str(this.year)
if len(s) != 4 or s[0] != '2':
raise ValidationError(_("Invalid Year !"))
_sql_constraints = [
('date_uniq',
'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.multi
@api.depends('company_id')
def _compute_company_country_code(self):
for this in self:
if this.company_id:
if not this.company_id.country_id:
raise ValidationError(
_("You must set the country of the company!"))
this.company_country_code = \
this.company_id.country_id.code.lower()
@api.multi
@api.depends('year', 'month')
def _compute_year_month(self):
for this in self:
if this.year and this.month:
this.year_month = '-'.join(
[str(this.year), format(this.month, '02')])
@api.multi
@api.depends('month')
def _check_validity(self):
""" TO DO: logic based upon computation lines """
for this in self:
this.valid = True
@api.multi
def copy(self, default=None):
self.ensure_one()
@@ -202,11 +203,11 @@ class IntrastatProductDeclaration(models.Model):
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')
def _account_config_warning(self, msg):
action = self.env.ref('account.action_account_config')
raise RedirectWarning(
msg, action.id,
_('Go to company configuration screen'))
_('Go to Accounting Configuration Settings screen'))
def _get_partner_country(self, inv_line):
country = inv_line.invoice_id.src_dest_country_id \
@@ -353,7 +354,7 @@ class IntrastatProductDeclaration(models.Model):
[('invoice_lines', 'in', inv_line.id)])
if po_lines:
if po_lines[0].move_ids:
region = po_lines[0].move_ids[0].location_id\
region = po_lines[0].move_ids[0].location_dest_id\
.get_intrastat_region()
elif inv_type in ('out_invoice', 'out_refund'):
so_lines = self.env['sale.order.line'].search(
@@ -374,7 +375,7 @@ class IntrastatProductDeclaration(models.Model):
"The default Intrastat Transport Mode "
"of the Company is not set, "
"please configure it first.")
self._company_warning(msg)
self._account_config_warning(msg)
return transport
def _get_incoterm(self, inv_line):
@@ -385,7 +386,7 @@ class IntrastatProductDeclaration(models.Model):
"The default Incoterm "
"of the Company is not set, "
"please configure it first.")
self._company_warning(msg)
self._account_config_warning(msg)
return incoterm
def _get_product_origin_country(self, inv_line):
@@ -435,7 +436,7 @@ class IntrastatProductDeclaration(models.Model):
with the country-specific logic for arrivals and dispatches.
Cf. l10n_be_intrastat_product_declaration for an example
"""
start_date = date(self.year, self.month, 1)
start_date = date(int(self.year), self.month, 1)
end_date = start_date + relativedelta(day=1, months=+1, days=-1)
domain = [
('date_invoice', '>=', start_date),
@@ -525,7 +526,7 @@ class IntrastatProductDeclaration(models.Model):
continue
else:
_logger.info(
'Skipping invoice line %s qty %s'
'Skipping invoice line %s qty %s '
'of invoice %s. Reason: no product nor hs_code'
% (inv_line.name, inv_line.quantity, invoice.number))
continue
@@ -608,7 +609,7 @@ class IntrastatProductDeclaration(models.Model):
@api.multi
def action_gather(self):
self.ensure_one()
self.message_post(_("Generate Lines from Invoices"))
self.message_post(body=_("Generate Lines from Invoices"))
self._check_generate_lines()
self._note = ''
if (
@@ -720,7 +721,7 @@ class IntrastatProductDeclaration(models.Model):
""" generate declaration lines """
self.ensure_one()
assert self.valid, 'Computation lines are not valid'
self.message_post(_("Generate Declaration Lines"))
self.message_post(body=_("Generate Declaration Lines"))
# Delete existing declaration lines
self.declaration_line_ids.unlink()
# Regenerate declaration lines from computation lines
@@ -743,7 +744,7 @@ class IntrastatProductDeclaration(models.Model):
def generate_xml(self):
""" generate the INTRASTAT Declaration XML file """
self.ensure_one()
self.message_post(_("Generate XML Declaration File"))
self.message_post(body=_("Generate XML Declaration File"))
self._check_generate_xml()
self._unlink_attachments()
xml_string = self._generate_xml()
@@ -755,6 +756,52 @@ class IntrastatProductDeclaration(models.Model):
raise UserError(
_("No XML File has been generated."))
@api.multi
def create_xls(self):
if self.env.context.get('computation_lines'):
report_file = 'instrastat_transactions'
else:
report_file = 'instrastat_declaration_lines'
return {
'type': 'ir.actions.report',
'report_type': 'xlsx',
'report_name': 'intrastat_product.product_declaration_xls',
'context': dict(self.env.context, report_file=report_file),
'data': {'dynamic_report': True},
}
@api.model
def _xls_computation_line_fields(self):
"""
Update list in custom module to add/drop columns or change order
"""
return [
'product', 'product_origin_country',
'hs_code', 'src_dest_country',
'amount_company_currency', 'accessory_cost',
'transaction', 'weight', 'suppl_unit_qty', 'suppl_unit',
'transport', 'invoice',
]
@api.model
def _xls_declaration_line_fields(self):
"""
Update list in custom module to add/drop columns or change order
"""
return [
'hs_code', 'src_dest_country', 'amount_company_currency',
'transaction', 'weight', 'suppl_unit_qty', 'suppl_unit',
'transport',
]
@api.model
def _xls_template(self):
"""
Placeholder for excel report template updates
"""
return {}
@api.multi
def done(self):
self.write({'state': 'done'})
@@ -766,27 +813,34 @@ class IntrastatProductDeclaration(models.Model):
class IntrastatProductComputationLine(models.Model):
_name = 'intrastat.product.computation.line'
_description = "Intrastat Product Computation Lines"
_description = "Intrastat Product Computataion Lines"
parent_id = fields.Many2one(
'intrastat.product.declaration',
string='Intrastat Product Declaration',
ondelete='cascade', readonly=True)
company_id = fields.Many2one(
related='parent_id.company_id', readonly=True)
'res.company', related='parent_id.company_id',
string="Company", readonly=True)
company_currency_id = fields.Many2one(
related='company_id.currency_id', readonly=True)
'res.currency', related='company_id.currency_id',
string="Company currency", readonly=True)
type = fields.Selection(
related='parent_id.type', readonly=True)
related='parent_id.type',
string='Type',
readonly=True)
reporting_level = fields.Selection(
related='parent_id.reporting_level', readonly=True)
related='parent_id.reporting_level',
string='Reporting Level',
readonly=True)
valid = fields.Boolean(
compute='_check_validity',
compute='_compute_check_validity',
string='Valid')
invoice_line_id = fields.Many2one(
'account.invoice.line', string='Invoice Line', readonly=True)
invoice_id = fields.Many2one(
related='invoice_line_id.invoice_id', string='Invoice', readonly=True)
'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)
@@ -795,11 +849,12 @@ class IntrastatProductComputationLine(models.Model):
help="Country of Origin/Destination",
domain=[('intrastat', '=', True)])
product_id = fields.Many2one(
related='invoice_line_id.product_id', readonly=True)
'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(
related='hs_code_id.intrastat_unit_id',
'intrastat.unit', related='hs_code_id.intrastat_unit_id',
string='Suppl. Unit', readonly=True,
help="Intrastat Supplementary Unit")
weight = fields.Float(
@@ -838,7 +893,7 @@ class IntrastatProductComputationLine(models.Model):
@api.multi
@api.depends('transport_id')
def _check_validity(self):
def _compute_check_validity(self):
""" TO DO: logic based upon fields """
for this in self:
this.valid = True
@@ -854,7 +909,7 @@ class IntrastatProductComputationLine(models.Model):
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
self.weight = self.product_id.weight
class IntrastatProductDeclarationLine(models.Model):
@@ -866,12 +921,19 @@ class IntrastatProductDeclarationLine(models.Model):
string='Intrastat Product Declaration',
ondelete='cascade', readonly=True)
company_id = fields.Many2one(
related='parent_id.company_id', readonly=True)
'res.company', related='parent_id.company_id',
string="Company", readonly=True)
company_currency_id = fields.Many2one(
related='company_id.currency_id', readonly=True)
type = fields.Selection(related='parent_id.type', readonly=True)
'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', readonly=True)
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)
@@ -910,40 +972,3 @@ class IntrastatProductDeclarationLine(models.Model):
product_origin_country_id = fields.Many2one(
'res.country', string='Country of Origin of the Product',
help="Country of origin of the product i.e. product 'made in ____'")
def _fields_to_sum(self):
"""
This method is DEPRECATED.
You should use the _fields_to_sum method on the
IntrastatProductDeclaration class.
"""
fields_to_sum = [
'weight',
'suppl_unit_qty',
]
return fields_to_sum
@api.model
def _prepare_declaration_line(self, computation_lines):
"""
This method is DEPRECATED.
You should use the _fields_to_sum method on the
IntrastatProductDeclaration class.
"""
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]
vals['amount_company_currency'] += (
computation_line['amount_company_currency'] +
computation_line['amount_accessory_cost_company_currency'])
# round, otherwise odoo with truncate (6.7 -> 6... instead of 7 !)
for field in fields_to_sum:
vals[field] = int(round(vals[field]))
if not vals['weight']:
vals['weight'] = 1
vals['amount_company_currency'] = int(round(
vals['amount_company_currency']))
return vals

View File

@@ -1,24 +1,24 @@
# -*- coding: utf-8 -*-
# © 2009-2017 Noviat nv/sa (www.noviat.com).
# Copyright 2009-2018 Noviat nv/sa (www.noviat.com).
# @author Luc de Meyer <info@noviat.com>
from odoo import models, fields
from odoo import fields, models
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())
_sql_constraints = [
('intrastat_region_code_unique',
'UNIQUE(code, country_id)', # TODO add company_id ?
'Code must be unique.')]
code = fields.Char(string='Code', required=True)
country_id = fields.Many2one(
comodel_name='res.country',
string='Country', required=True)
name = fields.Char(string='Name', translate=True)
description = fields.Char(string='Description')
company_id = fields.Many2one(
comodel_name='res.company', string='Company',
default=lambda self: self.env['res.company']._company_default_get(
'intrastat.region'))

View File

@@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# © 2011-2017 Akretion (http://www.akretion.com)
# © 2009-2017 Noviat (http://www.noviat.com)
# Copyright 2011-2017 Akretion (http://www.akretion.com)
# Copyright 2009-2018 Noviat (http://www.noviat.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Luc de Meyer <info@noviat.com>
from odoo import models, fields, api
from odoo import api, fields, models
class IntrastatTransaction(models.Model):
@@ -12,6 +11,10 @@ class IntrastatTransaction(models.Model):
_description = "Intrastat Transaction"
_order = 'code'
_rec_name = 'display_name'
_sql_constraints = [(
'intrastat_transaction_code_unique',
'UNIQUE(code, company_id)',
'Code must be unique.')]
code = fields.Char(string='Code', required=True)
description = fields.Text(string='Description')
@@ -19,8 +22,9 @@ class IntrastatTransaction(models.Model):
compute='_compute_display_name_field', string="Display Name",
readonly=True, store=True)
company_id = fields.Many2one(
'res.company', string='Company',
default=lambda self: self.env['res.company']._company_default_get())
comodel_name='res.company', string='Company',
default=lambda self: self.env['res.company']._company_default_get(
'intrastat.transaction'))
@api.multi
@api.depends('code', 'description')
@@ -32,8 +36,3 @@ class IntrastatTransaction(models.Model):
this.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.')]

View File

@@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# © 2011-2017 Akretion (http://www.akretion.com)
# © 2009-2017 Noviat (http://www.noviat.com)
# Copyright 2011-2017 Akretion (http://www.akretion.com)
# Copyright 2009-2019 Noviat (http://www.noviat.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Luc de Meyer <info@noviat.com>
from odoo import models, fields, api
from odoo import api, fields, models
class IntrastatTransportMode(models.Model):
@@ -12,9 +11,13 @@ class IntrastatTransportMode(models.Model):
_description = "Intrastat Transport Mode"
_rec_name = 'display_name'
_order = 'code'
_sql_constraints = [(
'intrastat_transport_code_unique',
'UNIQUE(code)',
'Code must be unique.')]
display_name = fields.Char(
string='Display Name', compute='_display_name', store=True,
string='Display Name', compute='_compute_display_name', store=True,
readonly=True)
code = fields.Char(string='Code', required=True)
name = fields.Char(string='Name', required=True, translate=True)
@@ -22,11 +25,6 @@ class IntrastatTransportMode(models.Model):
@api.multi
@api.depends('name', 'code')
def _display_name(self):
def _compute_display_name(self):
for this in self:
this.display_name = '%s. %s' % (this.code, this.name)
_sql_constraints = [(
'intrastat_transport_code_unique',
'UNIQUE(code)',
'Code must be unique.')]

View File

@@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# © 2011-2017 Akretion (http://www.akretion.com)
# © 2009-2017 Noviat (http://www.noviat.com)
# Copyright 2011-2017 Akretion (http://www.akretion.com)
# Copyright 2009-2018 Noviat (http://www.noviat.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Luc de Meyer <info@noviat.com>
from odoo import models, fields
from odoo import fields, models
class IntrastatUnit(models.Model):
@@ -14,7 +13,7 @@ class IntrastatUnit(models.Model):
name = fields.Char(string='Name', required=True)
description = fields.Char(string='Description', required=True)
uom_id = fields.Many2one(
'product.uom', string='Regular UoM',
comodel_name='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)
active = fields.Boolean(default=True)

View File

@@ -1,47 +1,46 @@
# -*- coding: utf-8 -*-
# © 2011-2017 Akretion (http://www.akretion.com)
# © 2009-2017 Noviat (http://www.noviat.com)
# Copyright 2011-2017 Akretion (http://www.akretion.com)
# Copyright 2009-2018 Noviat (http://www.noviat.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Luc de Meyer <info@noviat.com>
from odoo import models, fields, api
from odoo import api, fields, models
class ResCompany(models.Model):
_inherit = 'res.company'
intrastat_incoterm_id = fields.Many2one(
'stock.incoterms',
comodel_name='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',
selection='_intrastat_arrivals', string='Arrivals',
default='extended', required=True)
intrastat_dispatches = fields.Selection(
'_intrastat_dispatches', string='Dispatches',
selection='_intrastat_dispatches', string='Dispatches',
default='extended', required=True)
intrastat_transport_id = fields.Many2one(
'intrastat.transport_mode',
comodel_name='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',
comodel_name='intrastat.region',
string='Default Intrastat Region')
intrastat_transaction_out_invoice = fields.Many2one(
'intrastat.transaction',
comodel_name='intrastat.transaction',
string='Default Intrastat Transaction For Customer Invoice')
intrastat_transaction_out_refund = fields.Many2one(
'intrastat.transaction',
comodel_name='intrastat.transaction',
string='Default Intrastat Transaction for Customer Refunds')
intrastat_transaction_in_invoice = fields.Many2one(
'intrastat.transaction',
comodel_name='intrastat.transaction',
string='Default Intrastat Transaction For Supplier Invoices')
intrastat_transaction_in_refund = fields.Many2one(
'intrastat.transaction',
comodel_name='intrastat.transaction',
string='Default Intrastat Transaction For Supplier Refunds')
intrastat_accessory_costs = fields.Boolean(
string='Include Accessory Costs in Fiscal Value of Product')

View File

@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# Copyright 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# Copyright 2009-2018 Noviat (http://www.noviat.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import models, fields
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
@@ -29,3 +29,7 @@ class ResConfigSettings(models.TransientModel):
related='company_id.intrastat_transaction_in_refund')
intrastat_accessory_costs = fields.Boolean(
related='company_id.intrastat_accessory_costs')
country_id = fields.Many2one(
related='company_id.country_id', readonly=True)
country_code = fields.Char(
related='company_id.country_id.code', readonly=True)

View File

@@ -1,15 +1,14 @@
# -*- coding: utf-8 -*-
# © 2010-2017 Akretion (http://www.akretion.com)
# Copyright 2010-2017 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
from odoo import models, fields, api
from odoo import api, fields, models
class SaleOrder(models.Model):
_inherit = "sale.order"
intrastat_transport_id = fields.Many2one(
'intrastat.transport_mode', string='Transport Mode',
comodel_name='intrastat.transport_mode', string='Transport Mode',
help="This information is used in Intrastat reports")
intrastat = fields.Selection(
string='Intrastat Declaration',

View File

@@ -1,15 +1,15 @@
# -*- coding: utf-8 -*-
# © 2009-2017 Noviat nv/sa (www.noviat.com).
# Copyright 2009-2018 Noviat nv/sa (www.noviat.com).
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Luc de Meyer <info@noviat.com>
from odoo import models, fields, api
from odoo import api, fields, models
class StockWarehouse(models.Model):
_inherit = 'stock.warehouse'
region_id = fields.Many2one('intrastat.region', string='Intrastat Region')
region_id = fields.Many2one(
comodel_name='intrastat.region', string='Intrastat Region')
class StockLocation(models.Model):

View File

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

View File

@@ -0,0 +1,276 @@
# Copyright 2009-2018 Noviat
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from odoo import models
from odoo.tools.translate import translate, _
_logger = logging.getLogger(__name__)
IR_TRANSLATION_NAME = 'intrastat.product.report'
class IntrastatProductDeclarationXlsx(models.AbstractModel):
_name = 'report.intrastat_product.product_declaration_xls'
_inherit = 'report.report_xlsx.abstract'
def _(self, src):
lang = self.env.context.get('lang', 'en_US')
val = translate(
self.env.cr, IR_TRANSLATION_NAME, 'report', lang, src) or src
return val
def _get_template(self, declaration):
template = {
'product': {
'header': {
'type': 'string',
'value': self._('Product'),
},
'line': {
'value': self._render(
"line.product_id and line.product_id.name"),
},
'width': 36,
},
'product_origin_country': {
'header': {
'type': 'string',
'value': self._('Product C/O'),
},
'line': {
'type': 'string',
'value': self._render(
"line.product_origin_country_id.name or ''"),
},
'width': 28,
},
'hs_code': {
'header': {
'type': 'string',
'value': self._('Intrastat Code'),
},
'line': {
'type': 'string',
'value': self._render(
"line.hs_code_id.local_code"),
},
'width': 14,
},
'src_dest_country': {
'header': {
'type': 'string',
'value': self._('Country of Origin/Destination'),
},
'line': {
'type': 'string',
'value': self._render(
"line.src_dest_country_id.name"),
},
'width': 28,
},
'amount_company_currency': {
'header': {
'type': 'string',
'value': self._('Fiscal Value'),
'format': self.format_theader_yellow_right,
},
'line': {
'type': 'number',
'value': self._render("line.amount_company_currency"),
'format': self.format_tcell_amount_right,
},
'width': 18,
},
'accessory_cost': {
'header': {
'type': 'string',
'value': self._('Accessory Costs'),
'format': self.format_theader_yellow_right,
},
'line': {
'type': 'number',
'value': self._render(
"line.amount_accessory_cost_company_currency"),
'format': self.format_tcell_amount_right,
},
'width': 18,
},
'transaction': {
'header': {
'type': 'string',
'value': self._('Intrastat Transaction'),
},
'line': {
'value': self._render(
"line.transaction_id.display_name"),
},
'width': 36,
},
'weight': {
'header': {
'type': 'string',
'value': self._('Weight'),
'format': self.format_theader_yellow_right,
},
'line': {
'type': 'number',
'value': self._render(
"line.weight"),
'format': self.format_tcell_amount_right,
},
'width': 18,
},
'suppl_unit_qty': {
'header': {
'type': 'string',
'value': self._('Suppl. Unit Qty'),
'format': self.format_theader_yellow_right,
},
'line': {
# we don't specify a type here and rely on the
# report_xlsx_helper type detection to use
# write_string when suppl_unit_qty is zero
'value': self._render(
"line.suppl_unit_qty or ''"),
'format': self.format_tcell_amount_right,
},
'width': 18,
},
'suppl_unit': {
'header': {
'type': 'string',
'value': self._('Suppl. Unit'),
},
'line': {
'value': self._render(
"line.intrastat_unit_id.name or ''"),
},
'width': 14,
},
'incoterm': {
'header': {
'type': 'string',
'value': self._('Incoterm'),
},
'line': {
'value': self._render("line.incoterm_id.name or ''"),
},
'width': 14,
},
'transport': {
'header': {
'type': 'string',
'value': self._('Transport Mode'),
},
'line': {
'value': self._render("line.transport_id.name or ''"),
},
'width': 14,
},
'region': {
'header': {
'type': 'string',
'value': self._('Intrastat Region'),
},
'line': {
'value': self._render("line.region_id.name or ''"),
},
'width': 28,
},
'invoice': {
'header': {
'type': 'string',
'value': self._('Invoice'),
},
'line': {
'value': self._render("line.invoice_id.number"),
},
'width': 18,
},
}
template.update(declaration._xls_template())
return template
def _get_ws_params(self, wb, data, declaration):
template = self._get_template(declaration)
if self.env.context.get('computation_lines'):
wl = declaration._xls_computation_line_fields()
report = 'computation'
else:
wl = declaration._xls_declaration_line_fields()
report = 'declaration'
title = self._get_title(declaration, report, format='normal')
title_short = self._get_title(declaration, report, format='short')
sheet_name = title_short[:31].replace('/', '-')
params = {
'ws_name': sheet_name,
'generate_ws_method': '_intrastat_report',
'title': title,
'wanted_list': wl,
'col_specs': template,
}
return [params]
def _get_title(self, declaration, report, format='normal'):
title = declaration.year_month
if format == 'normal':
if report == 'computation':
title += ' : ' + _('Computation Lines')
else:
title += ' : ' + _('Declaration Lines')
return title
def _report_title(self, ws, row_pos, ws_params, data, declaration):
return self._write_ws_title(ws, row_pos, ws_params)
def _empty_report(self, ws, row_pos, ws_params, data, declaration,
report):
if report == 'computation':
lines = _('Computation Lines')
else:
lines = _('Declaration Lines')
no_entries = _("No") + " " + lines + " " + _("for period %s") \
% declaration.year_month
ws.write_string(row_pos, 0, no_entries, self.format_left_bold)
def _intrastat_report(self, workbook, ws, ws_params, data, declaration):
ws.set_landscape()
ws.fit_to_pages(1, 0)
ws.set_header(self.xls_headers['standard'])
ws.set_footer(self.xls_footers['standard'])
self._set_column_width(ws, ws_params)
row_pos = 0
row_pos = self._report_title(ws, row_pos, ws_params, data, declaration)
if self.env.context.get('computation_lines'):
report = 'computation'
lines = declaration.computation_line_ids
else:
report = 'declaration'
lines = declaration.declaration_line_ids
if not lines:
return self._empty_report(
ws, row_pos, ws_params, data, declaration, report)
row_pos = self._write_line(
ws, row_pos, ws_params, col_specs_section='header',
default_format=self.format_theader_yellow_left)
ws.freeze_panes(row_pos, 0)
for line in lines:
row_pos = self._write_line(
ws, row_pos, ws_params, col_specs_section='line',
render_space={'line': line},
default_format=self.format_tcell_left)

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -17,7 +17,8 @@
<button name="generate_xml"
string="Generate XML Declaration File"
type="object"
attrs="{'invisible': [('state', '!=', 'draft')]}"/>
attrs="{'invisible': [('state', '!=', 'draft')]}"
invisible="context.get('generic_intrastat_product_declaration')"/>
<button name="done" string="Done" type="object" class="oe_highlight" states="draft"/>
<button name="back2draft" string="Back to Draft" type="object" states="done"/>
<field name="state" widget="statusbar"/>
@@ -25,7 +26,7 @@
<sheet string="Intrastat Product Declaration">
<div class="oe_title">
<h1>
<label string="Intrastat Product Declaration"/>
<span>Intrastat Product Declaration </span>
<field name="year_month" class="oe_inline"/>
</h1>
</div>
@@ -48,13 +49,25 @@
</group>
<notebook>
<page string="Transactions">
<header>
<button name="create_xls" type="object" string="Excel Export"
context="{'computation_lines': 1}"/>
</header>
<group name="computation_lines">
<field name="computation_line_ids" nolabel="1"/>
<field name="computation_line_ids"
context="{'type': type, 'reporting_level': reporting_level}"
nolabel="1"/>
</group>
</page>
<page string="Declaration Lines">
<header>
<button name="create_xls" type="object" string="Excel Export"
context="{'declaration_lines': 1}"/>
</header>
<group name="declaration_lines">
<field name="declaration_line_ids" nolabel="1"/>
<field name="declaration_line_ids"
context="{'type': type, 'reporting_level': reporting_level}"
nolabel="1"/>
</group>
</page>
<page string="Notes">
@@ -79,7 +92,7 @@
<field name="revision"/>
<field name="type"/>
<field name="num_decl_lines"/>
<field name="total_amount" sum="1"/>
<field name="total_amount" sum="Total amount"/>
<field name="currency_id"/>
<field name="state"/>
</tree>
@@ -143,6 +156,7 @@
</div>
<field name="suppl_unit_qty"/>
<field name="intrastat_unit_id"/>
<field name="type" invisible="1"/>
<field name="reporting_level" invisible="1"/>
<field name="transport_id"
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"/>
@@ -168,10 +182,10 @@
<field name="product_id"/>
<field name="hs_code_id"/>
<field name="src_dest_country_id" domain="[('intrastat', '=', True)]"/>
<field name="amount_company_currency" sum="1"/>
<field name="amount_accessory_cost_company_currency" sum="1"/>
<field name="amount_company_currency"/>
<field name="amount_accessory_cost_company_currency"/>
<field name="transaction_id"/>
<field name="weight" sum="1"/>
<field name="weight"/>
<field name="suppl_unit_qty"
attrs="{'invisible': [('intrastat_unit_id', '=', False)], 'required': [('intrastat_unit_id', '!=', False)]}"/>
<field name="intrastat_unit_id"/>
@@ -180,6 +194,7 @@
<field name="region_id" invisible="1"/>
<field name="product_origin_country_id" invisible="1" string="Product C/O"/>
<field name="invoice_id"/>
<field name="type" invisible="1"/>
<field name="reporting_level" invisible="1"/>
</tree>
</field>
@@ -207,6 +222,7 @@
</div>
<field name="suppl_unit_qty"/>
<field name="intrastat_unit_id"/>
<field name="type" invisible="1"/>
<field name="reporting_level" invisible="1"/>
<field name="transport_id"
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"/>
@@ -230,11 +246,12 @@
invisible="not context.get('intrastat_product_declaration_line_main_view')"/>
<field name="hs_code_id"/>
<field name="src_dest_country_id" domain="[('intrastat', '=', True)]"/>
<field name="amount_company_currency" sum="1"/>
<field name="amount_company_currency"/>
<field name="transaction_id"/>
<field name="weight" sum="1"/>
<field name="weight"/>
<field name="suppl_unit_qty"/>
<field name="intrastat_unit_id"/>
<field name="type" invisible="1"/>
<field name="reporting_level" invisible="1"/>
<field name="transport_id"
attrs="{'required': [('reporting_level', '=', 'extended')], 'invisible': [('reporting_level', '!=', 'extended')]}"/>

View File

@@ -1,62 +1,82 @@
<?xml version="1.0"?>
<!--
© 2018 brain-tec AG (Kumar Aberer <kumar.aberer@braintec-group.com>)
© 2019 Noviat (www.noviat.com)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<record id="view_res_config_settings" model="ir.ui.view">
<field name="name">intrastat.account.config.settings.form</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="intrastat_base.view_intrastat_res_config_settings"/>
<field name="arch" type="xml">
<record id="view_res_config_settings" model="ir.ui.view">
<field name="name">intrastat.account.config.settings.form</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="intrastat_base.view_intrastat_res_config_settings"/>
<field name="arch" type="xml">
<xpath expr="//div[@id='intrastat']" position="after">
<div id="intrastat_content_grp" position="inside">
<div class="row mt16">
<label for="intrastat_arrivals" class="col-md-5 o_light_label"/>
<field name="intrastat_arrivals"/>
</div>
<div class="row mt16">
<label for="intrastat_dispatches" class="col-md-5 o_light_label"/>
<field name="intrastat_dispatches"/>
</div>
<div class="row mt16">
<label for="intrastat_transport_id" class="col-md-5 o_light_label"/>
<field name="intrastat_transport_id"/>
</div>
<div class="row mt16">
<label for="intrastat_incoterm_id" class="col-md-5 o_light_label"/>
<field name="intrastat_incoterm_id"/>
</div>
<div class="row mt16">
<label for="intrastat_transaction_out_invoice" class="col-md-5 o_light_label"/>
<field name="intrastat_transaction_out_invoice"/>
</div>
<div class="row mt16">
<label for="intrastat_transaction_out_refund" class="col-md-5 o_light_label"/>
<field name="intrastat_transaction_out_refund"/>
</div>
<div class="row mt16">
<label for="intrastat_transaction_in_invoice" class="col-md-5 o_light_label"/>
<field name="intrastat_transaction_in_invoice"/>
</div>
<div class="row mt16">
<label for="intrastat_transaction_in_refund" class="col-md-5 o_light_label"/>
<field name="intrastat_transaction_in_refund"/>
</div>
<div id="intrastat_accessory_costs" class="row mt16" invisible="1">
<label for="intrastat_accessory_costs" class="col-md-5 o_light_label"/>
<field name="intrastat_accessory_costs"/>
</div>
<div class="row mt16" id="intrastat_region" invisible="1">
<label for="intrastat_region_id" class="col-md-5 o_light_label"/>
<field name="intrastat_region_id"/>
</div>
<field name="country_id" invisible="1"/>
<field name="country_code" invisible="1"/>
<div class="row mt16 o_settings_container" id="intrastat-product">
<div class="col-xs-12 col-md-12 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<div class="row">
<label for="intrastat_arrivals" class="col-md-5 o_light_label"/>
<field name="intrastat_arrivals"/>
</div>
<div class="row">
<label for="intrastat_dispatches" class="col-md-5 o_light_label"/>
<field name="intrastat_dispatches"/>
</div>
<div class="row">
<label for="intrastat_transport_id" class="col-md-5 o_light_label"/>
<field name="intrastat_transport_id"/>
</div>
<div class="row">
<label for="intrastat_incoterm_id" class="col-md-5 o_light_label"/>
<field name="intrastat_incoterm_id"/>
</div>
<div class="row">
<label for="intrastat_transaction_out_invoice" class="col-md-5 o_light_label"/>
<field name="intrastat_transaction_out_invoice"/>
</div>
<div class="row">
<label for="intrastat_transaction_out_refund" class="col-md-5 o_light_label"/>
<field name="intrastat_transaction_out_refund"/>
</div>
<div class="row">
<label for="intrastat_transaction_in_invoice" class="col-md-5 o_light_label"/>
<field name="intrastat_transaction_in_invoice"/>
</div>
<div class="row">
<label for="intrastat_transaction_in_refund" class="col-md-5 o_light_label"/>
<field name="intrastat_transaction_in_refund"/>
</div>
<div class="row" attrs="{'invisible': [('country_code', 'not in', ['BE'])]}">
<label for="intrastat_region_id" class="col-md-5 o_light_label"/>
<field name="intrastat_region_id" domain="[('country_id','=', country_id)]"/>
</div>
</div>
<div class="o_setting_left_pane">
<field name="intrastat_accessory_costs"
attrs="{'invisible': [('country_code', 'in', ['BE'])]}"/>
</div>
<div class="o_setting_right_pane">
<div class="row">
<label for="intrastat_accessory_costs" class="col-md-12 o_light_label"
attrs="{'invisible': [('country_code', 'in', ['BE'])]}"/>
</div>
</div>
</field>
</record>
</div>
</div>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,55 @@
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: https://www.gnu.org/licenses/agpl
:alt: License: AGPL-3
=====================================
Generic Intrastat Product Declaration
=====================================
This module adds a menu entry for a Generic Intrastat Product Declaration.
This is useful to cover countries for which there is no localization module.
Installation
============
There is no specific installation procedure for this module.
Configuration and Usage
=======================
.. 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
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/intrastat/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smash it by providing detailed and welcomed feedback.
Credits
=======
Contributors
------------
* Luc De Meyer <luc.demeyer@noviat.com>
Do not contact contributors directly about support or help with technical issues.
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
: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.
To contribute to this module, please visit http://odoo-community.org.

View File

View File

@@ -0,0 +1,20 @@
# Copyright 2009-2018 Noviat.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Generic Intrastat Product Declaration',
'version': '11.0.1.0.0',
'category': 'Accounting & Finance',
'website': 'https://github.com/OCA/intrastat',
'author': 'Noviat,'
'Odoo Community Association (OCA)',
'license': 'AGPL-3',
'installable': True,
'depends': [
'intrastat_product',
],
'data': [
'security/intrastat_security.xml',
'views/intrastat_product.xml'
],
}

View File

@@ -0,0 +1,22 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * intrastat_product_generic
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 11.0\n"
"Report-Msgid-Bugs-To: \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_generic
#: model:ir.actions.act_window,name:intrastat_product_generic.intrastat_product_declaration_action_generic
#: model:ir.ui.menu,name:intrastat_product_generic.intrastat_product_declaration_menu_generic
#: model:res.groups,name:intrastat_product_generic.group_intrastat_product_generic
msgid "Generic Intrastat Product Declaration"
msgstr ""

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<record id="group_intrastat_product_generic" model="res.groups">
<field name="name">Generic Intrastat Product Declaration</field>
</record>
<record id="base.user_root" model="res.users">
<field eval="[(4, ref('group_intrastat_product_generic'))]" name="groups_id"/>
</record>
</odoo>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<odoo>
<record id="intrastat_product_declaration_action_generic" model="ir.actions.act_window">
<field name="name">Generic Intrastat Product Declaration</field>
<field name="res_model">intrastat.product.declaration</field>
<field name="view_mode">tree,form,graph</field>
<field name="context">{'generic_intrastat_product_declaration': 1}</field>
</record>
<menuitem id="intrastat_product_declaration_menu_generic"
parent="intrastat_base.menu_intrastat_base_root"
action="intrastat_product_declaration_action_generic"
groups="group_intrastat_product_generic"/>
</odoo>

View File

@@ -1,15 +1,16 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_harmonized_system
# * product_harmonized_system
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 11.0\n"
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-12-29 10:15+0000\n"
"PO-Revision-Date: 2018-12-29 10:15+0000\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"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
@@ -23,12 +24,15 @@ msgstr "Actif"
#. module: product_harmonized_system
#: model:hs.code,description:product_harmonized_system.84715000
msgid "Automatic data-processing machines (computers)"
msgstr "Automatic data-processing machines (computers)"
msgstr ""
#. module: product_harmonized_system
#: model:ir.model.fields,help:product_harmonized_system.field_hs_code_local_code
msgid "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."
msgstr "Code utilisé pour la DEB. Le code national commence par les 6 numéros du Système Harmonisé et est suivi généralement par un ou plusieurs numéros d'extention."
msgid ""
"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."
msgstr ""
#. module: product_harmonized_system
#: model:ir.model.fields,field_description:product_harmonized_system.field_hs_code_company_id
@@ -45,7 +49,7 @@ msgstr "Pays d'origine"
#: model:ir.model.fields,help:product_harmonized_system.field_product_product_origin_country_id
#: model:ir.model.fields,help:product_harmonized_system.field_product_template_origin_country_id
msgid "Country of origin of the product i.e. product 'made in ____'."
msgstr "Pays d'origine de l'article i.e. produit 'made in ____'."
msgstr ""
#. module: product_harmonized_system
#: model:ir.model.fields,field_description:product_harmonized_system.field_hs_code_create_uid
@@ -65,7 +69,7 @@ msgstr "Description"
#. module: product_harmonized_system
#: model:ir.model.fields,field_description:product_harmonized_system.field_hs_code_display_name
msgid "Display Name"
msgstr "Afficher le nom"
msgstr "Nom affiché"
#. module: product_harmonized_system
#: model:ir.model,name:product_harmonized_system.model_hs_code
@@ -80,24 +84,32 @@ msgstr "Code S.H."
#. module: product_harmonized_system
#: model:ir.actions.act_window,name:product_harmonized_system.hs_code_action
#: model:ir.ui.view,arch_db:product_harmonized_system.hs_code_view_tree
#, fuzzy
msgid "H.S. Codes"
msgstr "Codes S.H."
msgstr "Code S.H."
#. module: product_harmonized_system
#: model:ir.model.fields,help:product_harmonized_system.field_product_category_hs_code_id
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 "Code du système harmonisé. Si ce code n'est pas renseigné sur l'article, il sera lu ici, sur la catégorie d'article associée."
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
#: model:ir.model.fields,help:product_harmonized_system.field_product_product_hs_code_id
#: model:ir.model.fields,help:product_harmonized_system.field_product_template_hs_code_id
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 "Code du système harmonisé. La nomenclature est publiée par l'organisation mondiale des douanes, cf http://www.wcoomd.org/. Vous pouvez laisser ce champ vide et renseigner le code S.H. sur la catégorie d'article."
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
#: model:ir.model.fields,help:product_harmonized_system.field_hs_code_hs_code
msgid "Harmonized System code (6 digits). Full list is available from the World Customs Organisation, see http://www.wcoomd.org"
msgstr "Code du système harmonisé (6 chiffres). Liste complète publiée par l'organisation mondiale des douanes, cf http://www.wcoomd.org"
msgid ""
"Harmonized System code (6 digits). Full list is available from the World "
"Customs Organisation, see http://www.wcoomd.org"
msgstr ""
#. module: product_harmonized_system
#: model:ir.model.fields,field_description:product_harmonized_system.field_hs_code_id
@@ -111,6 +123,7 @@ msgstr "Propriétés pour l'import/export"
#. module: product_harmonized_system
#: model:ir.model.fields,field_description:product_harmonized_system.field_hs_code___last_update
#, fuzzy
msgid "Last Modified on"
msgstr "Dernière modification le"
@@ -132,23 +145,25 @@ msgstr "Code local"
#. module: product_harmonized_system
#: model:hs.code,description:product_harmonized_system.85340090
msgid "Printed circuits"
msgstr "Printed circuits"
msgstr ""
#. module: product_harmonized_system
#: model:ir.model,name:product_harmonized_system.model_product_product
#, fuzzy
msgid "Product"
msgstr "Article"
msgstr "Catégorie d'articles"
#. 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
#, fuzzy
msgid "Product Categories"
msgstr "Catégories d'articles"
msgstr "Catégorie d'articles"
#. module: product_harmonized_system
#: model:ir.model,name:product_harmonized_system.model_product_category
msgid "Product Category"
msgstr "Catégorie d'article"
msgstr "Catégorie d'articles"
#. module: product_harmonized_system
#: model:ir.model,name:product_harmonized_system.model_product_template
@@ -159,25 +174,38 @@ msgstr "Modèle d'article"
#: model:ir.model.fields,field_description:product_harmonized_system.field_hs_code_product_tmpl_ids
#: model:ir.ui.view,arch_db:product_harmonized_system.hs_code_view_form
msgid "Products"
msgstr "Articles"
msgstr ""
#. module: product_harmonized_system
#: model:ir.ui.view,arch_db:product_harmonized_system.hs_code_view_search
#, fuzzy
msgid "Search H.S. Codes"
msgstr "Rechercher parmi les codes S.H."
msgstr "Recherche dans les codes S.H."
#. module: product_harmonized_system
#: model:ir.model.fields,help:product_harmonized_system.field_hs_code_description
msgid "Short text description of the H.S. category"
msgstr "Courte description du code S.H."
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 "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é !"
#~ 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"
#~ msgid "HS Code"
#~ msgstr "Code S.H."
#~ msgid "HS Codes"
#~ msgstr "Codes S.H."

View File

@@ -1,10 +1,10 @@
# © 2011-2016 Akretion (http://www.akretion.com)
# © 2009-2016 Noviat (http://www.noviat.com)
# Copyright 2011-2016 Akretion (http://www.akretion.com)
# Copyright 2009-2016 Noviat (http://www.noviat.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Luc de Meyer <info@noviat.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api
from odoo import api, fields, models
class HSCode(models.Model):
@@ -31,12 +31,19 @@ class HSCode(models.Model):
"has a few additional digits to extend the H.S. code.")
active = fields.Boolean(default=True)
company_id = fields.Many2one(
'res.company', string='Company',
default=lambda self: self.env['res.company']._company_default_get())
'res.company', string='Company', readonly=True, required=True,
default=lambda self: self.env['res.company']._company_default_get(
'hs.code'))
product_categ_ids = fields.One2many(
'product.category', 'hs_code_id', string='Product Categories')
comodel_name='product.category',
inverse_name='hs_code_id',
string='Product Categories',
readonly=True)
product_tmpl_ids = fields.One2many(
'product.template', 'hs_code_id', string='Products')
comodel_name='product.template',
inverse_name='hs_code_id',
string='Products',
readonly=True)
@api.multi
@api.depends('local_code')

View File

@@ -1,10 +1,10 @@
# © 2011-2016 Akretion (http://www.akretion.com)
# © 2009-2016 Noviat (http://www.noviat.com)
# Copyright 2011-2016 Akretion (http://www.akretion.com)
# Copyright 2009-2016 Noviat (http://www.noviat.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Luc de Meyer <info@noviat.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api
from odoo import api, fields, models
class ProductCategory(models.Model):

View File

@@ -1,10 +1,10 @@
# © 2011-2016 Akretion (http://www.akretion.com)
# © 2009-2016 Noviat (http://www.noviat.com)
# Copyright 2011-2016 Akretion (http://www.akretion.com)
# Copyright 2009-2016 Noviat (http://www.noviat.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Luc de Meyer <info@noviat.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api
from odoo import api, fields, models
class ProductTemplate(models.Model):