mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-21 11:12:05 +02:00
Initial commit: Core packages
This commit is contained in:
commit
12c29a983b
9512 changed files with 8379910 additions and 0 deletions
6
odoo-bringout-oca-ocb-event/event/tests/__init__.py
Normal file
6
odoo-bringout-oca-ocb-event/event/tests/__init__.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import test_event_flow
|
||||
from . import test_event_internals
|
||||
from . import test_event_mail_schedule
|
||||
106
odoo-bringout-oca-ocb-event/event/tests/common.py
Normal file
106
odoo-bringout-oca-ocb-event/event/tests/common.py
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields
|
||||
from odoo.addons.mail.tests.common import mail_new_test_user
|
||||
from odoo.tests import common
|
||||
|
||||
|
||||
class EventCase(common.TransactionCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(EventCase, cls).setUpClass()
|
||||
|
||||
cls.admin_user = cls.env.ref('base.user_admin')
|
||||
cls.admin_user.write({
|
||||
'country_id': cls.env.ref('base.be').id,
|
||||
'login': 'admin',
|
||||
'notification_type': 'inbox',
|
||||
})
|
||||
cls.company_admin = cls.admin_user.company_id
|
||||
# set country in order to format Belgian numbers
|
||||
cls.company_admin.write({
|
||||
'country_id': cls.env.ref('base.be').id,
|
||||
})
|
||||
|
||||
# Test users to use through the various tests
|
||||
cls.user_portal = mail_new_test_user(
|
||||
cls.env,
|
||||
company_id=cls.company_admin.id,
|
||||
email='patrick.portal@test.example.com',
|
||||
groups='base.group_portal',
|
||||
login='portal_test',
|
||||
name='Patrick Portal',
|
||||
notification_type='email',
|
||||
tz='Europe/Brussels',
|
||||
)
|
||||
cls.user_employee = mail_new_test_user(
|
||||
cls.env,
|
||||
company_id=cls.company_admin.id,
|
||||
email='eglantine.employee@test.example.com',
|
||||
groups='base.group_user',
|
||||
login='user_employee',
|
||||
name='Eglantine Employee',
|
||||
notification_type='inbox',
|
||||
tz='Europe/Brussels',
|
||||
)
|
||||
cls.user_eventregistrationdesk = mail_new_test_user(
|
||||
cls.env,
|
||||
company_id=cls.company_admin.id,
|
||||
email='ursule.eventregistration@test.example.com',
|
||||
login='user_eventregistrationdesk',
|
||||
groups='base.group_user,event.group_event_registration_desk',
|
||||
name='Ursule EventRegistration',
|
||||
notification_type='inbox',
|
||||
tz='Europe/Brussels',
|
||||
)
|
||||
cls.user_eventuser = mail_new_test_user(
|
||||
cls.env,
|
||||
company_id=cls.company_admin.id,
|
||||
email='ursule.eventuser@test.example.com',
|
||||
groups='base.group_user,event.group_event_user',
|
||||
login='user_eventuser',
|
||||
name='Ursule EventUser',
|
||||
notification_type='inbox',
|
||||
tz='Europe/Brussels',
|
||||
)
|
||||
cls.user_eventmanager = mail_new_test_user(
|
||||
cls.env,
|
||||
company_id=cls.company_admin.id,
|
||||
email='martine.eventmanager@test.example.com',
|
||||
groups='base.group_user,event.group_event_manager',
|
||||
login='user_eventmanager',
|
||||
name='Martine EventManager',
|
||||
notification_type='inbox',
|
||||
tz='Europe/Brussels',
|
||||
)
|
||||
|
||||
cls.event_customer = cls.env['res.partner'].create({
|
||||
'name': 'Constantin Customer',
|
||||
'email': 'constantin@test.example.com',
|
||||
'country_id': cls.env.ref('base.be').id,
|
||||
'phone': '0485112233',
|
||||
'mobile': False,
|
||||
})
|
||||
cls.event_customer2 = cls.env['res.partner'].create({
|
||||
'name': 'Constantin Customer 2',
|
||||
'email': 'constantin2@test.example.com',
|
||||
'country_id': cls.env.ref('base.be').id,
|
||||
'phone': '0456987654',
|
||||
'mobile': '0456654321',
|
||||
})
|
||||
cls.reference_now = fields.Datetime.from_string('2022-09-05 15:11:34')
|
||||
|
||||
@classmethod
|
||||
def _create_registrations(cls, event, reg_count):
|
||||
# create some registrations
|
||||
create_date = fields.Datetime.now()
|
||||
registrations = cls.env['event.registration'].create([{
|
||||
'create_date': create_date,
|
||||
'event_id': event.id,
|
||||
'name': 'Test Registration %s' % x,
|
||||
'email': '_test_reg_%s@example.com' % x,
|
||||
'phone': '04560000%s%s' % (x, x),
|
||||
} for x in range(0, reg_count)])
|
||||
return registrations
|
||||
143
odoo-bringout-oca-ocb-event/event/tests/test_event_flow.py
Normal file
143
odoo-bringout-oca-ocb-event/event/tests/test_event_flow.py
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import datetime
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from freezegun import freeze_time
|
||||
|
||||
from odoo.addons.event.tests.common import EventCase
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.tests.common import users
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
class TestEventFlow(EventCase):
|
||||
|
||||
@mute_logger('odoo.addons.base.models.ir_model', 'odoo.models')
|
||||
def test_event_auto_confirm(self):
|
||||
""" Basic event management with auto confirmation """
|
||||
# EventUser creates a new event: ok
|
||||
test_event = self.env['event.event'].with_user(self.user_eventmanager).create({
|
||||
'name': 'TestEvent',
|
||||
'auto_confirm': True,
|
||||
'date_begin': datetime.datetime.now() + relativedelta(days=-1),
|
||||
'date_end': datetime.datetime.now() + relativedelta(days=1),
|
||||
'seats_max': 2,
|
||||
'seats_limited': True,
|
||||
})
|
||||
self.assertTrue(test_event.auto_confirm)
|
||||
|
||||
# EventUser create registrations for this event
|
||||
test_reg1 = self.env['event.registration'].with_user(self.user_eventuser).create({
|
||||
'name': 'TestReg1',
|
||||
'event_id': test_event.id,
|
||||
})
|
||||
scheduler = self.env['event.mail'].sudo().search([
|
||||
('event_id', '=', test_event.id),
|
||||
('interval_type', '=', 'after_sub')
|
||||
])
|
||||
self.assertTrue(scheduler.mail_registration_ids.mail_sent)
|
||||
|
||||
self.assertEqual(test_reg1.state, 'open', 'Event: auto_confirmation of registration failed')
|
||||
self.assertEqual(test_event.seats_reserved, 1, 'Event: wrong number of reserved seats after confirmed registration')
|
||||
test_reg2 = self.env['event.registration'].with_user(self.user_eventuser).create({
|
||||
'name': 'TestReg2',
|
||||
'event_id': test_event.id,
|
||||
})
|
||||
self.assertEqual(test_reg2.state, 'open', 'Event: auto_confirmation of registration failed')
|
||||
self.assertEqual(test_event.seats_reserved, 2, 'Event: wrong number of reserved seats after confirmed registration')
|
||||
|
||||
# EventUser create registrations for this event: too much registrations
|
||||
with self.assertRaises(ValidationError):
|
||||
self.env['event.registration'].with_user(self.user_eventuser).create({
|
||||
'name': 'TestReg3',
|
||||
'event_id': test_event.id,
|
||||
})
|
||||
|
||||
# EventUser validates registrations
|
||||
test_reg1.action_set_done()
|
||||
self.assertEqual(test_reg1.state, 'done', 'Event: wrong state of attended registration')
|
||||
self.assertEqual(test_event.seats_used, 1, 'Event: incorrect number of attendees after closing registration')
|
||||
test_reg2.action_set_done()
|
||||
self.assertEqual(test_reg1.state, 'done', 'Event: wrong state of attended registration')
|
||||
self.assertEqual(test_event.seats_used, 2, 'Event: incorrect number of attendees after closing registration')
|
||||
|
||||
@users('user_eventmanager')
|
||||
def test_event_default_datetime(self):
|
||||
""" Check that the default date_begin and date_end are correctly set """
|
||||
|
||||
# Should apply default datetimes
|
||||
with freeze_time(self.reference_now):
|
||||
default_event = self.env['event.event'].create({
|
||||
'name': 'Test Default Event',
|
||||
})
|
||||
self.assertEqual(default_event.date_begin, datetime.datetime.strptime('2022-09-05 15:30:00', '%Y-%m-%d %H:%M:%S'))
|
||||
self.assertEqual(default_event.date_end, datetime.datetime.strptime('2022-09-06 15:30:00', '%Y-%m-%d %H:%M:%S'))
|
||||
|
||||
specific_datetimes = {
|
||||
'date_begin': self.reference_now + relativedelta(days=1),
|
||||
'date_end': self.reference_now + relativedelta(days=3),
|
||||
}
|
||||
|
||||
# Should not apply default datetimes if values are set manually
|
||||
with freeze_time(self.reference_now):
|
||||
event = self.env['event.event'].create({
|
||||
'name': 'Test Event',
|
||||
**specific_datetimes,
|
||||
})
|
||||
self.assertEqual(event.date_begin, specific_datetimes['date_begin'])
|
||||
self.assertEqual(event.date_end, specific_datetimes['date_end'])
|
||||
|
||||
@mute_logger('odoo.addons.base.models.ir_model', 'odoo.models')
|
||||
def test_event_flow(self):
|
||||
""" Advanced event flow: no auto confirmation, manage minimum / maximum
|
||||
seats, ... """
|
||||
# EventUser creates a new event: ok
|
||||
test_event = self.env['event.event'].with_user(self.user_eventmanager).create({
|
||||
'name': 'TestEvent',
|
||||
'date_begin': datetime.datetime.now() + relativedelta(days=-1),
|
||||
'date_end': datetime.datetime.now() + relativedelta(days=1),
|
||||
'seats_limited': True,
|
||||
'seats_max': 10,
|
||||
})
|
||||
self.assertFalse(test_event.auto_confirm)
|
||||
|
||||
# EventUser create registrations for this event -> no auto confirmation
|
||||
test_reg1 = self.env['event.registration'].with_user(self.user_eventuser).create({
|
||||
'name': 'TestReg1',
|
||||
'event_id': test_event.id,
|
||||
})
|
||||
self.assertEqual(
|
||||
test_reg1.state, 'draft',
|
||||
'Event: new registration should not be confirmed with auto_confirmation parameter being False')
|
||||
|
||||
@mute_logger('odoo.addons.event.models.event_mail')
|
||||
def test_event_missed_mail_template(self):
|
||||
""" Check that error on mail sending is ignored if corresponding mail template was deleted """
|
||||
test_event = self.env['event.event'].with_user(self.user_eventmanager).create({
|
||||
'name': 'TestEvent',
|
||||
'date_begin': datetime.datetime.now() + relativedelta(days=-1),
|
||||
'date_end': datetime.datetime.now() + relativedelta(days=1),
|
||||
'seats_max': 2,
|
||||
'seats_limited': True,
|
||||
})
|
||||
self.assertFalse(test_event.auto_confirm)
|
||||
|
||||
# EventUser create registrations for this event
|
||||
test_reg = self.env['event.registration'].with_user(self.user_eventuser).create({
|
||||
'name': 'TestReg1',
|
||||
'event_id': test_event.id,
|
||||
})
|
||||
|
||||
scheduler = self.env['event.mail'].sudo().search([
|
||||
('event_id', '=', test_event.id),
|
||||
('interval_type', '=', 'after_sub')
|
||||
])
|
||||
|
||||
# Imagine user deletes mail template for whatever reason
|
||||
scheduler.template_ref.unlink()
|
||||
|
||||
# Mails should not be sent
|
||||
test_reg.action_confirm()
|
||||
self.assertFalse(scheduler.mail_registration_ids.mail_sent)
|
||||
994
odoo-bringout-oca-ocb-event/event/tests/test_event_internals.py
Normal file
994
odoo-bringout-oca-ocb-event/event/tests/test_event_internals.py
Normal file
|
|
@ -0,0 +1,994 @@
|
|||
# -*- 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 import Command
|
||||
from odoo.addons.event.tests.common import EventCase
|
||||
from odoo import exceptions
|
||||
from odoo.fields import Datetime as FieldsDatetime
|
||||
from odoo.tests.common import users, Form, tagged
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
class TestEventInternalsCommon(EventCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestEventInternalsCommon, cls).setUpClass()
|
||||
|
||||
cls.event_type_complex = cls.env['event.type'].create({
|
||||
'name': 'Update Type',
|
||||
'auto_confirm': True,
|
||||
'has_seats_limitation': True,
|
||||
'seats_max': 30,
|
||||
'default_timezone': 'Europe/Paris',
|
||||
'event_type_ticket_ids': [
|
||||
(0, 0, {'name': 'First Ticket',}),
|
||||
(0, 0, {'name': 'Second Ticket',}),
|
||||
],
|
||||
'event_type_mail_ids': [
|
||||
(0, 0, { # right at subscription
|
||||
'interval_unit': 'now',
|
||||
'interval_type': 'after_sub',
|
||||
'template_ref': 'mail.template,%i' % cls.env['ir.model.data']._xmlid_to_res_id('event.event_subscription')}),
|
||||
(0, 0, { # 1 days before event
|
||||
'interval_nbr': 1,
|
||||
'interval_unit': 'days',
|
||||
'interval_type': 'before_event',
|
||||
'template_ref': 'mail.template,%i' % cls.env['ir.model.data']._xmlid_to_res_id('event.event_reminder')}),
|
||||
],
|
||||
})
|
||||
|
||||
# Mock dates to have reproducible computed fields based on time
|
||||
cls.reference_now = datetime(2020, 1, 31, 10, 0, 0)
|
||||
cls.reference_beg = datetime(2020, 2, 1, 8, 30, 0)
|
||||
cls.reference_end = datetime(2020, 2, 4, 18, 45, 0)
|
||||
|
||||
cls.event_0 = cls.env['event.event'].create({
|
||||
'auto_confirm': True,
|
||||
'date_begin': cls.reference_beg,
|
||||
'date_end': cls.reference_end,
|
||||
'date_tz': 'Europe/Brussels',
|
||||
'name': 'TestEvent',
|
||||
})
|
||||
|
||||
|
||||
@tagged('event_event')
|
||||
class TestEventData(TestEventInternalsCommon):
|
||||
|
||||
@users('user_eventmanager')
|
||||
def test_event_date_computation(self):
|
||||
event = self.event_0.with_user(self.env.user)
|
||||
with freeze_time(self.reference_now):
|
||||
event.write({
|
||||
'registration_ids': [(0, 0, {'partner_id': self.event_customer.id, 'name': 'test_reg'})],
|
||||
'date_begin': datetime(2020, 1, 31, 15, 0, 0),
|
||||
'date_end': datetime(2020, 4, 5, 18, 0, 0),
|
||||
})
|
||||
registration = event.registration_ids[0]
|
||||
self.assertEqual(registration.get_date_range_str(), u'today')
|
||||
|
||||
event.date_begin = datetime(2020, 2, 1, 15, 0, 0)
|
||||
self.assertEqual(registration.get_date_range_str(), u'tomorrow')
|
||||
|
||||
event.date_begin = datetime(2020, 2, 2, 6, 0, 0)
|
||||
self.assertEqual(registration.get_date_range_str(), u'in 2 days')
|
||||
|
||||
event.date_begin = datetime(2020, 2, 20, 17, 0, 0)
|
||||
self.assertEqual(registration.get_date_range_str(), u'next month')
|
||||
|
||||
event.date_begin = datetime(2020, 3, 1, 10, 0, 0)
|
||||
self.assertEqual(registration.get_date_range_str(), u'on Mar 1, 2020')
|
||||
|
||||
# Is actually 8:30 to 20:00 in Mexico
|
||||
event.write({
|
||||
'date_begin': datetime(2020, 1, 31, 14, 30, 0),
|
||||
'date_end': datetime(2020, 2, 1, 2, 0, 0),
|
||||
'date_tz': 'America/Mexico_City'
|
||||
})
|
||||
self.assertTrue(event.is_one_day)
|
||||
|
||||
# Checks case when mocked today changes date before event, when event.date_tz considered
|
||||
with freeze_time(datetime(2020, 6, 20, 20, 0, 0)):
|
||||
event.write({
|
||||
'date_begin': datetime(2020, 6, 27, 1, 0, 0),
|
||||
'date_end': datetime(2020, 7, 8, 2, 0, 0),
|
||||
'date_tz': 'America/Los_Angeles'
|
||||
})
|
||||
# event_date_tz = 2020-06-26 18:00
|
||||
# today_tz = 2020-06-20 13:00
|
||||
# event_date_tz.date() - today_tz.date() = 6 days
|
||||
self.assertEqual(registration.get_date_range_str(), 'in 6 days')
|
||||
|
||||
# Checks case when event changes date before mocked today, when event.date_tz considered
|
||||
with freeze_time(datetime(2020, 6, 20, 13, 0, 0)):
|
||||
event.write({
|
||||
'date_begin': datetime(2020, 6, 25, 20, 0, 0),
|
||||
'date_end': datetime(2020, 7, 8, 2, 0, 0),
|
||||
'date_tz': 'Australia/Sydney'
|
||||
})
|
||||
# event_date_tz = 2020-06-26 06:00
|
||||
# today_tz = 2020-06-20 23:00
|
||||
# event_date_tz.date() - today_tz.date() = 6 days
|
||||
self.assertEqual(registration.get_date_range_str(), 'in 6 days')
|
||||
|
||||
@freeze_time('2020-1-31 10:00:00')
|
||||
@users('user_eventmanager')
|
||||
def test_event_date_timezone(self):
|
||||
event = self.event_0.with_user(self.env.user)
|
||||
# Is actually 8:30 to 20:00 in Mexico
|
||||
event.write({
|
||||
'date_begin': datetime(2020, 1, 31, 14, 30, 0),
|
||||
'date_end': datetime(2020, 2, 1, 2, 0, 0),
|
||||
'date_tz': 'America/Mexico_City'
|
||||
})
|
||||
self.assertTrue(event.is_one_day)
|
||||
self.assertFalse(event.is_ongoing)
|
||||
|
||||
@users('user_eventmanager')
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_event_configuration_from_type(self):
|
||||
""" Test data computation of event coming from its event.type template. """
|
||||
self.assertEqual(self.env.user.tz, 'Europe/Brussels')
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# STARTING DATA
|
||||
# ------------------------------------------------------------
|
||||
|
||||
event_type = self.env['event.type'].browse(self.event_type_complex.id)
|
||||
|
||||
event = self.env['event.event'].create({
|
||||
'name': 'Event Update Type',
|
||||
'date_begin': FieldsDatetime.to_string(datetime.today() + timedelta(days=1)),
|
||||
'date_end': FieldsDatetime.to_string(datetime.today() + timedelta(days=15)),
|
||||
'event_mail_ids': False,
|
||||
})
|
||||
self.assertEqual(event.date_tz, self.env.user.tz)
|
||||
self.assertFalse(event.seats_limited)
|
||||
self.assertFalse(event.auto_confirm)
|
||||
self.assertEqual(event.event_mail_ids, self.env['event.mail'])
|
||||
self.assertEqual(event.event_ticket_ids, self.env['event.event.ticket'])
|
||||
|
||||
registration = self._create_registrations(event, 1)
|
||||
self.assertEqual(registration.state, 'draft') # event is not auto confirm
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# FILL SYNC TEST
|
||||
# ------------------------------------------------------------
|
||||
|
||||
# change template to a one with mails -> fill event as it is void
|
||||
event_type.write({
|
||||
'event_type_mail_ids': [(5, 0), (0, 0, {
|
||||
'interval_nbr': 1, 'interval_unit': 'days', 'interval_type': 'before_event',
|
||||
'template_ref': 'mail.template,%i' % self.env['ir.model.data']._xmlid_to_res_id('event.event_reminder')})
|
||||
],
|
||||
'event_type_ticket_ids': [(5, 0), (0, 0, {'name': 'TestRegistration'})],
|
||||
})
|
||||
event.write({'event_type_id': event_type.id})
|
||||
self.assertEqual(event.date_tz, 'Europe/Paris')
|
||||
self.assertTrue(event.seats_limited)
|
||||
self.assertEqual(event.seats_max, event_type.seats_max)
|
||||
self.assertTrue(event.auto_confirm)
|
||||
# check 2many fields being populated
|
||||
self.assertEqual(len(event.event_mail_ids), 1)
|
||||
self.assertEqual(event.event_mail_ids.interval_nbr, 1)
|
||||
self.assertEqual(event.event_mail_ids.interval_unit, 'days')
|
||||
self.assertEqual(event.event_mail_ids.interval_type, 'before_event')
|
||||
self.assertEqual(event.event_mail_ids.template_ref, self.env.ref('event.event_reminder'))
|
||||
self.assertEqual(len(event.event_ticket_ids), 1)
|
||||
|
||||
# update template, unlink from event -> should not impact event
|
||||
event_type.write({'has_seats_limitation': False})
|
||||
self.assertEqual(event_type.seats_max, 0)
|
||||
self.assertTrue(event.seats_limited)
|
||||
self.assertEqual(event.seats_max, 30) # original template value
|
||||
event.write({'event_type_id': False})
|
||||
self.assertEqual(event.event_type_id, self.env["event.type"])
|
||||
|
||||
# set template back -> update event
|
||||
event.write({'event_type_id': event_type.id})
|
||||
self.assertFalse(event.seats_limited)
|
||||
self.assertEqual(event.seats_max, 0)
|
||||
self.assertEqual(len(event.event_ticket_ids), 1)
|
||||
event_ticket1 = event.event_ticket_ids[0]
|
||||
self.assertEqual(event_ticket1.name, 'TestRegistration')
|
||||
|
||||
@users('user_eventmanager')
|
||||
def test_event_configuration_mails_from_type(self):
|
||||
""" Test data computation (related to mails) of event coming from its event.type template.
|
||||
This test uses pretty low level Form data checks, as manipulations in a non-saved Form are
|
||||
required to highlight an undesired behavior when switching event_type templates :
|
||||
event_mail_ids not linked to a registration were generated and kept when switching between
|
||||
different templates in the Form, which could rapidly lead to a substantial amount of
|
||||
undesired lines. """
|
||||
# setup test records
|
||||
event_type_default = self.env['event.type'].create({
|
||||
'name': 'Type Default',
|
||||
'auto_confirm': True,
|
||||
'event_type_mail_ids': False,
|
||||
})
|
||||
event_type_mails = self.env['event.type'].create({
|
||||
'name': 'Type Mails',
|
||||
'auto_confirm': False,
|
||||
'event_type_mail_ids': [
|
||||
Command.clear(),
|
||||
Command.create({
|
||||
'notification_type': 'mail',
|
||||
'interval_nbr': 77,
|
||||
'interval_unit': 'days',
|
||||
'interval_type': 'after_event',
|
||||
'template_ref': 'mail.template,%i' % self.env['ir.model.data']._xmlid_to_res_id('event.event_reminder'),
|
||||
})
|
||||
],
|
||||
})
|
||||
event = self.env['event.event'].create({
|
||||
'name': 'Event',
|
||||
'date_begin': FieldsDatetime.to_string(datetime.today() + timedelta(days=1)),
|
||||
'date_end': FieldsDatetime.to_string(datetime.today() + timedelta(days=15)),
|
||||
'event_type_id': event_type_default.id
|
||||
})
|
||||
event.write({
|
||||
'event_mail_ids': [
|
||||
Command.clear(),
|
||||
Command.create({
|
||||
'notification_type': 'mail',
|
||||
'interval_unit': 'now',
|
||||
'interval_type': 'after_sub',
|
||||
'template_ref': 'mail.template,%i' % self.env['ir.model.data']._xmlid_to_res_id('event.event_subscription'),
|
||||
})
|
||||
]
|
||||
})
|
||||
mail = event.event_mail_ids[0]
|
||||
registration = self._create_registrations(event, 1)
|
||||
self.assertEqual(registration.state, 'open') # event auto confirms
|
||||
# verify that mail is linked to the registration
|
||||
self.assertEqual(
|
||||
set(mail.mapped('mail_registration_ids.registration_id.id')),
|
||||
set([registration.id])
|
||||
)
|
||||
# start test scenario
|
||||
event_form = Form(event)
|
||||
# verify that mail is linked to the event in the form
|
||||
self.assertEqual(
|
||||
set(map(lambda m: m.get('id', None), event_form.event_mail_ids._records)),
|
||||
set([mail.id])
|
||||
)
|
||||
# switch to an event_type with a mail template which should be computed
|
||||
event_form.event_type_id = event_type_mails
|
||||
# verify that 2 mails were computed
|
||||
self.assertEqual(len(event_form.event_mail_ids._records), 2)
|
||||
# verify that the mail linked to the registration was kept
|
||||
self.assertTrue(filter(lambda m: m.get('id', None) == mail.id, event_form.event_mail_ids._records))
|
||||
# since the other computed event.mail is to be created from an event.type.mail template,
|
||||
# verify that its attributes are the correct ones
|
||||
computed_mail = next(filter(lambda m: m.get('id', None) != mail.id, event_form.event_mail_ids._records), {})
|
||||
self.assertEqual(computed_mail.get('interval_nbr', None), 77)
|
||||
self.assertEqual(computed_mail.get('interval_unit', None), 'days')
|
||||
self.assertEqual(computed_mail.get('interval_type', None), 'after_event')
|
||||
# switch back to an event type without a mail template
|
||||
event_form.event_type_id = event_type_default
|
||||
# verify that the mail linked to the registration was kept, and the other removed
|
||||
self.assertEqual(
|
||||
set(map(lambda m: m.get('id', None), event_form.event_mail_ids._records)),
|
||||
set([mail.id])
|
||||
)
|
||||
|
||||
@users('user_eventmanager')
|
||||
def test_event_configuration_note_from_type(self):
|
||||
event_type = self.env['event.type'].browse(self.event_type_complex.id)
|
||||
|
||||
event = self.env['event.event'].create({
|
||||
'name': 'Event Update Type Note',
|
||||
'date_begin': FieldsDatetime.to_string(datetime.today() + timedelta(days=1)),
|
||||
'date_end': FieldsDatetime.to_string(datetime.today() + timedelta(days=15)),
|
||||
})
|
||||
|
||||
# verify that note is not propagated if the event type contains blank html
|
||||
event.write({'note': '<p>Event Note</p>'})
|
||||
event_type.write({'note': '<p><br></p>'})
|
||||
event.write({'event_type_id': event_type.id})
|
||||
self.assertEqual(event.note, '<p>Event Note</p>')
|
||||
|
||||
# verify that note is correctly propagated if it contains non empty html
|
||||
event.write({'event_type_id': False})
|
||||
event_type.write({'note': '<p>Event Type Note</p>'})
|
||||
event.write({'event_type_id': event_type.id})
|
||||
self.assertEqual(event.note, '<p>Event Type Note</p>')
|
||||
|
||||
@users('user_eventmanager')
|
||||
def test_event_configuration_tickets_from_type(self):
|
||||
""" Test data computation (related to tickets) of event coming from its event.type template.
|
||||
This test uses pretty low level Form data checks, as manipulations in a non-saved Form are
|
||||
required to highlight an undesired behavior when switching event_type templates :
|
||||
event_ticket_ids not linked to a registration were generated and kept when switching between
|
||||
different templates in the Form, which could rapidly lead to a substantial amount of
|
||||
undesired lines. """
|
||||
# setup test records
|
||||
event_type_default = self.env['event.type'].create({
|
||||
'name': 'Type Default',
|
||||
'auto_confirm': True
|
||||
})
|
||||
event_type_tickets = self.env['event.type'].create({
|
||||
'name': 'Type Tickets',
|
||||
'auto_confirm': False
|
||||
})
|
||||
event_type_tickets.write({
|
||||
'event_type_ticket_ids': [
|
||||
Command.clear(),
|
||||
Command.create({
|
||||
'name': 'Default Ticket',
|
||||
'seats_max': 10,
|
||||
})
|
||||
]
|
||||
})
|
||||
event = self.env['event.event'].create({
|
||||
'name': 'Event',
|
||||
'date_begin': FieldsDatetime.to_string(datetime.today() + timedelta(days=1)),
|
||||
'date_end': FieldsDatetime.to_string(datetime.today() + timedelta(days=15)),
|
||||
'event_type_id': event_type_default.id
|
||||
})
|
||||
event.write({
|
||||
'event_ticket_ids': [
|
||||
Command.clear(),
|
||||
Command.create({
|
||||
'name': 'Registration Ticket',
|
||||
'seats_max': 10,
|
||||
})
|
||||
]
|
||||
})
|
||||
ticket = event.event_ticket_ids[0]
|
||||
registration = self._create_registrations(event, 1)
|
||||
# link the ticket to the registration
|
||||
registration.write({'event_ticket_id': ticket.id})
|
||||
# start test scenario
|
||||
event_form = Form(event)
|
||||
# verify that the ticket is linked to the event in the form
|
||||
self.assertEqual(
|
||||
set(map(lambda m: m.get('name', None), event_form.event_ticket_ids._records)),
|
||||
set(['Registration Ticket'])
|
||||
)
|
||||
# switch to an event_type with a ticket template which should be computed
|
||||
event_form.event_type_id = event_type_tickets
|
||||
# verify that both tickets are computed
|
||||
self.assertEqual(
|
||||
set(map(lambda m: m.get('name', None), event_form.event_ticket_ids._records)),
|
||||
set(['Registration Ticket', 'Default Ticket'])
|
||||
)
|
||||
# switch back to an event_type without default tickets
|
||||
event_form.event_type_id = event_type_default
|
||||
# verify that the ticket linked to the registration was kept, and the other removed
|
||||
self.assertEqual(
|
||||
set(map(lambda m: m.get('name', None), event_form.event_ticket_ids._records)),
|
||||
set(['Registration Ticket'])
|
||||
)
|
||||
|
||||
@users('user_eventmanager')
|
||||
def test_event_mail_default_config(self):
|
||||
event = self.env['event.event'].create({
|
||||
'name': 'Event Update Type',
|
||||
'date_begin': FieldsDatetime.to_string(datetime.today() + timedelta(days=1)),
|
||||
'date_end': FieldsDatetime.to_string(datetime.today() + timedelta(days=15)),
|
||||
})
|
||||
self.assertEqual(event.date_tz, self.env.user.tz)
|
||||
self.assertFalse(event.seats_limited)
|
||||
self.assertFalse(event.auto_confirm)
|
||||
|
||||
#Event Communications: when no event type, default configuration
|
||||
self.assertEqual(len(event.event_mail_ids), 3)
|
||||
self.assertEqual(event.event_mail_ids[0].interval_unit, 'now')
|
||||
self.assertEqual(event.event_mail_ids[0].interval_type, 'after_sub')
|
||||
self.assertEqual(event.event_mail_ids[0].template_ref, self.env.ref('event.event_subscription'))
|
||||
self.assertEqual(event.event_mail_ids[1].interval_nbr, 1)
|
||||
self.assertEqual(event.event_mail_ids[1].interval_unit, 'hours')
|
||||
self.assertEqual(event.event_mail_ids[1].interval_type, 'before_event')
|
||||
self.assertEqual(event.event_mail_ids[1].template_ref, self.env.ref('event.event_reminder'))
|
||||
self.assertEqual(event.event_mail_ids[2].interval_nbr, 3)
|
||||
self.assertEqual(event.event_mail_ids[2].interval_unit, 'days')
|
||||
self.assertEqual(event.event_mail_ids[2].interval_type, 'before_event')
|
||||
self.assertEqual(event.event_mail_ids[2].template_ref, self.env.ref('event.event_reminder'))
|
||||
|
||||
event.write({
|
||||
'event_mail_ids': False
|
||||
})
|
||||
self.assertEqual(event.event_mail_ids, self.env['event.mail'])
|
||||
|
||||
def test_event_mail_filter_template_on_event(self):
|
||||
"""Test that the mail template are filtered to show only those which are related to the event registration model.
|
||||
|
||||
This is important to be able to show only relevant mail templates on the related
|
||||
field "template_ref".
|
||||
"""
|
||||
self.env['mail.template'].search([('model', '=', 'event.registration')]).unlink()
|
||||
self.env['mail.template'].create({'model_id': self.env['ir.model']._get('event.registration').id, 'name': 'test template'})
|
||||
self.env['mail.template'].create({'model_id': self.env['ir.model']._get('res.partner').id, 'name': 'test template'})
|
||||
templates = self.env['mail.template'].with_context(filter_template_on_event=True).name_search('test template')
|
||||
self.assertEqual(len(templates), 1, 'Should return only mail templates related to the event registration model')
|
||||
|
||||
@freeze_time('2020-1-31 10:00:00')
|
||||
@users('user_eventmanager')
|
||||
def test_event_registrable(self):
|
||||
"""Test if `_compute_event_registrations_open` works properly."""
|
||||
event = self.event_0.with_user(self.env.user)
|
||||
event.write({
|
||||
'date_begin': datetime(2020, 1, 30, 8, 0, 0),
|
||||
'date_end': datetime(2020, 1, 31, 8, 0, 0),
|
||||
})
|
||||
self.assertFalse(event.event_registrations_open)
|
||||
event.write({
|
||||
'date_end': datetime(2020, 2, 4, 8, 0, 0),
|
||||
})
|
||||
self.assertTrue(event.event_registrations_open)
|
||||
|
||||
# ticket without dates boundaries -> ok
|
||||
ticket = self.env['event.event.ticket'].create({
|
||||
'name': 'TestTicket',
|
||||
'event_id': event.id,
|
||||
})
|
||||
self.assertTrue(event.event_registrations_open)
|
||||
|
||||
# even with valid tickets, date limits registrations
|
||||
event.write({
|
||||
'date_begin': datetime(2020, 1, 28, 15, 0, 0),
|
||||
'date_end': datetime(2020, 1, 30, 15, 0, 0),
|
||||
})
|
||||
self.assertFalse(event.event_registrations_open)
|
||||
|
||||
# no more seats available
|
||||
registration = self.env['event.registration'].create({
|
||||
'name': 'Albert Test',
|
||||
'event_id': event.id,
|
||||
})
|
||||
registration.action_confirm()
|
||||
event.write({
|
||||
'date_end': datetime(2020, 2, 1, 15, 0, 0),
|
||||
'seats_max': 1,
|
||||
'seats_limited': True,
|
||||
})
|
||||
self.assertEqual(event.seats_available, 0)
|
||||
self.assertFalse(event.event_registrations_open)
|
||||
|
||||
# seats available are back
|
||||
registration.unlink()
|
||||
self.assertEqual(event.seats_available, 1)
|
||||
self.assertTrue(event.event_registrations_open)
|
||||
|
||||
# but tickets are expired
|
||||
ticket.write({'end_sale_datetime': datetime(2020, 1, 30, 15, 0, 0)})
|
||||
self.assertTrue(ticket.is_expired)
|
||||
self.assertFalse(event.event_registrations_open)
|
||||
|
||||
@freeze_time('2020-1-31 10:00:00')
|
||||
@users('user_eventmanager')
|
||||
def test_event_ongoing(self):
|
||||
event_1 = self.env['event.event'].create({
|
||||
'name': 'Test Event 1',
|
||||
'date_begin': datetime(2020, 1, 25, 8, 0, 0),
|
||||
'date_end': datetime(2020, 2, 1, 18, 0, 0),
|
||||
})
|
||||
self.assertTrue(event_1.is_ongoing)
|
||||
ongoing_event_ids = self.env['event.event']._search([('is_ongoing', '=', True)])
|
||||
self.assertIn(event_1.id, ongoing_event_ids)
|
||||
|
||||
event_1.update({'date_begin': datetime(2020, 2, 1, 9, 0, 0)})
|
||||
self.assertFalse(event_1.is_ongoing)
|
||||
ongoing_event_ids = self.env['event.event']._search([('is_ongoing', '=', True)])
|
||||
self.assertNotIn(event_1.id, ongoing_event_ids)
|
||||
|
||||
event_2 = self.env['event.event'].create({
|
||||
'name': 'Test Event 2',
|
||||
'date_begin': datetime(2020, 1, 25, 8, 0, 0),
|
||||
'date_end': datetime(2020, 1, 28, 8, 0, 0),
|
||||
})
|
||||
self.assertFalse(event_2.is_ongoing)
|
||||
finished_or_upcoming_event_ids = self.env['event.event']._search([('is_ongoing', '=', False)])
|
||||
self.assertIn(event_2.id, finished_or_upcoming_event_ids)
|
||||
|
||||
event_2.update({'date_end': datetime(2020, 2, 2, 8, 0, 1)})
|
||||
self.assertTrue(event_2.is_ongoing)
|
||||
finished_or_upcoming_event_ids = self.env['event.event']._search([('is_ongoing', '=', False)])
|
||||
self.assertNotIn(event_2.id, finished_or_upcoming_event_ids)
|
||||
|
||||
@users('user_eventmanager')
|
||||
def test_event_seats(self):
|
||||
event_type = self.event_type_complex.with_user(self.env.user)
|
||||
event = self.env['event.event'].create({
|
||||
'name': 'Event Update Type',
|
||||
'event_type_id': event_type.id,
|
||||
'date_begin': FieldsDatetime.to_string(datetime.today() + timedelta(days=1)),
|
||||
'date_end': FieldsDatetime.to_string(datetime.today() + timedelta(days=15)),
|
||||
})
|
||||
|
||||
self.assertEqual(event.address_id, self.env.user.company_id.partner_id)
|
||||
# seats: coming from event type configuration
|
||||
self.assertTrue(event.seats_limited)
|
||||
self.assertEqual(event.seats_available, event.event_type_id.seats_max)
|
||||
self.assertEqual(event.seats_unconfirmed, 0)
|
||||
self.assertEqual(event.seats_reserved, 0)
|
||||
self.assertEqual(event.seats_used, 0)
|
||||
self.assertEqual(event.seats_expected, 0)
|
||||
|
||||
# create registration in order to check the seats computation
|
||||
self.assertTrue(event.auto_confirm)
|
||||
reg_open_multiple = self.env['event.registration'].create([{
|
||||
'event_id': event.id,
|
||||
'name': 'reg_open',
|
||||
} for _ in range(5)])
|
||||
self.assertEqual(set(reg_open_multiple.mapped('state')), {'open'})
|
||||
reg_open = reg_open_multiple[0]
|
||||
|
||||
reg_draft = self.env['event.registration'].create({
|
||||
'event_id': event.id,
|
||||
'name': 'reg_draft',
|
||||
})
|
||||
reg_draft.write({'state': 'draft'})
|
||||
reg_done = self.env['event.registration'].create({
|
||||
'event_id': event.id,
|
||||
'name': 'reg_done',
|
||||
})
|
||||
reg_done.write({'state': 'done'})
|
||||
self.assertEqual(event.seats_available, event.event_type_id.seats_max - 6)
|
||||
self.assertEqual(event.seats_unconfirmed, 1)
|
||||
self.assertEqual(event.seats_reserved, 5)
|
||||
self.assertEqual(event.seats_used, 1)
|
||||
self.assertEqual(event.seats_expected, 7)
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# SEATS AVAILABILITY AND (UN-)ARCHIVING REGISTRATIONS
|
||||
# ------------------------------------------------------------
|
||||
|
||||
# Archiving and seats availability
|
||||
reg_open.action_archive()
|
||||
self.assertEqual(event.seats_reserved, 4)
|
||||
self.assertEqual(event.seats_available, event.event_type_id.seats_max - 5)
|
||||
self.assertEqual(event.seats_expected, 6)
|
||||
|
||||
reg_draft.action_archive()
|
||||
self.assertEqual(event.seats_unconfirmed, 0)
|
||||
self.assertEqual(event.seats_available, event.event_type_id.seats_max - 5)
|
||||
self.assertEqual(event.seats_expected, 5)
|
||||
|
||||
# Un-archiving confirmed seats requires available seat(s)
|
||||
reg_open.action_unarchive()
|
||||
self.assertEqual(event.seats_reserved, 5)
|
||||
self.assertEqual(event.seats_available, event.event_type_id.seats_max - 6)
|
||||
self.assertEqual(event.seats_expected, 6)
|
||||
|
||||
reg_draft.action_unarchive()
|
||||
self.assertEqual(event.seats_unconfirmed, 1)
|
||||
self.assertEqual(event.seats_available, event.event_type_id.seats_max - 6)
|
||||
self.assertEqual(event.seats_expected, 7)
|
||||
|
||||
reg_open.action_archive()
|
||||
self.assertEqual(event.seats_reserved, 4)
|
||||
|
||||
# It is not possible to set a seats_max value below number of current
|
||||
# confirmed registrations. (4 "reserved" + 1 "used")
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
event.write({'seats_max': 4})
|
||||
event.write({'seats_max': 5})
|
||||
self.assertEqual(event.seats_available, 0)
|
||||
|
||||
# It is not possible to unarchive a confirmed seat if the event is fully booked
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
reg_open.action_unarchive()
|
||||
|
||||
# raising the limit allows it
|
||||
event.write({'seats_max': 6})
|
||||
self.assertEqual(reg_open.state, "open")
|
||||
reg_open.action_unarchive()
|
||||
|
||||
# It is not possible to confirm a draft reservation if the event is
|
||||
# fully booked
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
reg_draft.write({'state': 'open'})
|
||||
|
||||
# With auto-confirm, it is also impossible to create a draft
|
||||
# registration when the event is full
|
||||
new_draft_to_autoconfirm = {
|
||||
'event_id': event.id,
|
||||
'name': 'New registration with auto confirm'
|
||||
}
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.env['event.registration'].create(new_draft_to_autoconfirm)
|
||||
|
||||
# If the seats limitation is removed, it becomes possible of course
|
||||
event.write({'seats_limited': 0})
|
||||
self.env['event.registration'].create(new_draft_to_autoconfirm)
|
||||
|
||||
|
||||
@tagged('event_registration')
|
||||
class TestEventRegistrationData(TestEventInternalsCommon):
|
||||
|
||||
@users('user_eventmanager')
|
||||
def test_registration_partner_sync(self):
|
||||
""" Test registration computed fields about partner """
|
||||
test_email = '"Nibbler In Space" <nibbler@futurama.example.com>'
|
||||
test_phone = '0456001122'
|
||||
test_phone_fmt = '+32456001122'
|
||||
|
||||
event = self.env['event.event'].browse(self.event_0.ids)
|
||||
customer = self.env['res.partner'].browse(self.event_customer.id)
|
||||
|
||||
# take all from partner
|
||||
event.write({
|
||||
'registration_ids': [(0, 0, {
|
||||
'partner_id': customer.id,
|
||||
})]
|
||||
})
|
||||
new_reg = event.registration_ids[0]
|
||||
self.assertEqual(new_reg.partner_id, customer)
|
||||
self.assertEqual(new_reg.name, customer.name)
|
||||
self.assertEqual(new_reg.email, customer.email)
|
||||
self.assertEqual(new_reg.phone, customer.phone)
|
||||
|
||||
# partial update
|
||||
event.write({
|
||||
'registration_ids': [(0, 0, {
|
||||
'partner_id': customer.id,
|
||||
'name': 'Nibbler In Space',
|
||||
'email': test_email,
|
||||
})]
|
||||
})
|
||||
new_reg = event.registration_ids.sorted()[0]
|
||||
self.assertEqual(new_reg.partner_id, customer)
|
||||
self.assertEqual(
|
||||
new_reg.name, 'Nibbler In Space',
|
||||
'Registration should take user input over computed partner value')
|
||||
self.assertEqual(
|
||||
new_reg.email, test_email,
|
||||
'Registration should take user input over computed partner value')
|
||||
self.assertEqual(
|
||||
new_reg.phone, customer.phone,
|
||||
'Registration should take partner value if not user input')
|
||||
|
||||
# already filled information should not be updated
|
||||
event.write({
|
||||
'registration_ids': [(0, 0, {
|
||||
'name': 'Nibbler In Space',
|
||||
'phone': test_phone,
|
||||
})]
|
||||
})
|
||||
new_reg = event.registration_ids.sorted()[0]
|
||||
self.assertEqual(new_reg.name, 'Nibbler In Space')
|
||||
self.assertEqual(new_reg.email, False)
|
||||
self.assertEqual(new_reg.phone, test_phone_fmt)
|
||||
new_reg.write({'partner_id': customer.id})
|
||||
self.assertEqual(new_reg.partner_id, customer)
|
||||
self.assertEqual(new_reg.name, 'Nibbler In Space')
|
||||
self.assertEqual(new_reg.email, customer.email)
|
||||
self.assertEqual(new_reg.phone, test_phone_fmt)
|
||||
|
||||
@users('user_eventmanager')
|
||||
def test_registration_partner_sync_company(self):
|
||||
""" Test synchronization involving companies """
|
||||
event = self.env['event.event'].browse(self.event_0.ids)
|
||||
customer = self.env['res.partner'].browse(self.event_customer.id)
|
||||
|
||||
# create company structure (using sudo as required partner manager group)
|
||||
company = self.env['res.partner'].sudo().create({
|
||||
'name': 'Customer Company',
|
||||
'is_company': True,
|
||||
'type': 'other',
|
||||
})
|
||||
customer.sudo().write({'type': 'invoice', 'parent_id': company.id})
|
||||
contact = self.env['res.partner'].sudo().create({
|
||||
'name': 'ContactName',
|
||||
'parent_id': company.id,
|
||||
'type': 'contact',
|
||||
'email': 'ContactEmail <contact.email@test.example.com>',
|
||||
'phone': '+32456998877',
|
||||
})
|
||||
|
||||
# take all from partner
|
||||
event.write({
|
||||
'registration_ids': [(0, 0, {
|
||||
'partner_id': customer.id,
|
||||
})]
|
||||
})
|
||||
new_reg = event.registration_ids[0]
|
||||
self.assertEqual(new_reg.partner_id, customer)
|
||||
self.assertEqual(new_reg.name, contact.name)
|
||||
self.assertEqual(new_reg.email, contact.email)
|
||||
self.assertEqual(new_reg.phone, contact.phone)
|
||||
|
||||
|
||||
@tagged('event_registration', 'phone_number')
|
||||
class TestEventRegistrationPhone(EventCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
cls.test_event_address = cls.env['res.partner'].create({
|
||||
'city': 'Gandhinagar',
|
||||
'country_id': cls.env.ref("base.in").id,
|
||||
'name': 'Odoo In',
|
||||
'zip': '382007',
|
||||
})
|
||||
cls.test_event = cls.env['event.event'].create({
|
||||
'address_id': cls.test_event_address.id,
|
||||
'company_id': cls.company_admin.id,
|
||||
'date_begin': datetime(2023, 6, 5, 8, 0, 0),
|
||||
'date_end': datetime(2023, 6, 8, 18, 0, 0),
|
||||
'name': 'Test Phone Format',
|
||||
})
|
||||
|
||||
@users('user_eventregistrationdesk')
|
||||
def test_assert_initial_values(self):
|
||||
customer = self.event_customer.with_env(self.env)
|
||||
customer2 = self.event_customer2.with_env(self.env)
|
||||
event = self.test_event.with_env(self.env)
|
||||
|
||||
self.assertFalse(customer.mobile)
|
||||
self.assertEqual(customer.phone, '0485112233')
|
||||
self.assertEqual(customer2.mobile, '0456654321')
|
||||
self.assertEqual(customer2.phone, '0456987654')
|
||||
|
||||
self.assertEqual(event.company_id.country_id, self.env.ref("base.be"))
|
||||
self.assertEqual(event.country_id, self.env.ref("base.in"))
|
||||
|
||||
@users('user_eventregistrationdesk')
|
||||
def test_registration_form_phone(self):
|
||||
""" Test onchange on phone / mobile, should try to format number """
|
||||
event = self.test_event.with_user(self.env.user)
|
||||
|
||||
lead_form = Form(self.env['event.registration'])
|
||||
lead_form.event_id = event
|
||||
lead_form.mobile = '7200000011'
|
||||
lead_form.phone = '7200000000'
|
||||
self.assertEqual(lead_form.mobile, '+917200000011')
|
||||
self.assertEqual(lead_form.phone, '+917200000000')
|
||||
|
||||
@users('user_eventregistrationdesk')
|
||||
def test_registration_phone_format(self):
|
||||
""" Test phone formatting: based on partner (BE numbers) or event
|
||||
(IN numbers) or company (BE numbers). """
|
||||
event = self.test_event.with_user(self.env.user)
|
||||
|
||||
# customer_id, mobile, phone -> based on partner or event country
|
||||
sources = [
|
||||
(self.event_customer.id, None, None), # BE local on partner
|
||||
(self.event_customer2.id, None, None), # BE local on partner
|
||||
(self.event_customer2.id, '0456001122', None), # BE local + on partner
|
||||
(False, '0456778899', '+32456778899'), # BE local + BE global
|
||||
(False, '7200000000', False), # IN local
|
||||
(False, False, '7200000011'), # IN local
|
||||
(False, '7200000000', '7200000011'), # IN local
|
||||
(False, '+917200000088', '+917200000099'), # IN global
|
||||
]
|
||||
# mobile, phone
|
||||
expected = [
|
||||
(False, '0485112233'), # partner values, no format
|
||||
('0456654321', '0456987654'), # partner values, no format
|
||||
('+32456001122', '0456987654'), # BE on partner / partner value, no format
|
||||
('0456778899', '+32456778899'), # IN on event -> cannot format BE
|
||||
('+917200000000', False), # IN on event
|
||||
(False, '+917200000011'), # IN on event
|
||||
('+917200000000', '+917200000011'), # IN on event
|
||||
('+917200000088', '+917200000099'), # already formatted
|
||||
]
|
||||
for (partner_id, mobile, phone), (exp_mobile, exp_phone) in zip(sources, expected):
|
||||
with self.subTest(partner_id=partner_id, mobile=mobile, phone=phone):
|
||||
create_vals = {
|
||||
'event_id': event.id,
|
||||
'partner_id': partner_id,
|
||||
}
|
||||
if mobile is not None:
|
||||
create_vals['mobile'] = mobile
|
||||
if phone is not None:
|
||||
create_vals['phone'] = phone
|
||||
reg = self.env['event.registration'].create(create_vals)
|
||||
self.assertEqual(reg.mobile, exp_mobile)
|
||||
self.assertEqual(reg.phone, exp_phone)
|
||||
|
||||
# no country on event -> based on partner or event company country
|
||||
self.test_event.write({'address_id': False})
|
||||
expected = [
|
||||
(False, '0485112233'), # partner values, no format
|
||||
('0456654321', '0456987654'), # partner values, no format
|
||||
('+32456001122', '0456987654'), # BE on partner / partner value, no format
|
||||
('+32456778899', '+32456778899'), # BE on company
|
||||
('7200000000', False), # BE on company -> cannot format IN
|
||||
(False, '7200000011'), # BE on company -> cannot format IN
|
||||
('7200000000', '7200000011'), # BE on company -> cannot format IN
|
||||
('+917200000088', '+917200000099'), # already formatted
|
||||
]
|
||||
for (partner_id, mobile, phone), (exp_mobile, exp_phone) in zip(sources, expected):
|
||||
with self.subTest(partner_id=partner_id, mobile=mobile, phone=phone):
|
||||
create_vals = {
|
||||
'event_id': event.id,
|
||||
'partner_id': partner_id,
|
||||
}
|
||||
if mobile is not None:
|
||||
create_vals['mobile'] = mobile
|
||||
if phone is not None:
|
||||
create_vals['phone'] = phone
|
||||
reg = self.env['event.registration'].create(create_vals)
|
||||
self.assertEqual(reg.mobile, exp_mobile)
|
||||
self.assertEqual(reg.phone, exp_phone)
|
||||
|
||||
|
||||
@tagged('event_ticket')
|
||||
class TestEventTicketData(TestEventInternalsCommon):
|
||||
|
||||
@freeze_time('2020-1-31 10:00:00')
|
||||
@users('user_eventmanager')
|
||||
def test_event_ticket_fields(self):
|
||||
""" Test event ticket fields synchronization """
|
||||
INITIAL_TICKET_SEATS_MAX = 30
|
||||
event = self.event_0.with_user(self.env.user)
|
||||
event.write({
|
||||
'event_ticket_ids': [
|
||||
(5, 0),
|
||||
(0, 0, {
|
||||
'name': 'First Ticket',
|
||||
'seats_max': INITIAL_TICKET_SEATS_MAX,
|
||||
}), (0, 0, { # limited in time, available (01/10 (start) < 01/31 (today) < 02/10 (end))
|
||||
'name': 'Second Ticket',
|
||||
'start_sale_datetime': datetime(2020, 1, 10, 0, 0, 0),
|
||||
'end_sale_datetime': datetime(2020, 2, 10, 23, 59, 59),
|
||||
})
|
||||
],
|
||||
'auto_confirm': False # to interact with registrations states
|
||||
})
|
||||
first_ticket = event.event_ticket_ids.filtered(lambda t: t.name == 'First Ticket')
|
||||
second_ticket = event.event_ticket_ids.filtered(lambda t: t.name == 'Second Ticket')
|
||||
|
||||
self.assertTrue(first_ticket.seats_limited)
|
||||
self.assertTrue(first_ticket.sale_available)
|
||||
self.assertFalse(first_ticket.is_expired)
|
||||
|
||||
self.assertFalse(second_ticket.seats_limited)
|
||||
self.assertTrue(second_ticket.sale_available)
|
||||
self.assertFalse(second_ticket.is_expired)
|
||||
# sale is ended
|
||||
second_ticket.write({'end_sale_datetime': datetime(2020, 1, 20, 23, 59, 59)})
|
||||
self.assertFalse(second_ticket.sale_available)
|
||||
self.assertTrue(second_ticket.is_expired)
|
||||
# sale has not started
|
||||
second_ticket.write({
|
||||
'start_sale_datetime': datetime(2020, 2, 10, 0, 0, 0),
|
||||
'end_sale_datetime': datetime(2020, 2, 20, 23, 59, 59),
|
||||
})
|
||||
self.assertFalse(second_ticket.sale_available)
|
||||
self.assertFalse(second_ticket.is_expired)
|
||||
# sale started today
|
||||
second_ticket.write({
|
||||
'start_sale_datetime': datetime(2020, 1, 31, 0, 0, 0),
|
||||
'end_sale_datetime': datetime(2020, 2, 20, 23, 59, 59),
|
||||
})
|
||||
self.assertTrue(second_ticket.sale_available)
|
||||
self.assertTrue(second_ticket.is_launched)
|
||||
self.assertFalse(second_ticket.is_expired)
|
||||
# incoherent dates are invalid
|
||||
with self.assertRaises(exceptions.UserError):
|
||||
second_ticket.write({'end_sale_datetime': datetime(2020, 1, 20, 23, 59, 59)})
|
||||
|
||||
#test if event start/end dates are taking datetime fields (hours, minutes, seconds) into account
|
||||
second_ticket.write({'start_sale_datetime': datetime(2020, 1, 31, 11, 0, 0)})
|
||||
self.assertFalse(second_ticket.sale_available)
|
||||
self.assertFalse(second_ticket.is_launched)
|
||||
|
||||
second_ticket.write({
|
||||
'start_sale_datetime': datetime(2020, 1, 31, 7, 0, 0),
|
||||
'end_sale_datetime': datetime(2020, 2, 27, 13, 0, 0)
|
||||
})
|
||||
|
||||
self.assertTrue(second_ticket.sale_available)
|
||||
self.assertTrue(second_ticket.is_launched)
|
||||
self.assertFalse(second_ticket.is_expired)
|
||||
|
||||
second_ticket.write({
|
||||
'end_sale_datetime': datetime(2020, 1, 31, 9, 0, 0)
|
||||
})
|
||||
|
||||
self.assertFalse(second_ticket.sale_available)
|
||||
self.assertTrue(second_ticket.is_expired)
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# (UN -)ARCHIVING REGISTRATIONS AND SEATS AVAILABILITY
|
||||
# ------------------------------------------------------------
|
||||
|
||||
# Archiving and seats availability
|
||||
reg_draft_multiple = self.env['event.registration'].create([{
|
||||
'event_id': event.id,
|
||||
'name': f'reg_draft #{idx}',
|
||||
'event_ticket_id': first_ticket.id,
|
||||
} for idx in range(3)])
|
||||
reg_draft = reg_draft_multiple[0]
|
||||
|
||||
reg_open = self.env['event.registration'].create({
|
||||
'event_id': event.id,
|
||||
'name': 'reg_open',
|
||||
'event_ticket_id': first_ticket.id,
|
||||
'state': 'open'
|
||||
})
|
||||
|
||||
reg_done = self.env['event.registration'].create({
|
||||
'event_id': event.id,
|
||||
'name': 'reg_done',
|
||||
'event_ticket_id': first_ticket.id,
|
||||
'state': 'done'
|
||||
})
|
||||
|
||||
self.assertEqual(first_ticket.seats_unconfirmed, 3)
|
||||
self.assertEqual(first_ticket.seats_reserved, 1)
|
||||
self.assertEqual(first_ticket.seats_used, 1)
|
||||
self.assertEqual(first_ticket.seats_available, INITIAL_TICKET_SEATS_MAX - 2)
|
||||
|
||||
reg_done.action_archive()
|
||||
self.assertEqual(first_ticket.seats_used, 0)
|
||||
self.assertEqual(first_ticket.seats_available, INITIAL_TICKET_SEATS_MAX - 1)
|
||||
|
||||
reg_open.action_archive()
|
||||
self.assertEqual(first_ticket.seats_reserved, 0)
|
||||
self.assertEqual(first_ticket.seats_available, INITIAL_TICKET_SEATS_MAX)
|
||||
|
||||
reg_draft.action_archive()
|
||||
self.assertEqual(first_ticket.seats_unconfirmed, 2)
|
||||
|
||||
# Un-archiving confirmed/done seats requires available seat(s)
|
||||
reg_open.action_unarchive()
|
||||
self.assertEqual(first_ticket.seats_reserved, 1)
|
||||
self.assertEqual(first_ticket.seats_available, INITIAL_TICKET_SEATS_MAX - 1)
|
||||
|
||||
reg_done.action_unarchive()
|
||||
self.assertEqual(first_ticket.seats_used, 1)
|
||||
self.assertEqual(first_ticket.seats_available, INITIAL_TICKET_SEATS_MAX - 2)
|
||||
|
||||
reg_draft.action_unarchive()
|
||||
self.assertEqual(first_ticket.seats_unconfirmed, 3)
|
||||
self.assertEqual(first_ticket.seats_available, INITIAL_TICKET_SEATS_MAX - 2)
|
||||
|
||||
# It is not possible to set a seats_max value below the current number of confirmed
|
||||
# registrations. (There is still 1 "used" seat too)
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
first_ticket.write({'seats_max': 1})
|
||||
|
||||
reg_open.action_archive()
|
||||
first_ticket.write({'seats_max': 1})
|
||||
|
||||
# It is not possible to unarchive confirmed seat if ticket is fully booked
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
reg_open.action_unarchive()
|
||||
|
||||
# SEATS AVAILABILITY
|
||||
|
||||
# With auto-confirm, it is impossible to create a draft
|
||||
# registration when the ticket is fully booked (1 used + 1 reserved)
|
||||
self.assertEqual(event.seats_available, 0)
|
||||
first_ticket.event_id.auto_confirm = True
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
self.env['event.registration'].create({
|
||||
'event_id': event.id,
|
||||
'name': 'New registration with auto confirm',
|
||||
'event_ticket_id': first_ticket.id,
|
||||
})
|
||||
|
||||
# It is not possible to convert a draft to an open registration
|
||||
# when the event is fully booked
|
||||
with self.assertRaises(exceptions.ValidationError):
|
||||
reg_draft.write({'state': 'open'})
|
||||
|
||||
|
||||
@tagged('event_event')
|
||||
class TestEventTypeData(TestEventInternalsCommon):
|
||||
|
||||
@users('user_eventmanager')
|
||||
def test_event_type_fields(self):
|
||||
""" Test event type fields synchronization """
|
||||
# create test type and ensure its initial values
|
||||
event_type = self.env['event.type'].create({
|
||||
'name': 'Testing fields computation',
|
||||
'has_seats_limitation': True,
|
||||
'seats_max': 30,
|
||||
})
|
||||
self.assertTrue(event_type.has_seats_limitation)
|
||||
self.assertEqual(event_type.seats_max, 30)
|
||||
|
||||
# reset seats limitation
|
||||
event_type.write({'has_seats_limitation': False})
|
||||
self.assertFalse(event_type.has_seats_limitation)
|
||||
self.assertEqual(event_type.seats_max, 0)
|
||||
|
|
@ -0,0 +1,408 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
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
|
||||
|
||||
|
||||
class TestMailSchedule(EventCase, MockEmail):
|
||||
|
||||
@mute_logger('odoo.addons.base.models.ir_model', 'odoo.models')
|
||||
def test_event_mail_schedule(self):
|
||||
""" Test mail scheduling for events """
|
||||
self.env.company.write({
|
||||
'name': 'YourCompany',
|
||||
'email': 'info@yourcompany.example.com',
|
||||
})
|
||||
event_cron_id = self.env.ref('event.event_mail_scheduler')
|
||||
|
||||
# deactivate other schedulers to avoid messing with crons
|
||||
self.env['event.mail'].search([]).unlink()
|
||||
|
||||
# freeze some datetimes, and ensure more than 1D+1H before event starts
|
||||
# to ease time-based scheduler check
|
||||
# Since `now` is used to set the `create_date` of an event and create_date
|
||||
# has often microseconds, we set it to ensure that the scheduler we still be
|
||||
# launched if scheduled_date == create_date - microseconds
|
||||
now = datetime(2021, 3, 20, 14, 30, 15, 123456)
|
||||
event_date_begin = datetime(2021, 3, 22, 8, 0, 0)
|
||||
event_date_end = datetime(2021, 3, 24, 18, 0, 0)
|
||||
|
||||
with freeze_time(now):
|
||||
# create with admin to force create_date
|
||||
test_event = self.env['event.event'].create({
|
||||
'name': 'TestEventMail',
|
||||
'create_date': now,
|
||||
'user_id': self.user_eventmanager.id,
|
||||
'auto_confirm': True,
|
||||
'date_begin': event_date_begin,
|
||||
'date_end': event_date_end,
|
||||
'event_mail_ids': [
|
||||
(0, 0, { # right at subscription
|
||||
'interval_unit': 'now',
|
||||
'interval_type': 'after_sub',
|
||||
'template_ref': 'mail.template,%i' % self.env['ir.model.data']._xmlid_to_res_id('event.event_subscription')}),
|
||||
(0, 0, { # one day after subscription
|
||||
'interval_nbr': 1,
|
||||
'interval_unit': 'hours',
|
||||
'interval_type': 'after_sub',
|
||||
'template_ref': 'mail.template,%i' % self.env['ir.model.data']._xmlid_to_res_id('event.event_subscription')}),
|
||||
(0, 0, { # 1 days before event
|
||||
'interval_nbr': 1,
|
||||
'interval_unit': 'days',
|
||||
'interval_type': 'before_event',
|
||||
'template_ref': 'mail.template,%i' % self.env['ir.model.data']._xmlid_to_res_id('event.event_reminder')}),
|
||||
(0, 0, { # immediately after event
|
||||
'interval_nbr': 1,
|
||||
'interval_unit': 'hours',
|
||||
'interval_type': 'after_event',
|
||||
'template_ref': 'mail.template,%i' % self.env['ir.model.data']._xmlid_to_res_id('event.event_reminder')}),
|
||||
]
|
||||
})
|
||||
self.assertEqual(test_event.create_date, now)
|
||||
|
||||
# check subscription scheduler
|
||||
after_sub_scheduler = self.env['event.mail'].search([('event_id', '=', test_event.id), ('interval_type', '=', 'after_sub'), ('interval_unit', '=', 'now')])
|
||||
self.assertEqual(len(after_sub_scheduler), 1, 'event: wrong scheduler creation')
|
||||
self.assertEqual(after_sub_scheduler.scheduled_date, test_event.create_date.replace(microsecond=0))
|
||||
self.assertFalse(after_sub_scheduler.mail_done)
|
||||
self.assertEqual(after_sub_scheduler.mail_state, 'running')
|
||||
self.assertEqual(after_sub_scheduler.mail_count_done, 0)
|
||||
after_sub_scheduler_2 = self.env['event.mail'].search([('event_id', '=', test_event.id), ('interval_type', '=', 'after_sub'), ('interval_unit', '=', 'hours')])
|
||||
self.assertEqual(len(after_sub_scheduler_2), 1, 'event: wrong scheduler creation')
|
||||
self.assertEqual(after_sub_scheduler_2.scheduled_date, test_event.create_date.replace(microsecond=0) + relativedelta(hours=1))
|
||||
self.assertFalse(after_sub_scheduler_2.mail_done)
|
||||
self.assertEqual(after_sub_scheduler_2.mail_state, 'running')
|
||||
self.assertEqual(after_sub_scheduler_2.mail_count_done, 0)
|
||||
# check before event scheduler
|
||||
event_prev_scheduler = self.env['event.mail'].search([('event_id', '=', test_event.id), ('interval_type', '=', 'before_event')])
|
||||
self.assertEqual(len(event_prev_scheduler), 1, 'event: wrong scheduler creation')
|
||||
self.assertEqual(event_prev_scheduler.scheduled_date, event_date_begin + relativedelta(days=-1))
|
||||
self.assertFalse(event_prev_scheduler.mail_done)
|
||||
self.assertEqual(event_prev_scheduler.mail_state, 'scheduled')
|
||||
self.assertEqual(event_prev_scheduler.mail_count_done, 0)
|
||||
# check after event scheduler
|
||||
event_next_scheduler = self.env['event.mail'].search([('event_id', '=', test_event.id), ('interval_type', '=', 'after_event')])
|
||||
self.assertEqual(len(event_next_scheduler), 1, 'event: wrong scheduler creation')
|
||||
self.assertEqual(event_next_scheduler.scheduled_date, event_date_end + relativedelta(hours=1))
|
||||
self.assertFalse(event_next_scheduler.mail_done)
|
||||
self.assertEqual(event_next_scheduler.mail_state, 'scheduled')
|
||||
self.assertEqual(event_next_scheduler.mail_count_done, 0)
|
||||
|
||||
# create some registrations
|
||||
with freeze_time(now), self.mock_mail_gateway():
|
||||
reg1 = self.env['event.registration'].create({
|
||||
'create_date': now,
|
||||
'event_id': test_event.id,
|
||||
'name': 'Reg1',
|
||||
'email': 'reg1@example.com',
|
||||
})
|
||||
reg2 = self.env['event.registration'].create({
|
||||
'create_date': now,
|
||||
'event_id': test_event.id,
|
||||
'name': 'Reg2',
|
||||
'email': 'reg2@example.com',
|
||||
})
|
||||
|
||||
# REGISTRATIONS / PRE SCHEDULERS
|
||||
# --------------------------------------------------
|
||||
|
||||
# check registration state
|
||||
self.assertTrue(all(reg.state == 'open' for reg in reg1 + reg2), 'Registrations: should be auto-confirmed')
|
||||
self.assertTrue(all(reg.create_date == now for reg in reg1 + reg2), 'Registrations: should have open date set to confirm date')
|
||||
|
||||
# verify that subscription scheduler was auto-executed after each registration
|
||||
self.assertEqual(len(after_sub_scheduler.mail_registration_ids), 2, 'event: should have 2 scheduled communication (1 / registration)')
|
||||
for mail_registration in after_sub_scheduler.mail_registration_ids:
|
||||
self.assertEqual(mail_registration.scheduled_date, now.replace(microsecond=0))
|
||||
self.assertTrue(mail_registration.mail_sent, 'event: registration mail should be sent at registration creation')
|
||||
self.assertTrue(after_sub_scheduler.mail_done, 'event: all subscription mails should have been sent')
|
||||
self.assertEqual(after_sub_scheduler.mail_state, 'running')
|
||||
self.assertEqual(after_sub_scheduler.mail_count_done, 2)
|
||||
|
||||
# check emails effectively sent
|
||||
self.assertEqual(len(self._new_mails), 2, 'event: should have 2 scheduled emails (1 / registration)')
|
||||
self.assertMailMailWEmails(
|
||||
[formataddr((reg1.name, reg1.email)), formataddr((reg2.name, reg2.email))],
|
||||
'outgoing',
|
||||
content=None,
|
||||
fields_values={'subject': 'Your registration at %s' % test_event.name,
|
||||
'email_from': self.user_eventmanager.company_id.email_formatted,
|
||||
})
|
||||
|
||||
# same for second scheduler: scheduled but not sent
|
||||
self.assertEqual(len(after_sub_scheduler_2.mail_registration_ids), 2, 'event: should have 2 scheduled communication (1 / registration)')
|
||||
for mail_registration in after_sub_scheduler_2.mail_registration_ids:
|
||||
self.assertEqual(mail_registration.scheduled_date, now.replace(microsecond=0) + relativedelta(hours=1))
|
||||
self.assertFalse(mail_registration.mail_sent, 'event: registration mail should be scheduled, not sent')
|
||||
self.assertFalse(after_sub_scheduler_2.mail_done, 'event: all subscription mails should be scheduled, not sent')
|
||||
self.assertEqual(after_sub_scheduler_2.mail_count_done, 0)
|
||||
|
||||
# execute event reminder scheduler explicitly, before scheduled date -> should not do anything
|
||||
with freeze_time(now), self.mock_mail_gateway():
|
||||
after_sub_scheduler_2.execute()
|
||||
self.assertFalse(any(mail_reg.mail_sent for mail_reg in after_sub_scheduler_2.mail_registration_ids))
|
||||
self.assertFalse(after_sub_scheduler_2.mail_done)
|
||||
self.assertEqual(after_sub_scheduler_2.mail_count_done, 0)
|
||||
self.assertEqual(len(self._new_mails), 0, 'event: should not send mails before scheduled date')
|
||||
|
||||
# execute event reminder scheduler explicitly, right at scheduled date -> should sent mails
|
||||
now_registration = now + relativedelta(hours=1)
|
||||
with freeze_time(now_registration), self.mock_mail_gateway():
|
||||
after_sub_scheduler_2.execute()
|
||||
|
||||
# verify that subscription scheduler was auto-executed after each registration
|
||||
self.assertEqual(len(after_sub_scheduler_2.mail_registration_ids), 2, 'event: should have 2 scheduled communication (1 / registration)')
|
||||
self.assertTrue(all(mail_reg.mail_sent for mail_reg in after_sub_scheduler_2.mail_registration_ids))
|
||||
self.assertTrue(after_sub_scheduler_2.mail_done, 'event: all subscription mails should have been sent')
|
||||
self.assertEqual(after_sub_scheduler_2.mail_state, 'running')
|
||||
self.assertEqual(after_sub_scheduler_2.mail_count_done, 2)
|
||||
|
||||
# check emails effectively sent
|
||||
self.assertEqual(len(self._new_mails), 2, 'event: should have 2 scheduled emails (1 / registration)')
|
||||
self.assertMailMailWEmails(
|
||||
[formataddr((reg1.name, reg1.email)), formataddr((reg2.name, reg2.email))],
|
||||
'outgoing',
|
||||
content=None,
|
||||
fields_values={'subject': 'Your registration at %s' % test_event.name,
|
||||
'email_from': self.user_eventmanager.company_id.email_formatted,
|
||||
})
|
||||
|
||||
# PRE SCHEDULERS (MOVE FORWARD IN TIME)
|
||||
# --------------------------------------------------
|
||||
|
||||
self.assertFalse(event_prev_scheduler.mail_done)
|
||||
self.assertEqual(event_prev_scheduler.mail_state, 'scheduled')
|
||||
|
||||
# simulate cron running before scheduled date -> should not do anything
|
||||
now_start = event_date_begin + relativedelta(hours=-25, microsecond=654321)
|
||||
with freeze_time(now_start), self.mock_mail_gateway():
|
||||
event_cron_id.method_direct_trigger()
|
||||
|
||||
self.assertFalse(event_prev_scheduler.mail_done)
|
||||
self.assertEqual(event_prev_scheduler.mail_state, 'scheduled')
|
||||
self.assertEqual(event_prev_scheduler.mail_count_done, 0)
|
||||
self.assertEqual(len(self._new_mails), 0)
|
||||
|
||||
# execute cron to run schedulers after scheduled date
|
||||
now_start = event_date_begin + relativedelta(hours=-23, microsecond=654321)
|
||||
with freeze_time(now_start), self.mock_mail_gateway():
|
||||
event_cron_id.method_direct_trigger()
|
||||
|
||||
# check that scheduler is finished
|
||||
self.assertTrue(event_prev_scheduler.mail_done, 'event: reminder scheduler should have run')
|
||||
self.assertEqual(event_prev_scheduler.mail_state, 'sent', 'event: reminder scheduler should have run')
|
||||
|
||||
# check emails effectively sent
|
||||
self.assertEqual(len(self._new_mails), 2, 'event: should have scheduled 2 mails (1 / registration)')
|
||||
self.assertMailMailWEmails(
|
||||
[formataddr((reg1.name, reg1.email)), formataddr((reg2.name, reg2.email))],
|
||||
'outgoing',
|
||||
content=None,
|
||||
fields_values={'subject': '%s: tomorrow' % test_event.name,
|
||||
'email_from': self.user_eventmanager.company_id.email_formatted,
|
||||
})
|
||||
|
||||
# NEW REGISTRATION EFFECT ON SCHEDULERS
|
||||
# --------------------------------------------------
|
||||
|
||||
test_event.write({'auto_confirm': False})
|
||||
with freeze_time(now_start), self.mock_mail_gateway():
|
||||
reg3 = self.env['event.registration'].create({
|
||||
'create_date': now_start,
|
||||
'event_id': test_event.id,
|
||||
'name': 'Reg3',
|
||||
'email': 'reg3@example.com',
|
||||
})
|
||||
|
||||
# no more seats
|
||||
self.assertEqual(reg3.state, 'draft')
|
||||
|
||||
# schedulers state untouched
|
||||
self.assertTrue(event_prev_scheduler.mail_done)
|
||||
self.assertFalse(event_next_scheduler.mail_done)
|
||||
self.assertTrue(after_sub_scheduler.mail_done, 'event: scheduler on registration not updated next to draft registration')
|
||||
self.assertTrue(after_sub_scheduler_2.mail_done, 'event: scheduler on registration not updated next to draft registration')
|
||||
|
||||
# confirm registration -> should trigger registration schedulers
|
||||
# NOTE: currently all schedulers are based on create_date
|
||||
# meaning several communications may be sent in the time time
|
||||
with freeze_time(now_start + relativedelta(hours=1)), self.mock_mail_gateway():
|
||||
reg3.action_confirm()
|
||||
|
||||
# verify that subscription scheduler was auto-executed after new registration confirmed
|
||||
self.assertEqual(len(after_sub_scheduler.mail_registration_ids), 3, 'event: should have 3 scheduled communication (1 / registration)')
|
||||
new_mail_reg = after_sub_scheduler.mail_registration_ids.filtered(lambda mail_reg: mail_reg.registration_id == reg3)
|
||||
self.assertEqual(new_mail_reg.scheduled_date, now_start.replace(microsecond=0))
|
||||
self.assertTrue(new_mail_reg.mail_sent, 'event: registration mail should be sent at registration creation')
|
||||
self.assertTrue(after_sub_scheduler.mail_done, 'event: all subscription mails should have been sent')
|
||||
self.assertEqual(after_sub_scheduler.mail_count_done, 3)
|
||||
# verify that subscription scheduler was auto-executed after new registration confirmed
|
||||
self.assertEqual(len(after_sub_scheduler_2.mail_registration_ids), 3, 'event: should have 3 scheduled communication (1 / registration)')
|
||||
new_mail_reg = after_sub_scheduler_2.mail_registration_ids.filtered(lambda mail_reg: mail_reg.registration_id == reg3)
|
||||
self.assertEqual(new_mail_reg.scheduled_date, now_start.replace(microsecond=0) + relativedelta(hours=1))
|
||||
self.assertTrue(new_mail_reg.mail_sent, 'event: registration mail should be sent at registration creation')
|
||||
self.assertTrue(after_sub_scheduler_2.mail_done, 'event: all subscription mails should have been sent')
|
||||
self.assertEqual(after_sub_scheduler_2.mail_count_done, 3)
|
||||
|
||||
# check emails effectively sent
|
||||
self.assertEqual(len(self._new_mails), 2, 'event: should have 1 scheduled emails (new registration only)')
|
||||
# manual check because 2 identical mails are sent and mail tools do not support it easily
|
||||
for mail in self._new_mails:
|
||||
self.assertEqual(mail.email_from, self.user_eventmanager.company_id.email_formatted)
|
||||
self.assertEqual(mail.subject, 'Your registration at %s' % test_event.name)
|
||||
self.assertEqual(mail.state, 'outgoing')
|
||||
self.assertEqual(mail.email_to, formataddr((reg3.name, reg3.email)))
|
||||
|
||||
# POST SCHEDULERS (MOVE FORWARD IN TIME)
|
||||
# --------------------------------------------------
|
||||
|
||||
self.assertFalse(event_next_scheduler.mail_done)
|
||||
|
||||
# execute event reminder scheduler explicitly after its schedule date
|
||||
new_end = event_date_end + relativedelta(hours=2)
|
||||
with freeze_time(new_end), self.mock_mail_gateway():
|
||||
event_cron_id.method_direct_trigger()
|
||||
|
||||
# check that scheduler is finished
|
||||
self.assertTrue(event_next_scheduler.mail_done, 'event: reminder scheduler should should have run')
|
||||
self.assertEqual(event_next_scheduler.mail_state, 'sent', 'event: reminder scheduler should have run')
|
||||
self.assertEqual(event_next_scheduler.mail_count_done, 3)
|
||||
|
||||
# check emails effectively sent
|
||||
self.assertEqual(len(self._new_mails), 3, 'event: should have scheduled 3 mails, one for each registration')
|
||||
self.assertMailMailWEmails(
|
||||
[formataddr((reg1.name, reg1.email)), formataddr((reg2.name, reg2.email)), formataddr((reg3.name, reg3.email))],
|
||||
'outgoing',
|
||||
content=None,
|
||||
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")
|
||||
|
||||
@mute_logger('odoo.addons.base.models.ir_model', 'odoo.models')
|
||||
def test_archived_event_mail_schedule(self):
|
||||
""" Test mail scheduling for archived events """
|
||||
event_cron_id = self.env.ref('event.event_mail_scheduler')
|
||||
|
||||
# deactivate other schedulers to avoid messing with crons
|
||||
self.env['event.mail'].search([]).unlink()
|
||||
|
||||
# freeze some datetimes, and ensure more than 1D+1H before event starts
|
||||
# to ease time-based scheduler check
|
||||
now = datetime(2023, 7, 24, 14, 30, 15)
|
||||
event_date_begin = datetime(2023, 7, 26, 8, 0, 0)
|
||||
event_date_end = datetime(2023, 7, 28, 18, 0, 0)
|
||||
|
||||
with freeze_time(now):
|
||||
test_event = self.env['event.event'].with_user(self.user_eventmanager).create({
|
||||
'name': 'TestEventMail',
|
||||
'auto_confirm': True,
|
||||
'date_begin': event_date_begin,
|
||||
'date_end': event_date_end,
|
||||
'event_mail_ids': [
|
||||
(0, 0, { # right at subscription
|
||||
'interval_unit': 'now',
|
||||
'interval_type': 'after_sub',
|
||||
'template_ref': 'mail.template,%i' % self.env['ir.model.data']._xmlid_to_res_id('event.event_subscription')}),
|
||||
(0, 0, { # 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')})
|
||||
]
|
||||
})
|
||||
|
||||
# check event scheduler
|
||||
scheduler = self.env['event.mail'].search([('event_id', '=', test_event.id)])
|
||||
self.assertEqual(len(scheduler), 2, 'event: wrong scheduler creation')
|
||||
|
||||
event_prev_scheduler = self.env['event.mail'].search([('event_id', '=', test_event.id), ('interval_type', '=', 'before_event')])
|
||||
|
||||
with freeze_time(now), self.mock_mail_gateway():
|
||||
self.env['event.registration'].create({
|
||||
'create_date': now,
|
||||
'event_id': test_event.id,
|
||||
'name': 'Reg1',
|
||||
'email': 'reg1@example.com',
|
||||
})
|
||||
self.env['event.registration'].create({
|
||||
'create_date': now,
|
||||
'event_id': test_event.id,
|
||||
'name': 'Reg2',
|
||||
'email': 'reg2@example.com',
|
||||
})
|
||||
# check emails effectively sent
|
||||
self.assertEqual(len(self._new_mails), 2, 'event: should have 2 scheduled emails (1 / registration)')
|
||||
|
||||
# Archive the Event
|
||||
test_event.action_archive()
|
||||
|
||||
# execute cron to run schedulers
|
||||
now_start = event_date_begin + relativedelta(hours=-3)
|
||||
with freeze_time(now_start), self.mock_mail_gateway():
|
||||
event_cron_id.method_direct_trigger()
|
||||
|
||||
# check that scheduler is not executed
|
||||
self.assertFalse(event_prev_scheduler.mail_done, 'event: reminder scheduler should should have run')
|
||||
Loading…
Add table
Add a link
Reference in a new issue