[FIX] mail: schedule activity with user's today

The activity was incorrectly scheduled with a deadline as the now in UTC while
the state was computed using "today" in the user's timezone.
This made the nightly test fail (run at 23:30 UTC with the user in UTC+2).

Use context_today instead of today for all activity_schedule calls
To make it easier, use on the context_today default value instead of setting
context_today everywhere (which is more error prone in the future)

Never use datetime, only date objects
add a warning to detect potential errors when passing a datetime

Closes #26411
This commit is contained in:
Martin Trigaux
2018-08-17 13:46:39 +02:00
parent c51cfbc58b
commit d97e69ff02
8 changed files with 19 additions and 12 deletions
+1 -1
View File
@@ -721,7 +721,7 @@ class HrExpenseSheet(models.Model):
def activity_update(self):
for expense_report in self.filtered(lambda hol: hol.state == 'submit'):
self.activity_schedule(
'hr_expense.mail_act_expense_approval', fields.Date.today(),
'hr_expense.mail_act_expense_approval',
user_id=expense_report._get_responsible_for_approval().id)
self.filtered(lambda hol: hol.state == 'approve').activity_feedback(['hr_expense.mail_act_expense_approval'])
self.filtered(lambda hol: hol.state == 'cancel').activity_unlink(['hr_expense.mail_act_expense_approval'])
+2 -2
View File
@@ -621,12 +621,12 @@ class HolidaysRequest(models.Model):
to_clean |= holiday
elif holiday.state == 'confirm':
holiday.activity_schedule(
'hr_holidays.mail_act_leave_approval', fields.Date.today(),
'hr_holidays.mail_act_leave_approval',
user_id=holiday._get_responsible_for_approval().id)
elif holiday.state == 'validate1':
holiday.activity_feedback(['hr_holidays.mail_act_leave_approval'])
holiday.activity_schedule(
'hr_holidays.mail_act_leave_second_approval', fields.Date.today(),
'hr_holidays.mail_act_leave_second_approval',
user_id=holiday._get_responsible_for_approval().id)
elif holiday.state == 'validate':
to_do |= holiday
@@ -466,12 +466,12 @@ class HolidaysAllocation(models.Model):
to_clean |= allocation
elif allocation.state == 'confirm':
allocation.activity_schedule(
'hr_holidays.mail_act_leave_allocation_approval', fields.Date.today(),
'hr_holidays.mail_act_leave_allocation_approval',
user_id=allocation._get_responsible_for_approval().id)
elif allocation.state == 'validate1':
allocation.activity_feedback(['hr_holidays.mail_act_leave_allocation_approval'])
allocation.activity_schedule(
'hr_holidays.mail_act_leave_allocation_second_approval', fields.Date.today(),
'hr_holidays.mail_act_leave_allocation_second_approval',
user_id=allocation._get_responsible_for_approval().id)
elif allocation.state == 'validate':
to_do |= allocation
+1 -2
View File
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import date
from dateutil.relativedelta import relativedelta
from odoo import _, api, fields, models
@@ -96,7 +95,7 @@ class ServerActions(models.Model):
'activity_type_id': action.activity_type_id.id,
}
if action.activity_date_deadline_range > 0:
vals['date_deadline'] = date.today() + relativedelta(**{action.activity_date_deadline_range_type: action.activity_date_deadline_range})
vals['date_deadline'] = fields.Date.context_today(action) + relativedelta(**{action.activity_date_deadline_range_type: action.activity_date_deadline_range})
for record in records:
if action.activity_user_type == 'specific':
user = action.activity_user_id
+9 -1
View File
@@ -4,12 +4,15 @@
from collections import defaultdict
from datetime import date, datetime
from dateutil.relativedelta import relativedelta
import logging
import pytz
from odoo import api, exceptions, fields, models, _
from odoo.tools import pycompat
_logger = logging.getLogger(__name__)
class MailActivityType(models.Model):
""" Activity Types are used to categorize activities. Each type is a different
@@ -579,12 +582,17 @@ class MailActivityMixin(models.AbstractModel):
xml_id of activity type instead of directly giving an activity_type_id.
It is useful to avoid having various "env.ref" in the code and allow
to let the mixin handle access rights.
:param date_deadline: the day the activity must be scheduled on
the timezone of the user must be considered to set the correct deadline
"""
if self.env.context.get('mail_activity_automation_skip'):
return False
if not date_deadline:
date_deadline = fields.Date.today()
date_deadline = fields.Date.context_today(self)
if isinstance(date_deadline, datetime):
_logger.warning("Scheduled deadline should be a date (got %s)", date_deadline)
if act_type_xmlid:
activity_type = self.sudo().env.ref(act_type_xmlid)
else:
+1 -1
View File
@@ -366,7 +366,7 @@ class SaleOrder(models.Model):
if values['invoice_status'] == 'upselling':
for order in self:
order.activity_schedule(
'sale.mail_act_sale_upsell', fields.Date.today(),
'sale.mail_act_sale_upsell',
user_id=order.user_id.id,
note=_("Upsell <a href='#' data-oe-model='%s' data-oe-id='%d'>%s</a> for customer <a href='#' data-oe-model='%s' data-oe-id='%s'>%s</a>") % (
order._name, order.id, order.name,
@@ -27,7 +27,7 @@ class PurchaseOrder(models.Model):
sale_to_notify_map[sale_order] |= purchase_line
for sale_order, purchase_order_lines in sale_to_notify_map.items():
sale_order.activity_schedule_with_view('mail.mail_activity_data_warning', fields.Datetime.now(),
sale_order.activity_schedule_with_view('mail.mail_activity_data_warning',
user_id=sale_order.user_id.id or self.env.uid,
views_or_xmlid='sale_purchase.exception_sale_on_purchase_cancellation',
render_context={
+2 -2
View File
@@ -58,7 +58,7 @@ class SaleOrder(models.Model):
purchase_to_notify_map[purchase_line.order_id] |= purchase_line.sale_line_id
for purchase_order, sale_order_lines in purchase_to_notify_map.items():
purchase_order.activity_schedule_with_view('mail.mail_activity_data_warning', fields.Datetime.now(),
purchase_order.activity_schedule_with_view('mail.mail_activity_data_warning',
user_id=purchase_order.user_id.id or self.env.uid,
views_or_xmlid='sale_purchase.exception_purchase_on_sale_cancellation',
render_context={
@@ -151,7 +151,7 @@ class SaleOrderLine(models.Model):
'sale_orders': sale_lines.mapped('order_id'),
'origin_values': origin_values,
}
purchase_order.activity_schedule_with_view('mail.mail_activity_data_warning', fields.Datetime.now(),
purchase_order.activity_schedule_with_view('mail.mail_activity_data_warning',
user_id=purchase_order.user_id.id or self.env.uid,
views_or_xmlid='sale_purchase.exception_purchase_on_sale_quantity_decreased',
render_context=render_context)