mirror of
https://github.com/OCA/intrastat-extrastat.git
synced 2025-02-16 17:13:41 +02:00
pre-commit
This commit is contained in:
committed by
Alexis de Lattre
parent
03bf6c9641
commit
7b15ab026c
@@ -4,26 +4,24 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Intrastat Reporting Base',
|
||||
'version': '13.0.1.0.0',
|
||||
'category': 'Intrastat',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Base module for Intrastat reporting',
|
||||
'author': 'Akretion,Noviat,Odoo Community Association (OCA)',
|
||||
'website': 'https://github.com/OCA/intrastat',
|
||||
'depends': ['base_vat', 'account'],
|
||||
'excludes': ['account_intrastat'],
|
||||
'data': [
|
||||
'data/country_data.xml',
|
||||
'views/product_template.xml',
|
||||
'views/res_partner.xml',
|
||||
'views/res_country.xml',
|
||||
'views/account_tax.xml',
|
||||
'views/res_config_settings.xml',
|
||||
'views/intrastat.xml',
|
||||
"name": "Intrastat Reporting Base",
|
||||
"version": "13.0.1.0.0",
|
||||
"category": "Intrastat",
|
||||
"license": "AGPL-3",
|
||||
"summary": "Base module for Intrastat reporting",
|
||||
"author": "Akretion,Noviat,Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/intrastat",
|
||||
"depends": ["base_vat", "account"],
|
||||
"excludes": ["account_intrastat"],
|
||||
"data": [
|
||||
"data/country_data.xml",
|
||||
"views/product_template.xml",
|
||||
"views/res_partner.xml",
|
||||
"views/res_country.xml",
|
||||
"views/account_tax.xml",
|
||||
"views/res_config_settings.xml",
|
||||
"views/intrastat.xml",
|
||||
],
|
||||
'demo': [
|
||||
'demo/intrastat_demo.xml',
|
||||
],
|
||||
'installable': True,
|
||||
"demo": ["demo/intrastat_demo.xml"],
|
||||
"installable": True,
|
||||
}
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
# Copyright 2011-2019 Akretion France (http://www.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 AccountTax(models.Model):
|
||||
_inherit = "account.tax"
|
||||
|
||||
exclude_from_intrastat_if_present = fields.Boolean(
|
||||
string='Exclude invoice line from intrastat if this tax is present',
|
||||
string="Exclude invoice line from intrastat if this tax is present",
|
||||
help="If this tax is present on an invoice line, this invoice "
|
||||
"line will be skipped when generating Intrastat Product or "
|
||||
"Service lines from invoices.")
|
||||
"Service lines from invoices.",
|
||||
)
|
||||
|
||||
|
||||
class AccountTaxTemplate(models.Model):
|
||||
_inherit = "account.tax.template"
|
||||
|
||||
exclude_from_intrastat_if_present = fields.Boolean(
|
||||
string='Exclude invoice line from intrastat if this tax is present',
|
||||
string="Exclude invoice line from intrastat if this tax is present",
|
||||
help="If this tax is present on an invoice line, this invoice "
|
||||
"line will be skipped when generating Intrastat Product or "
|
||||
"Service lines from invoices.")
|
||||
"Service lines from invoices.",
|
||||
)
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
# Copyright 2009-2019 Noviat (http://www.noviat.com)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from io import BytesIO
|
||||
from lxml import etree
|
||||
from sys import exc_info
|
||||
import base64
|
||||
from traceback import format_exception
|
||||
import logging
|
||||
from io import BytesIO
|
||||
from sys import exc_info
|
||||
from traceback import format_exception
|
||||
|
||||
from odoo import api, fields, models, tools, _
|
||||
from lxml import etree
|
||||
|
||||
from odoo import _, api, fields, models, tools
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -20,7 +21,7 @@ class IntrastatCommon(models.AbstractModel):
|
||||
_description = "Common functions for intrastat reports for products "
|
||||
"and services"
|
||||
|
||||
@api.depends('declaration_line_ids.amount_company_currency')
|
||||
@api.depends("declaration_line_ids.amount_company_currency")
|
||||
def _compute_numbers(self):
|
||||
for this in self:
|
||||
total_amount = 0 # it is an integer
|
||||
@@ -39,8 +40,8 @@ class IntrastatCommon(models.AbstractModel):
|
||||
company = this.company_id
|
||||
if not company.country_id:
|
||||
raise UserError(
|
||||
_("The country is not set on the company '%s'.")
|
||||
% company.name)
|
||||
_("The country is not set on the company '%s'.") % company.name
|
||||
)
|
||||
return True
|
||||
|
||||
def _check_generate_xml(self):
|
||||
@@ -48,64 +49,66 @@ class IntrastatCommon(models.AbstractModel):
|
||||
if not this.company_id.partner_id.vat:
|
||||
raise UserError(
|
||||
_("The VAT number is not set for the partner '%s'.")
|
||||
% this.company_id.partner_id.name)
|
||||
% this.company_id.partner_id.name
|
||||
)
|
||||
return True
|
||||
|
||||
@api.model
|
||||
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, mode='rb'))
|
||||
"""Validate the XML file against the XSD"""
|
||||
xsd_etree_obj = etree.parse(tools.file_open(xsd_file, mode="rb"))
|
||||
official_schema = etree.XMLSchema(xsd_etree_obj)
|
||||
try:
|
||||
t = etree.parse(BytesIO(xml_string))
|
||||
official_schema.assertValid(t)
|
||||
except (etree.XMLSchemaParseError, etree.DocumentInvalid) as e:
|
||||
logger.warning(
|
||||
"The XML file is invalid against the XML Schema Definition")
|
||||
logger.warning("The XML file is invalid against the XML Schema Definition")
|
||||
logger.warning(xml_string)
|
||||
logger.warning(e)
|
||||
usererror = '%s\n\n%s' % (e.__class__.__name__, str(e))
|
||||
usererror = "{}\n\n{}".format(e.__class__.__name__, str(e))
|
||||
raise UserError(usererror)
|
||||
except Exception:
|
||||
error = _("Unknown Error")
|
||||
tb = ''.join(format_exception(*exc_info()))
|
||||
error += '\n%s' % tb
|
||||
tb = "".join(format_exception(*exc_info()))
|
||||
error += "\n%s" % tb
|
||||
logger.warning(error)
|
||||
raise UserError(error)
|
||||
|
||||
def _attach_xml_file(self, xml_string, declaration_name):
|
||||
'''Attach the XML file to the report_intrastat_product/service
|
||||
object'''
|
||||
"""Attach the XML file to the report_intrastat_product/service
|
||||
object"""
|
||||
self.ensure_one()
|
||||
filename = '%s_%s.xml' % (self.year_month, declaration_name)
|
||||
attach = self.env['ir.attachment'].create({
|
||||
'name': filename,
|
||||
'res_id': self.id,
|
||||
'res_model': self._name,
|
||||
'datas': base64.encodestring(xml_string),
|
||||
'datas_fname': filename})
|
||||
filename = "{}_{}.xml".format(self.year_month, declaration_name)
|
||||
attach = self.env["ir.attachment"].create(
|
||||
{
|
||||
"name": filename,
|
||||
"res_id": self.id,
|
||||
"res_model": self._name,
|
||||
"datas": base64.encodestring(xml_string),
|
||||
"datas_fname": filename,
|
||||
}
|
||||
)
|
||||
return attach.id
|
||||
|
||||
def _unlink_attachments(self):
|
||||
atts = self.env['ir.attachment'].search(
|
||||
[('res_model', '=', self._name),
|
||||
('res_id', '=', self.id)])
|
||||
atts = self.env["ir.attachment"].search(
|
||||
[("res_model", "=", self._name), ("res_id", "=", self.id)]
|
||||
)
|
||||
atts.unlink()
|
||||
|
||||
@api.model
|
||||
def _open_attach_view(self, attach_id, title='XML file'):
|
||||
'''Returns an action which opens the form view of the
|
||||
corresponding attachement'''
|
||||
def _open_attach_view(self, attach_id, title="XML file"):
|
||||
"""Returns an action which opens the form view of the
|
||||
corresponding attachement"""
|
||||
action = {
|
||||
'name': title,
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'ir.attachment',
|
||||
'type': 'ir.actions.act_window',
|
||||
'nodestroy': True,
|
||||
'target': 'current',
|
||||
'res_id': attach_id,
|
||||
"name": title,
|
||||
"view_type": "form",
|
||||
"view_mode": "form",
|
||||
"res_model": "ir.attachment",
|
||||
"type": "ir.actions.act_window",
|
||||
"nodestroy": True,
|
||||
"target": "current",
|
||||
"res_id": attach_id,
|
||||
}
|
||||
return action
|
||||
|
||||
@@ -128,20 +131,23 @@ class IntrastatCommon(models.AbstractModel):
|
||||
if this.company_id.intrastat_remind_user_ids:
|
||||
mail_template.send_mail(this.id)
|
||||
logger.info(
|
||||
'Intrastat Reminder email has been sent (XMLID: %s).'
|
||||
% mail_template_xmlid)
|
||||
"Intrastat Reminder email has been sent (XMLID: %s)."
|
||||
% mail_template_xmlid
|
||||
)
|
||||
else:
|
||||
logger.warning(
|
||||
'The list of users receiving the Intrastat Reminder is '
|
||||
'empty on company %s' % this.company_id.name)
|
||||
"The list of users receiving the Intrastat Reminder is "
|
||||
"empty on company %s" % this.company_id.name
|
||||
)
|
||||
return True
|
||||
|
||||
def unlink(self):
|
||||
for intrastat in self:
|
||||
if intrastat.state == 'done':
|
||||
if intrastat.state == "done":
|
||||
raise UserError(
|
||||
_('Cannot delete the declaration %s '
|
||||
'because it is in Done state') % self.year_month)
|
||||
_("Cannot delete the declaration %s " "because it is in Done state")
|
||||
% self.year_month
|
||||
)
|
||||
return super(IntrastatCommon, self).unlink()
|
||||
|
||||
|
||||
@@ -149,9 +155,10 @@ class IntrastatResultView(models.TransientModel):
|
||||
"""
|
||||
Transient Model to display Intrastat Report results
|
||||
"""
|
||||
_name = 'intrastat.result.view'
|
||||
_description = 'Pop-up to show errors on intrastat report generation'
|
||||
|
||||
_name = "intrastat.result.view"
|
||||
_description = "Pop-up to show errors on intrastat report generation"
|
||||
|
||||
note = fields.Text(
|
||||
string='Notes', readonly=True,
|
||||
default=lambda self: self._context.get('note'))
|
||||
string="Notes", readonly=True, default=lambda self: self._context.get("note")
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Copyright 2010-2016 Akretion (<alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
@@ -9,18 +9,22 @@ class ProductTemplate(models.Model):
|
||||
_inherit = "product.template"
|
||||
|
||||
is_accessory_cost = fields.Boolean(
|
||||
string='Is accessory cost',
|
||||
string="Is accessory cost",
|
||||
help="Activate this option for shipping costs, packaging "
|
||||
"costs and all services related to the sale of products. "
|
||||
"This option is used for Intrastat reports.")
|
||||
"This option is used for Intrastat reports.",
|
||||
)
|
||||
|
||||
@api.constrains('type', 'is_accessory_cost')
|
||||
@api.constrains("type", "is_accessory_cost")
|
||||
def _check_accessory_cost(self):
|
||||
for this in self:
|
||||
if this.is_accessory_cost and this.type != 'service':
|
||||
if this.is_accessory_cost and this.type != "service":
|
||||
raise ValidationError(
|
||||
_("The option 'Is accessory cost?' should only be "
|
||||
_(
|
||||
"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))
|
||||
"'%s'"
|
||||
)
|
||||
% (this.name, this.type)
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# @author: <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
@@ -10,29 +10,32 @@ class ResCompany(models.Model):
|
||||
_inherit = "res.company"
|
||||
|
||||
intrastat_remind_user_ids = fields.Many2many(
|
||||
'res.users', column1='company_id', column2='user_id',
|
||||
"res.users",
|
||||
column1="company_id",
|
||||
column2="user_id",
|
||||
string="Users Receiving the Intrastat Reminder",
|
||||
help="List of Odoo users who will receive a notification to "
|
||||
"remind them about the Intrastat declaration.")
|
||||
"remind them about the Intrastat declaration.",
|
||||
)
|
||||
intrastat_email_list = fields.Char(
|
||||
compute='_compute_intrastat_email_list',
|
||||
string='List of emails of Users Receiving the Intrastat Reminder')
|
||||
compute="_compute_intrastat_email_list",
|
||||
string="List of emails of Users Receiving the Intrastat Reminder",
|
||||
)
|
||||
|
||||
@api.depends(
|
||||
'intrastat_remind_user_ids', 'intrastat_remind_user_ids.email')
|
||||
@api.depends("intrastat_remind_user_ids", "intrastat_remind_user_ids.email")
|
||||
def _compute_intrastat_email_list(self):
|
||||
for this in self:
|
||||
emails = []
|
||||
for user in this.intrastat_remind_user_ids:
|
||||
if user.email:
|
||||
emails.append(user.email)
|
||||
this.intrastat_email_list = ','.join(emails)
|
||||
this.intrastat_email_list = ",".join(emails)
|
||||
|
||||
@api.constrains('intrastat_remind_user_ids')
|
||||
@api.constrains("intrastat_remind_user_ids")
|
||||
def _check_intrastat_remind_users(self):
|
||||
for this in self:
|
||||
for user in this.intrastat_remind_user_ids:
|
||||
if not user.email:
|
||||
raise ValidationError(
|
||||
_("Missing e-mail address on user '%s'.") %
|
||||
(user.name))
|
||||
_("Missing e-mail address on user '%s'.") % (user.name)
|
||||
)
|
||||
|
||||
@@ -6,7 +6,8 @@ from odoo import fields, models
|
||||
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
_inherit = 'res.config.settings'
|
||||
_inherit = "res.config.settings"
|
||||
|
||||
intrastat_remind_user_ids = fields.Many2many(
|
||||
related='company_id.intrastat_remind_user_ids', readonly=False)
|
||||
related="company_id.intrastat_remind_user_ids", readonly=False
|
||||
)
|
||||
|
||||
@@ -6,8 +6,8 @@ from odoo import fields, models
|
||||
|
||||
|
||||
class ResCountry(models.Model):
|
||||
_inherit = 'res.country'
|
||||
_inherit = "res.country"
|
||||
|
||||
intrastat = fields.Boolean(
|
||||
string='EU Country',
|
||||
help="Set to True for all European Union countries.")
|
||||
string="EU Country", help="Set to True for all European Union countries."
|
||||
)
|
||||
|
||||
@@ -6,17 +6,15 @@ class TestIntrastatBase(TransactionCase):
|
||||
|
||||
def test_10_countries(self):
|
||||
# check if only EU countries have the 'intrastat' bit set
|
||||
france = self.env.ref('base.fr')
|
||||
france = self.env.ref("base.fr")
|
||||
self.assertTrue(france.intrastat)
|
||||
brazil = self.env.ref('base.br')
|
||||
brazil = self.env.ref("base.br")
|
||||
self.assertFalse(brazil.intrastat)
|
||||
|
||||
def test_20_company(self):
|
||||
# add 'Demo user' to intrastat_remind_user_ids
|
||||
demo_user = self.env.ref('base.user_demo')
|
||||
demo_company = self.env.ref('base.main_company')
|
||||
demo_company.write({
|
||||
'intrastat_remind_user_ids': [(6, False, [demo_user.id])]
|
||||
})
|
||||
demo_user = self.env.ref("base.user_demo")
|
||||
demo_company = self.env.ref("base.main_company")
|
||||
demo_company.write({"intrastat_remind_user_ids": [(6, False, [demo_user.id])]})
|
||||
# then check if intrastat_email_list contains the email of the user
|
||||
self.assertEquals(demo_company.intrastat_email_list, demo_user.email)
|
||||
|
||||
Reference in New Issue
Block a user