From 78aea4c0d6d0d60cb355851b28b246be48875e76 Mon Sep 17 00:00:00 2001 From: "Andrzej(pian)" Date: Mon, 11 Mar 2024 14:50:01 +0100 Subject: [PATCH] [FIX] event: Include unregistered attendee emails in total sent count Before this commit the Email Sent Count (located in the Communication tab of the event view) wasn't including emails sent to the attendees who weren't confirmed. [This commit changes] Event mail scheduler will include seats_uncofirmed into calculation of the mail_count_done which is the count of emails sent. This is reflecting the actual number of emails sent. [Reproduce] - Install event_mail,event_sms - Create event E starting in time T (Events/Events) - Add an "Unconfirmed" attendee (Modify state via database write) - Add an E-Mail in the Communication tab of the event E - Set Interval time > T, - Template: "Email Reminder" - Trigger "Before the event" - Run scheduled Action sending email (Scheduled Actions / Event: Mail Scheduler) - BUG: email sent, but not included in the sent count in the communication tab of the event E opw-3693626 closes odoo/odoo#157229 Signed-off-by: Andrzej Pietrusiak (pian) --- addons/event/models/event_mail.py | 3 +- addons/event_sms/models/event_mail.py | 2 +- .../test_event_full/tests/test_event_mail.py | 82 +++++++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/addons/event/models/event_mail.py b/addons/event/models/event_mail.py index f9c99b8a0fe..d267ea68dd4 100644 --- a/addons/event/models/event_mail.py +++ b/addons/event/models/event_mail.py @@ -185,9 +185,10 @@ class EventMailScheduler(models.Model): # do not send emails if the mailing was scheduled before the event but the event is over if scheduler.scheduled_date <= now and (scheduler.interval_type != 'before_event' or scheduler.event_id.date_end > now): scheduler.event_id.mail_attendees(scheduler.template_ref.id) + # Mail is sent to all attendees (unconfirmed as well), so count all attendees scheduler.update({ 'mail_done': True, - 'mail_count_done': scheduler.event_id.seats_reserved + scheduler.event_id.seats_used, + 'mail_count_done': len(scheduler.event_id.registration_ids.filtered(lambda r: r.state != 'cancel')) }) return True diff --git a/addons/event_sms/models/event_mail.py b/addons/event_sms/models/event_mail.py index e00a66798c8..fc2cd10aa81 100644 --- a/addons/event_sms/models/event_mail.py +++ b/addons/event_sms/models/event_mail.py @@ -58,7 +58,7 @@ class EventMailScheduler(models.Model): ) scheduler.update({ 'mail_done': True, - 'mail_count_done': scheduler.event_id.seats_reserved + scheduler.event_id.seats_used, + 'mail_count_done': len(scheduler.event_id.registration_ids.filtered(lambda r: r.state != 'cancel')) }) return super(EventMailScheduler, self).execute() diff --git a/addons/test_event_full/tests/test_event_mail.py b/addons/test_event_full/tests/test_event_mail.py index 30c2766e804..9959bf539ff 100644 --- a/addons/test_event_full/tests/test_event_mail.py +++ b/addons/test_event_full/tests/test_event_mail.py @@ -1,6 +1,11 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from datetime import datetime, timedelta +from freezegun import freeze_time + +from odoo.addons.mail.tests.common import MockEmail +from odoo.addons.sms.tests.common import MockSMS from odoo.addons.test_event_full.tests.common import TestWEventCommon from odoo.exceptions import ValidationError from odoo.tests import tagged @@ -43,3 +48,80 @@ class TestTemplateRefModel(TestWEventCommon): self.assertEqual(str(cm.exception), 'The template which is referenced should be coming from mail.template model.') else: self.assertEqual(str(cm.exception), 'The template which is referenced should be coming from sms.template model.') + +class TestEventSmsMailSchedule(TestWEventCommon, MockEmail, MockSMS): + + @freeze_time('2020-07-06 12:00:00') + def test_event_mail_before_trigger_sent_count(self): + """ Emails are sent to both confirmed and unconfirmed attendees. + This test checks that the count of sent emails includes the emails sent to unconfirmed ones + + Time in the test is frozen to simulate the following state: + + NOW Event Start Event End + 12:00 13:00 14:00 + | | | + ──────────────────────────────────────► + | | time + ◄─────────────────► + 3 hours + Trigger before event + """ + self.sms_template_rem = self.env['sms.template'].create({ + 'name': 'Test reminder', + 'model_id': self.env.ref('event.model_event_registration').id, + 'body': '{{ object.event_id.organizer_id.name }} reminder', + 'lang': '{{ object.partner_id.lang }}' + }) + test_event = self.env['event.event'].create({ + 'name': 'TestEventMail', + # 'user_id': self.env.ref('base.user_admin').id, + 'date_begin': datetime.now() + timedelta(hours=1), + 'date_end': datetime.now() + timedelta(hours=2), + 'event_mail_ids': [ + (0, 0, { # email 3 hours before event + 'interval_nbr': 3, + 'interval_unit': 'hours', + 'interval_type': 'before_event', + 'template_ref': 'mail.template,%i' % self.env['ir.model.data']._xmlid_to_res_id('event.event_reminder')}), + (0, 0, { # sms 3 hours before event + 'interval_nbr': 3, + 'interval_unit': 'hours', + 'interval_type': 'before_event', + 'notification_type': 'sms', + 'template_ref': 'sms.template,%i' % self.sms_template_rem.id}), + ] + }) + mail_scheduler = test_event.event_mail_ids + self.assertEqual(len(mail_scheduler), 2, 'There should be two mail schedulers. One for mail one for sms. Cannot perform test') + + # Add registrations + self.env['event.registration'].create([{ + 'event_id': test_event.id, + 'name': 'RegistrationUnconfirmed', + 'email': 'Registration@Unconfirmed.com', + 'state': 'draft', + }, { + 'event_id': test_event.id, + 'name': 'RegistrationCanceled', + 'email': 'Registration@Canceled.com', + 'state': 'cancel', + }, { + 'event_id': test_event.id, + 'name': 'RegistrationConfirmed', + 'email': 'Registration@Confirmed.com', + 'state': 'open', + }]) + + with self.mock_mail_gateway(), self.mockSMSGateway(): + mail_scheduler.execute() + + self.assertEqual(len(self._new_mails), 2, 'Mails were not created') + self.assertEqual(len(self._new_sms), 2, 'SMS were not created') + + self.assertEqual(test_event.seats_taken, 1, 'Wrong number of seats_taken') + + self.assertEqual(mail_scheduler.filtered(lambda r: r.notification_type == 'mail').mail_count_done, 2, + 'Wrong Emails Sent Count! Probably emails sent to unconfirmed attendees were not included into the Sent Count') + self.assertEqual(mail_scheduler.filtered(lambda r: r.notification_type == 'sms').mail_count_done, 2, + 'Wrong SMS Sent Count! Probably SMS sent to unconfirmed attendees were not included into the Sent Count')