From bbd15cdca6e3bf6c92d3e230a2b7697c801a2cfb Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Mon, 7 Sep 2015 11:01:26 +0200 Subject: [PATCH 1/3] [FIX] resource: interval_get_multi To compute the intervals of working time, the function interval_get_multi used 'hour_to' and 'hour_from' from "resource.calendar.attendance" model. 'hour_to' and 'hour_from' are not in UTC timezone. All the dates in odoo are compared in UTC. Then 'hour_to' and 'hour_from' must be converted. To take into account the minutes in this computation, the minutes from the start date are added in the variable todo (number of working hours). opw:648349 --- addons/resource/resource.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/addons/resource/resource.py b/addons/resource/resource.py index 3021ea9fdb5..155d6ab4c68 100644 --- a/addons/resource/resource.py +++ b/addons/resource/resource.py @@ -25,7 +25,7 @@ from dateutil import rrule import math from faces import * from openerp.osv import fields, osv -from openerp.tools.float_utils import float_compare +from openerp.tools.float_utils import float_compare, float_round as f_round from openerp.tools.translate import _ from itertools import groupby @@ -152,18 +152,21 @@ class resource_calendar(osv.osv): for d, hours, id in date_and_hours_by_cal: dt_from = datetime.strptime(d, '%Y-%m-%d %H:%M:%S') + tzinfo = fields.datetime.context_timestamp(cr, uid, dt_from, context={}).tzinfo if not id: td = int(hours)*3 results[(d, hours, id)] = [(dt_from, dt_from + timedelta(hours=td))] continue dt_leave = self._get_leaves(cr, uid, id, resource) - todo = hours + todo = hours + f_round(float(dt_from.minute)/60, 2) result = [] maxrecur = 100 current_hour = dt_from.hour while float_compare(todo, 0, 4) and maxrecur: for (hour_from,hour_to) in [(item['hour_from'], item['hour_to']) for item in hours_by_cal[id] if item['dayofweek'] == str(dt_from.weekday())]: + hour_from = dt_from.replace(hour=int(hour_from)).replace(tzinfo=tzinfo).astimezone(pytz.UTC).hour + hour_to = dt_from.replace(hour=int(hour_to)).replace(tzinfo=tzinfo).astimezone(pytz.UTC).hour leave_flag = False if (hour_to>current_hour) and float_compare(todo, 0, 4): m = max(hour_from, current_hour) From 909e6e300a6f2e1b1a6617f5d5e8233b0d42513e Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Tue, 8 Sep 2015 12:02:10 +0200 Subject: [PATCH 2/3] [FIX] email_template: use valid email_from content Correctly use the email_from tag from template. This partially reverts commit 0f82346167698fb7349ff16618d1cecf8984cca9. "[FIX] email_template: keep email_from and outgoing server" Remove the email_from part that was incorrect, keeping the one on mail_server_id Instead of assigning an non-evaulated email_from in the context, specify the email_from in the onchange method. This way the created email has an evaulated from value. This was an issue for templates using email_from like "${(object.user_id.email or '')|safe}" In the _notify method method, the email_from is partially respected as it will be used a fallback only. However changing that would introduce a modification of behaviour not suitable for 7.0 branch. Fixes #8409 --- addons/email_template/wizard/mail_compose_message.py | 8 +++----- addons/mail/mail_followers.py | 5 +---- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/addons/email_template/wizard/mail_compose_message.py b/addons/email_template/wizard/mail_compose_message.py index d9b5f5fe6ba..29aa83ab01b 100644 --- a/addons/email_template/wizard/mail_compose_message.py +++ b/addons/email_template/wizard/mail_compose_message.py @@ -76,8 +76,6 @@ class mail_compose_message(osv.TransientModel): # store them in the context to avoid falling back to default values if template.mail_server_id: email_context['mail_server_id'] = template.mail_server_id.id - if template.email_from: - email_context['email_from'] = template.email_from new_attachment_ids = [] for attachment in wizard.attachment_ids: if attachment in template.attachment_ids: @@ -91,7 +89,7 @@ class mail_compose_message(osv.TransientModel): """ - mass_mailing: we cannot render, so return the template values - normal mode: return rendered values """ if template_id and composition_mode == 'mass_mail': - values = self.pool.get('email.template').read(cr, uid, template_id, ['subject', 'body_html', 'attachment_ids'], context) + values = self.pool.get('email.template').read(cr, uid, template_id, ['subject', 'body_html', 'attachment_ids', 'email_from'], context) values.pop('id') elif template_id: values = self.generate_email_for_composer(cr, uid, template_id, res_id, context=context) @@ -110,7 +108,7 @@ class mail_compose_message(osv.TransientModel): } values['attachment_ids'].append(ir_attach_obj.create(cr, uid, data_attach, context=context)) else: - values = self.default_get(cr, uid, ['body', 'subject', 'partner_ids', 'attachment_ids'], context=context) + values = self.default_get(cr, uid, ['body', 'subject', 'partner_ids', 'attachment_ids', 'email_from'], context=context) if values.get('body_html'): values['body'] = values.pop('body_html') @@ -148,7 +146,7 @@ class mail_compose_message(osv.TransientModel): mail.compose.message, transform email_cc and email_to into partner_ids """ template_values = self.pool.get('email.template').generate_email(cr, uid, template_id, res_id, context=context) # filter template values - fields = ['body_html', 'subject', 'email_to', 'email_recipients', 'email_cc', 'attachment_ids', 'attachments'] + fields = ['body_html', 'subject', 'email_to', 'email_recipients', 'email_cc', 'attachment_ids', 'attachments', 'email_from'] values = dict((field, template_values[field]) for field in fields if template_values.get(field)) values['body'] = values.pop('body_html', '') diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py index 29bd64ef5fa..259bb86ca0c 100644 --- a/addons/mail/mail_followers.py +++ b/addons/mail/mail_followers.py @@ -156,10 +156,7 @@ class mail_notification(osv.Model): body_html = tools.append_content_to_html(body_html, signature, plaintext=True, container_tag='div') # email_from: partner-user alias or partner email or mail.message email_from - if 'email_from' in context: - # temporary workaround for mail from send mail wizard - email_from = context['email_from'] - elif msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0].alias_domain and msg.author_id.user_ids[0].alias_name: + if msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0].alias_domain and msg.author_id.user_ids[0].alias_name: email_from = formataddr((msg.author_id.name, '%s@%s' % (msg.author_id.user_ids[0].alias_name, msg.author_id.user_ids[0].alias_domain))) elif msg.author_id: email_from = formataddr((msg.author_id.name, msg.author_id.email)) From a7ff1104bc7d3b87ac9249b60d0a3658f7ad5438 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Fri, 11 Sep 2015 14:58:44 +0200 Subject: [PATCH 3/3] [FIX] base: sanitize module description --- openerp/addons/base/module/module.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openerp/addons/base/module/module.py b/openerp/addons/base/module/module.py index 8ffb60055f9..3a2980a898e 100644 --- a/openerp/addons/base/module/module.py +++ b/openerp/addons/base/module/module.py @@ -45,6 +45,7 @@ from openerp import modules, pooler, tools, addons from openerp.modules.db import create_categories from openerp.tools.parse_version import parse_version from openerp.tools.translate import _ +from openerp.tools import html_sanitize from openerp.osv import fields, osv, orm _logger = logging.getLogger(__name__) @@ -154,9 +155,10 @@ class module(osv.osv): def _get_desc(self, cr, uid, ids, field_name=None, arg=None, context=None): res = dict.fromkeys(ids, '') for module in self.browse(cr, uid, ids, context=context): - overrides = dict(embed_stylesheet=False, doctitle_xform=False, output_encoding='unicode') + overrides = dict(embed_stylesheet=False, doctitle_xform=False, + output_encoding='unicode', xml_declaration=False) output = publish_string(source=module.description, settings_overrides=overrides, writer=MyWriter()) - res[module.id] = output + res[module.id] = html_sanitize(output) return res def _get_latest_version(self, cr, uid, ids, field_name=None, arg=None, context=None):