[IMP] calendar(_sms): add template selection on reminders

The purpose is to allow the user to have the opportunity to manage what is
going to be send as reminders. He can now access to the template or create
a new one when the type of reminder is email or sms. In case of a simple
notification, a new text field is added to add custom content.

Task ID-2191254
COM PR odoo/odoo#68443
UPG PR odoo/upgrade#2313

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Jérémy Hennecart
2021-03-30 12:15:00 +00:00
committed by Thibault Delavallée
parent f87a0eb763
commit 4a616e1ab1
12 changed files with 110 additions and 33 deletions
+1 -1
View File
@@ -26,9 +26,9 @@ If you need to manage your meetings, you should install the CRM module.
'security/ir.model.access.csv',
'security/calendar_security.xml',
'data/calendar_cron.xml',
'data/mail_template_data.xml',
'data/calendar_data.xml',
'data/mail_data_various.xml',
'data/mail_template_data.xml',
'views/mail_activity_views.xml',
'views/calendar_templates.xml',
'views/calendar_views.xml',
+3 -1
View File
@@ -36,12 +36,14 @@
<field name="duration" eval="3" />
<field name="interval">hours</field>
<field name="alarm_type">email</field>
<field name="mail_template_id" ref="calendar.calendar_template_meeting_reminder"/>
</record>
<record id="alarm_mail_2" model="calendar.alarm">
<field name="name">Email - 6 Hours</field>
<field name="duration" eval="6" />
<field name="interval">hours</field>
<field name="alarm_type">email</field>
<field name="mail_template_id" ref="calendar.calendar_template_meeting_reminder"/>
</record>
</data>
</odoo>
</odoo>
+14
View File
@@ -21,6 +21,12 @@ class Alarm(models.Model):
'Duration in minutes', store=True,
search='_search_duration_minutes', compute='_compute_duration_minutes',
help="Duration in minutes")
mail_template_id = fields.Many2one(
'mail.template', string="Email Template",
domain=[('model', 'in', ['calendar.attendee'])],
compute='_compute_mail_template_id', readonly=False, store=True,
help="Template used to render mail reminder content.")
body = fields.Text("Additional Message", help="Additional message that would be sent with the notification for the reminder")
@api.depends('interval', 'duration')
def _compute_duration_minutes(self):
@@ -34,6 +40,14 @@ class Alarm(models.Model):
else:
alarm.duration_minutes = 0
@api.depends('alarm_type', 'mail_template_id')
def _compute_mail_template_id(self):
for alarm in self:
if alarm.alarm_type == 'email' and not alarm.mail_template_id:
alarm.mail_template_id = self.env['ir.model.data'].xmlid_to_res_id('calendar.calendar_template_meeting_reminder')
elif alarm.alarm_type != 'email' or not alarm.mail_template_id:
alarm.mail_template_id = False
def _search_duration_minutes(self, operator, value):
return [
'|', '|',
@@ -5,6 +5,7 @@ import logging
from datetime import timedelta
from odoo import api, fields, models
from odoo.tools import plaintext2html
_logger = logging.getLogger(__name__)
@@ -135,7 +136,7 @@ class AlarmManager(models.AbstractModel):
})
return result
def _get_events_to_notify(self, ttype):
def _get_events_by_alarm_to_notify(self, alarm_type):
"""
Get the events with an alarm of the given type between the cron
last call and now.
@@ -146,7 +147,7 @@ class AlarmManager(models.AbstractModel):
already.
"""
self.env.cr.execute('''
SELECT "event"."id"
SELECT "alarm"."id", "event"."id"
FROM "calendar_event" AS "event"
JOIN "calendar_alarm_calendar_event_rel" AS "event_alarm_rel"
ON "event"."id" = "event_alarm_rel"."calendar_event_id"
@@ -157,20 +158,33 @@ class AlarmManager(models.AbstractModel):
AND "event"."active"
AND "event"."start" - CAST("alarm"."duration" || ' ' || "alarm"."interval" AS Interval) >= %s
AND "event"."start" - CAST("alarm"."duration" || ' ' || "alarm"."interval" AS Interval) < now() at time zone 'utc'
)''', [ttype, self.env.context['lastcall']])
)''', [alarm_type, self.env.context['lastcall']])
ids = [row[0] for row in self.env.cr.fetchall()]
return self.env['calendar.event'].browse(ids)
events_by_alarm = {}
for alarm_id, event_id in self.env.cr.fetchall():
events_by_alarm.setdefault(alarm_id, list()).append(event_id)
return events_by_alarm
@api.model
def _send_reminder(self):
# Executed via cron
events = self._get_events_to_notify('email')
events_by_alarm = self._get_events_by_alarm_to_notify('email')
if not events_by_alarm:
return
event_ids = list(set(event_id for event_ids in events_by_alarm.values() for event_id in event_ids))
events = self.env['calendar.event'].browse(event_ids)
attendees = events.attendee_ids.filtered(lambda a: a.state != 'declined')
attendees.with_context(calendar_template_ignore_recurrence=True)._send_mail_to_attendees(
self.env.ref('calendar.calendar_template_meeting_reminder', raise_if_not_found=False),
force_send=True,
)
alarms = self.env['calendar.alarm'].browse(events_by_alarm.keys())
for alarm in alarms:
alarm_attendees = attendees.filtered(lambda attendee: attendee.event_id.id in events_by_alarm[alarm.id])
alarm_attendees.with_context(
mail_notify_force_send=True,
calendar_template_ignore_recurrence=True
)._send_mail_to_attendees(
alarm.mail_template_id,
force_send=True
)
@api.model
def get_next_notif(self):
@@ -198,6 +212,8 @@ class AlarmManager(models.AbstractModel):
if alarm.alarm_type == 'notification':
message = meeting.display_time
if alarm.body:
message += '<p>%s</p>' % plaintext2html(alarm.body)
delta = alert['notify_at'] - fields.Datetime.now()
delta = delta.seconds + delta.days * 3600 * 24
+25 -15
View File
@@ -23,7 +23,7 @@
<field name="name">calendar.alarm.tree</field>
<field name="model">calendar.alarm</field>
<field name="arch" type="xml">
<tree string="Calendar Alarm" sample="1" editable="bottom">
<tree string="Calendar Alarm" sample="1">
<field name="name" invisible="1"/>
<field name="alarm_type"/>
<field name="duration"/>
@@ -33,23 +33,32 @@
</record>
<record id="calendar_alarm_view_form" model="ir.ui.view">
<field name="name">calendar.alarm.form</field>
<field name="model">calendar.alarm</field>
<field name="arch" type="xml">
<form string="Calendar Alarm">
<group>
<field name="name">calendar.alarm.form</field>
<field name="model">calendar.alarm</field>
<field name="arch" type="xml">
<form string="Calendar Alarm">
<sheet>
<group>
<field name="name" invisible="1"/>
<field name="alarm_type"/>
<group>
<field name="name" invisible="1"/>
<field name="alarm_type"/>
</group>
<group>
<label for="duration"/>
<div class="o_row">
<field name="duration"/>
<field name="interval"/>
</div>
</group>
<group attrs="{'invisible': [('alarm_type','=','notification')]}">
<field name="mail_template_id" attrs="{'invisible': [('alarm_type','!=','email')], 'required': [('alarm_type', '=', 'email')]}"
context="{'default_model': 'calendar.event'}"/>
</group>
</group>
<group>
<label for="duration"/>
<div class="o_row">
<field name="duration"/>
<field name="interval"/>
</div>
<group attrs="{'invisible': [('alarm_type','!=','notification')]}">
<field name="body"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
@@ -57,6 +66,7 @@
<record id="action_calendar_alarm" model="ir.actions.act_window">
<field name="name">Calendar Alarm</field>
<field name="res_model">calendar.alarm</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_calendar_alarm_tree"/>
</record>
+1
View File
@@ -3,6 +3,7 @@
{
'name': "Calendar - SMS",
'version': "1.1",
'summary': 'Send text messages as event reminders',
'description': "Send text messages as event reminders",
'category': 'Hidden',
+14 -1
View File
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
from odoo import api, fields, models
class CalendarAlarm(models.Model):
@@ -10,3 +10,16 @@ class CalendarAlarm(models.Model):
alarm_type = fields.Selection(selection_add=[
('sms', 'SMS Text Message')
], ondelete={'sms': 'set default'})
sms_template_id = fields.Many2one(
'sms.template', string="SMS Template",
domain=[('model', 'in', ['calendar.event'])],
compute='_compute_sms_template_id', readonly=False, store=True,
help="Template used to render SMS reminder content.")
@api.depends('alarm_type', 'mail_template_id')
def _compute_sms_template_id(self):
for alarm in self:
if alarm.alarm_type == 'sms' and not alarm.sms_template_id:
alarm.sms_template_id = self.env['ir.model.data'].xmlid_to_res_id('calendar_sms.sms_template_data_calendar_reminder')
elif alarm.alarm_type != 'sms' or not alarm.sms_template_id:
alarm.sms_template_id = False
@@ -12,4 +12,13 @@ class AlarmManager(models.AbstractModel):
""" Cron method, overridden here to send SMS reminders as well
"""
super()._send_reminder()
self._get_events_to_notify(ttype='sms')._do_sms_reminder()
alarms_by_event = self._get_events_by_alarm_to_notify(ttype='sms')
if not alarms_by_event:
return
events = self.env['calendar.event'].browse(list(alarms_by_event.keys()))
attendees = events.attendee_ids.filtered(lambda a: a.state != 'declined')
for event_id in alarms_by_event.keys():
event_alarms = attendees.event_id.alarm_ids.filtered(lambda alarm: alarm.id in alarms_by_event.get(event_id, []))
for alarm in event_alarms:
events.browse(event_id)._do_sms_reminder(alarm)
+2 -2
View File
@@ -13,11 +13,11 @@ class CalendarEvent(models.Model):
"""
return self.mapped('attendee_ids').filtered(lambda att: att.state != 'declined').mapped('partner_id')
def _do_sms_reminder(self):
def _do_sms_reminder(self, alarm):
""" Send an SMS text reminder to attendees that haven't declined the event """
for event in self:
event._message_sms_with_template(
template_xmlid='calendar_sms.sms_template_data_calendar_reminder',
template=alarm.sms_template_id,
template_fallback=_("Event reminder: %(name)s, %(time)s.", name=event.name, time=event.display_time),
partner_ids=self._sms_get_default_partners().ids,
put_in_queue=False
@@ -1,6 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="calendar_alarm_view_form" model="ir.ui.view">
<field name="name">calendar.alarm.view.form.inherit.calendar.sms</field>
<field name="model">calendar.alarm</field>
<field name="inherit_id" ref="calendar.calendar_alarm_view_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='mail_template_id']" position="after">
<field name="sms_template_id" attrs="{'invisible': [('alarm_type','!=','sms')], 'required': [('alarm_type', '=', 'sms')]}"
context="{'default_model': 'calendar.event'}"/>
</xpath>
</field>
</record>
<!-- Add action entry in the Action Menu for Events -->
<record id="calendar_event_act_window_sms_composer_single" model="ir.actions.act_window">
<field name="name">Send SMS</field>
@@ -313,7 +313,7 @@ class TestCompanyLeave(TransactionCase):
})
company_leave._compute_date_from_to()
with self.assertQueryCount(__system__=737, admin=865):
with self.assertQueryCount(__system__=739, admin=865):
# Original query count: 1987
# Without tracking/activity context keys: 5154
company_leave.action_validate()
@@ -31,7 +31,7 @@ class TestWorkEntryHolidaysPerformance(TestWorkEntryHolidaysBase):
self.richard_emp.generate_work_entries(date(2018, 1, 1), date(2018, 1, 2))
leave = self.create_leave(datetime(2018, 1, 1, 7, 0), datetime(2018, 1, 1, 18, 0))
with self.assertQueryCount(__system__=91, admin=99):
with self.assertQueryCount(__system__=92, admin=99):
leave.action_validate()
leave.action_refuse()