Make dutch ICP report workable on odoo 8.0 [FIX] Some small changes in base, to make check_generate_lines better reusable (no need to force currency field on report), and do away with '_' before method name, as method should not be private, as it is called from other classes.

This commit is contained in:
Ronald Portier
2015-02-04 20:11:31 +01:00
committed by Alexis de Lattre
parent a8510ae4d8
commit 9ea20f0d5e

View File

@@ -1,8 +1,8 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
############################################################################## ##############################################################################
# #
# Report intrastat base module for Odoo # Report intrastat base module for OpenERP
# Copyright (C) 2010-2014 Akretion (http://www.akretion.com/). # Copyright (C) 2010-2013 Akretion (http://www.akretion.com/).
# @author Alexis de Lattre <alexis.delattre@akretion.com> # @author Alexis de Lattre <alexis.delattre@akretion.com>
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
@@ -20,9 +20,9 @@
# #
############################################################################## ##############################################################################
from openerp import models, api, tools, _ from openerp.osv import orm
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT from openerp.tools.translate import _
from openerp.exceptions import Warning, ValidationError from openerp import tools
from datetime import datetime from datetime import datetime
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
import logging import logging
@@ -30,64 +30,81 @@ import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class ReportIntrastatCommon(models.AbstractModel): class report_intrastat_common(orm.TransientModel):
_name = "report.intrastat.common" _name = "report.intrastat.common"
_description = "Common functions for intrastat reports for products " _description = "Common functions for intrastat reports for products "
"and services" "and services"
@api.one def _compute_numbers(self, cr, uid, ids, object, context=None):
@api.depends( result = {}
'intrastat_line_ids', 'intrastat_line_ids.amount_company_currency') for intrastat in object.browse(cr, uid, ids, context=context):
def _compute_numbers(self): total_amount = 0.0
total_amount = 0.0 num_lines = 0
num_lines = 0 for line in intrastat.intrastat_line_ids:
for line in self.intrastat_line_ids: total_amount += line.amount_company_currency
total_amount += line.amount_company_currency num_lines += 1
num_lines += 1 result[intrastat.id] = {
self.num_lines = num_lines 'num_lines': num_lines,
self.total_amount = total_amount 'total_amount': total_amount,
}
return result
@api.one def _compute_dates(self, cr, uid, ids, object, context=None):
@api.depends('start_date') result = {}
def _compute_dates(self): for intrastat in object.browse(cr, uid, ids, context=context):
start_date_dt = datetime.strptime( start_date_datetime = datetime.strptime(
self.start_date, DEFAULT_SERVER_DATE_FORMAT) intrastat.start_date, '%Y-%m-%d')
self.end_date = datetime.strftime( end_date_str = datetime.strftime(
start_date_dt + relativedelta(day=31), DEFAULT_SERVER_DATE_FORMAT) start_date_datetime + relativedelta(day=31), '%Y-%m-%d')
self.year_month = start_date_dt.strftime('%Y-%m') result[intrastat.id] = {
'end_date': end_date_str,
'year_month': start_date_datetime.strftime('%Y-%m'),
}
return result
@api.one def _check_start_date(self, cr, uid, ids, object, context=None):
@api.constrains('start_date')
def _check_start_date(self):
'''Check that the start date is the first day of the month''' '''Check that the start date is the first day of the month'''
datetime_to_check = datetime.strptime( for date_to_check in object.read(
self.start_date, DEFAULT_SERVER_DATE_FORMAT) cr, uid, ids, ['start_date'], context=context):
if datetime_to_check.day != 1: datetime_to_check = datetime.strptime(
return ValidationError( date_to_check['start_date'], '%Y-%m-%d')
_('The start date must be the first day of the month')) if datetime_to_check.day != 1:
return False
return True
@api.one def check_generate_lines(self, cr, uid, intrastat, context=None):
def _check_generate_lines(self): """Check wether all requirements are met for generating lines."""
if not self.company_id.country_id: if not intrastat.company_id:
raise Warning( # Should not be possible, but just in case:
raise orm.except_orm(
_('Error :'),
_("Company not yet set on intrastat report.")
)
company_obj = intrastat.company_id # Simplify references
if not company_obj.country_id:
raise orm.except_orm(
_('Error :'),
_("The country is not set on the company '%s'.") _("The country is not set on the company '%s'.")
% self.company_id.name) % company_obj.name
if self.currency_id.name != 'EUR': )
raise Warning( if not company_obj.currency_id.name == 'EUR':
raise orm.except_orm(
_('Error :'),
_("The company currency must be 'EUR', but is currently '%s'.") _("The company currency must be 'EUR', but is currently '%s'.")
% self.currency_id.name) % company_obj.currency_id.name
)
return True return True
@api.one def _check_generate_xml(self, cr, uid, intrastat, context=None):
def _check_generate_xml(self): if not intrastat.company_id.partner_id.vat:
if not self.company_id.partner_id.vat: raise orm.except_orm(
raise Warning( _('Error :'),
_("The VAT number is not set for the partner '%s'.") _("The VAT number is not set for the partner '%s'.")
% self.company_id.partner_id.name) % intrastat.company_id.partner_id.name)
return True return True
@api.model def _check_xml_schema(
def _check_xml_schema(self, xml_root, xml_string, xsd_file): self, cr, uid, xml_root, xml_string, xsd_file, context=None):
'''Validate the XML file against the XSD''' '''Validate the XML file against the XSD'''
from lxml import etree from lxml import etree
xsd_etree_obj = etree.parse( xsd_etree_obj = etree.parse(
@@ -97,12 +114,13 @@ class ReportIntrastatCommon(models.AbstractModel):
official_schema.assertValid(xml_root) official_schema.assertValid(xml_root)
except Exception, e: except Exception, e:
# if the validation of the XSD fails, we arrive here # if the validation of the XSD fails, we arrive here
logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
logger.warning( _logger.warning(
"The XML file is invalid against the XML Schema Definition") "The XML file is invalid against the XML Schema Definition")
logger.warning(xml_string) _logger.warning(xml_string)
logger.warning(e) _logger.warning(e)
raise Warning( raise orm.except_orm(
_('Error :'),
_("The generated XML file is not valid against the official " _("The generated XML file is not valid against the official "
"XML Schema Definition. The generated XML file and the " "XML Schema Definition. The generated XML file and the "
"full error have been written in the server logs. " "full error have been written in the server logs. "
@@ -111,29 +129,39 @@ class ReportIntrastatCommon(models.AbstractModel):
% str(e)) % str(e))
return True return True
@api.multi def _attach_xml_file(
def _attach_xml_file(self, xml_string, declaration_name): self, cr, uid, ids, object, xml_string, start_date_datetime,
declaration_name, context=None):
'''Attach the XML file to the report_intrastat_product/service ''' '''Attach the XML file to the report_intrastat_product/service '''
'''object''' '''object'''
self.ensure_one()
import base64 import base64
filename = '%s_%s.xml' % (self.year_month, declaration_name) assert len(ids) == 1, "Only one ID accepted"
attach = self.with_context( filename = '%s_%s.xml' % (
default_res_id=self.id, datetime.strftime(start_date_datetime, '%Y-%m'),
default_res_model=self._name).env['ir.attachment'].create({ declaration_name)
'name': filename, if not context:
'datas': base64.encodestring(xml_string), context = {}
'datas_fname': filename}) context.update({
return attach.id 'default_res_id': ids[0],
'default_res_model': object._name
})
attach_id = self.pool['ir.attachment'].create(
cr, uid, {
'name': filename,
'datas': base64.encodestring(xml_string),
'datas_fname': filename},
context=context)
return attach_id
@api.model def _open_attach_view(
def _open_attach_view(self, attach_id, title='XML file'): self, cr, uid, attach_id, title='XML file', context=None):
'''Returns an action which opens the form view of the ''' '''Returns an action which opens the form view of the '''
'''corresponding attachement''' '''corresponding attachement'''
action = { action = {
'name': title, 'name': title,
'view_type': 'form', 'view_type': 'form',
'view_mode': 'form', 'view_mode': 'form,tree',
'view_id': False,
'res_model': 'ir.attachment', 'res_model': 'ir.attachment',
'type': 'ir.actions.act_window', 'type': 'ir.actions.act_window',
'nodestroy': True, 'nodestroy': True,
@@ -142,27 +170,30 @@ class ReportIntrastatCommon(models.AbstractModel):
} }
return action return action
@api.one def partner_on_change(self, cr, uid, ids, partner_id=False, context=None):
def send_reminder_email(self, mail_template_xmlid): result = {}
mail_template = self.env.ref(mail_template_xmlid) result['value'] = {}
if self.company_id.intrastat_remind_user_ids: if partner_id:
company = self.pool['res.partner'].read(
cr, uid, partner_id, ['vat'], context=context)
result['value']['partner_vat'] = company['vat']
return result
def send_reminder_email(
self, cr, uid, company, module_name, template_xmlid,
intrastat_id, context=None):
template_model, template_id =\
self.pool['ir.model.data'].get_object_reference(
cr, uid, module_name, template_xmlid)
assert template_model == 'email.template', 'Wrong model'
if company.intrastat_remind_user_ids:
self.pool['email.template'].send_mail( self.pool['email.template'].send_mail(
self._cr, self._uid, mail_template.id, self.id, cr, uid, template_id, intrastat_id, context=context)
context=self._context)
logger.info( logger.info(
'Intrastat Reminder email has been sent (XMLID: %s).' 'Intrastat Reminder email has been sent (XMLID: %s).'
% mail_template_xmlid) % template_xmlid)
else: else:
logger.warning( logger.warning(
'The list of users receiving the Intrastat Reminder is empty ' 'The list of users receiving the Intrastat Reminder is empty '
'on company %s' % self.company_id.name) 'on company %s' % company.name)
return True return True
@api.multi
def unlink(self):
for intrastat in self:
if intrastat.state == 'done':
raise Warning(
_('Cannot delete the declaration %s '
'because it is in Done state') % self.year_month)
return super(ReportIntrastatCommon, self).unlink()