[IMP] event: prevent communication line duplication on an event

Currently, when we change the event template, all the communication
lines linked with are added to the event. That means, even if some of
the lines are sent, and if the new templates lines that has exact same
configuration than the sent ones, they are still added to the event,
which means the same mails will be sent again to the attendees.

With this commit, we check that the communication line being added
(as a result of template change) has the same configuration against
any of the already sent one, it is skipped. As a result, attendees
will not be spammed with the same emails.

taskID-2811310

closes odoo/odoo#89961

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Umesh Gupta
2022-08-16 16:27:52 +02:00
committed by umgu-odoo
parent 98e00bdb58
commit e8949d9f79
3 changed files with 82 additions and 12 deletions
+7 -4
View File
@@ -460,11 +460,14 @@ class EventEvent(models.Model):
lambda mail: not(mail._origin.mail_done) and not(mail._origin.mail_registration_ids)
)
command = [Command.unlink(mail.id) for mail in mails_to_remove]
# lines to add: those which do not have the exact copy available in lines to keep
if event.event_type_id.event_type_mail_ids:
command += [
Command.create(line._prepare_event_mail_values())
for line in event.event_type_id.event_type_mail_ids
]
mails_to_keep_vals = {mail._prepare_event_mail_values() for mail in event.event_mail_ids - mails_to_remove}
for mail in event.event_type_id.event_type_mail_ids:
mail_values = mail._prepare_event_mail_values()
if mail_values not in mails_to_keep_vals:
command.append(Command.create(mail_values._asdict()))
if command:
event.event_mail_ids = command
+18 -8
View File
@@ -5,6 +5,7 @@ import logging
import random
import threading
from collections import namedtuple
from datetime import datetime
from dateutil.relativedelta import relativedelta
@@ -59,14 +60,13 @@ class EventTypeMail(models.Model):
def _prepare_event_mail_values(self):
self.ensure_one()
return {
'notification_type': self.notification_type,
'interval_nbr': self.interval_nbr,
'interval_unit': self.interval_unit,
'interval_type': self.interval_type,
'template_ref': '%s,%i' % (self.template_ref._name, self.template_ref.id)
}
return namedtuple("MailValues", ['notification_type', 'interval_nbr', 'interval_unit', 'interval_type', 'template_ref'])(
self.notification_type,
self.interval_nbr,
self.interval_unit,
self.interval_type,
'%s,%i' % (self.template_ref._name, self.template_ref.id)
)
class EventMailScheduler(models.Model):
""" Event automated mailing. This model replaces all existing fields and
@@ -182,6 +182,16 @@ class EventMailScheduler(models.Model):
return self.env['event.mail.registration'].create(new)
return self.env['event.mail.registration']
def _prepare_event_mail_values(self):
self.ensure_one()
return namedtuple("MailValues", ['notification_type', 'interval_nbr', 'interval_unit', 'interval_type', 'template_ref'])(
self.notification_type,
self.interval_nbr,
self.interval_unit,
self.interval_type,
'%s,%i' % (self.template_ref._name, self.template_ref.id)
)
@api.model
def _warn_template_error(self, scheduler, exception):
# We warn ~ once by hour ~ instead of every 10 min if the interval unit is more than 'hours'.
@@ -5,6 +5,7 @@ from datetime import datetime
from dateutil.relativedelta import relativedelta
from freezegun import freeze_time
from odoo import Command
from odoo.addons.event.tests.common import EventCase
from odoo.addons.mail.tests.common import MockEmail
from odoo.tools import formataddr, mute_logger
@@ -276,3 +277,59 @@ class TestMailSchedule(EventCase, MockEmail):
fields_values={'subject': '%s: today' % test_event.name,
'email_from': self.user_eventmanager.company_id.email_formatted,
})
@mute_logger('odoo.addons.base.models.ir_model', 'odoo.models')
def test_unique_event_mail_ids(self):
# create event with default event_mail_ids lines
test_event = self.env['event.event'].with_user(self.user_eventmanager).create({
'name': "TestEvent",
'auto_confirm': True,
'date_begin': datetime.now(),
'date_end': datetime.now() + relativedelta(days=1),
'seats_max': 2,
'seats_limited': True,
})
event_mail_ids_initial = test_event.event_mail_ids
self._create_registrations(test_event, 1)
mail_done = test_event.event_mail_ids.filtered(lambda mail: mail.mail_done and mail.mail_registration_ids)
self.assertEqual(len(test_event.event_mail_ids), 3, "Should have 3 communication lines")
self.assertEqual(len(mail_done), 1, "Should have sent first mail immediately")
# change the event type that has event_type_mail_ids having one identical and one non-identical configuration
event_type = self.env['event.type'].create({
'name': "Go Sports",
'event_type_mail_ids': [
Command.create({
'notification_type': 'mail',
'interval_nbr': 0,
'interval_unit': 'now',
'interval_type': 'after_sub',
'template_ref': 'mail.template,%i' % self.env['ir.model.data']._xmlid_to_res_id('event.event_subscription')}),
Command.create({
'notification_type': 'mail',
'interval_nbr': 5,
'interval_unit': 'hours',
'interval_type': 'before_event',
'template_ref': 'mail.template,%i' % self.env['ir.model.data']._xmlid_to_res_id('event.event_reminder')}),
]
})
test_event.event_type_id = event_type
self.assertTrue(mail_done in test_event.event_mail_ids, "Sent communication should not have been removed")
mail_not_done = event_mail_ids_initial - mail_done
self.assertFalse(test_event.event_mail_ids & mail_not_done, "Other default communication lines should have been removed")
self.assertEqual(len(test_event.event_mail_ids), 2, "Should now have only two communication lines")
mails_to_send = test_event.event_mail_ids - mail_done
duplicate_mails = mails_to_send.filtered(lambda mail:
mail.notification_type == 'mail' and\
mail.interval_nbr == 0 and\
mail.interval_unit == 'now' and\
mail.interval_type == 'after_sub' and\
mail.template_ref.id == self.env['ir.model.data']._xmlid_to_res_id('event.event_subscription'))
self.assertEqual(len(duplicate_mails), 0,
"The duplicate configuration (first one from event_type.event_type_mail_ids which has same configuration as the sent one) should not have been added")