[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:
@@ -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'])
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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={
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user