Files
odoo_source/addons/event/tests/test_event_internals.py
T
Thibault Delavallée d2840a0519 [FIX] event: include timezoned event date_end in registration open computation
Purpose of this commit is to try to lessen random conditions being concatenated
in templates by correctly computing event_registrations_open field that is
now correctly based on

  * event.date_end -> if event is done, registrations are not open anymore;
  * event.start_sale_date -> lowest start date of tickets (if any; start_sale_date
    is False if no ticket are defined, see _compute_start_sale_date);
  * any ticket is available for sale (seats available) if any;
  * seats are unlimited or seats are available;

Some better timezone computation is included even if it could be done better.

Task ID 2228189
Community PR odoo/odoo#48652

X-original-commit: a11af9074499465b6dd8ad1400e60c7af96e21c7
2020-04-03 11:07:55 +00:00

318 lines
13 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import date, datetime, timedelta
from unittest.mock import patch
from odoo.addons.event.tests.common import TestEventCommon
from odoo import exceptions
from odoo.fields import Datetime as FieldsDatetime, Date as FieldsDate
from odoo.tests.common import users
from odoo.tools import mute_logger
class TestEventData(TestEventCommon):
@classmethod
def setUpClass(cls):
super(TestEventData, cls).setUpClass()
cls.patcher = patch('odoo.addons.event.models.event_event.fields.Datetime', wraps=FieldsDatetime)
cls.mock_datetime = cls.patcher.start()
cls.mock_datetime.now.return_value = datetime(2020, 1, 31, 10, 0, 0)
cls.addClassCleanup(cls.patcher.stop)
cls.event_0.write({
'date_begin': datetime(2020, 2, 1, 8, 30, 0),
'date_end': datetime(2020, 2, 4, 18, 45, 0),
})
@users('user_eventmanager')
def test_event_date_computation(self):
event = self.event_0.with_user(self.env.user)
event.write({
'registration_ids': [(0, 0, {'partner_id': self.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, 11:00:00 AM')
# 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': 'Mexico/General'
})
self.assertTrue(event.is_one_day)
@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': 'Mexico/General'
})
self.assertTrue(event.is_one_day)
self.assertFalse(event.is_ongoing)
@users('user_eventmanager')
def test_event_fields(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)
for x in range(5):
reg = self.env['event.registration'].create({
'event_id': event.id,
'name': 'reg_open',
})
self.assertEqual(reg.state, 'open')
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)
@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.
Some one2many notably are duplicated from type configuration and some
advanced testing is required, notably mail schedulers. """
self.assertEqual(self.env.user.tz, 'Europe/Brussels')
event_type = self.event_type_complex.with_user(self.env.user)
event_type.write({
'use_mail_schedule': False,
})
self.assertEqual(event_type.event_type_mail_ids, self.env['event.type.mail'])
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)
self.assertEqual(event.event_mail_ids, self.env['event.mail'])
event_type.write({
'use_mail_schedule': True,
'event_type_mail_ids': [(5, 0), (0, 0, {
'interval_nbr': 1, 'interval_unit': 'days', 'interval_type': 'before_event',
'template_id': self.env['ir.model.data'].xmlid_to_res_id('event.event_reminder')})]
})
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)
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_id, self.env.ref('event.event_reminder'))
@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_date': datetime(2020, 1, 30, 15, 0, 0)})
self.assertTrue(ticket.is_expired)
self.assertFalse(event.event_registrations_open)
@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)
class TestEventTicketData(TestEventCommon):
def setUp(self):
super(TestEventTicketData, self).setUp()
self.ticket_date_patcher = patch('odoo.addons.event.models.event_ticket.fields.Date', wraps=FieldsDate)
self.ticket_date_patcher_mock = self.ticket_date_patcher.start()
self.ticket_date_patcher_mock.context_today.return_value = date(2020, 1, 31)
def tearDown(self):
super(TestEventTicketData, self).tearDown()
self.ticket_date_patcher.stop()
@users('user_eventmanager')
def test_event_ticket_fields(self):
""" Test event ticket fields synchronization """
event = self.event_0.with_user(self.env.user)
event.write({
'event_ticket_ids': [
(5, 0),
(0, 0, {
'name': 'First Ticket',
'seats_max': 30,
}), (0, 0, { # limited in time, available (01/10 (start) < 01/31 (today) < 02/10 (end))
'name': 'Second Ticket',
'start_sale_date': date(2020, 1, 10),
'end_sale_date': date(2020, 2, 10),
})
],
})
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_date': date(2020, 1, 20)})
self.assertFalse(second_ticket.sale_available)
self.assertTrue(second_ticket.is_expired)
# sale has not started
second_ticket.write({
'start_sale_date': date(2020, 2, 10),
'end_sale_date': date(2020, 2, 20),
})
self.assertFalse(second_ticket.sale_available)
self.assertFalse(second_ticket.is_expired)
# incoherent dates are invalid
with self.assertRaises(exceptions.UserError):
second_ticket.write({'end_sale_date': date(2020, 1, 20)})
class TestEventTypeData(TestEventCommon):
@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,
'use_ticket': True,
})
self.assertTrue(event_type.has_seats_limitation)
self.assertEqual(event_type.seats_max, 30)
self.assertEqual(event_type.event_type_ticket_ids.mapped('name'), ['Registration'])
# reset seats limitation
event_type.write({'has_seats_limitation': False})
self.assertFalse(event_type.has_seats_limitation)
self.assertEqual(event_type.seats_max, 0)
# reset tickets
event_type.write({'use_ticket': False})
self.assertEqual(event_type.event_type_ticket_ids, self.env['event.type.ticket'])