From 3895baf28f1153201338cdfd0336e2907b6245b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 8 Jan 2020 13:25:40 +0000 Subject: [PATCH 1/6] [IMP] event: clean event.type (event category) demo and data In this commit we clean some event.type definitions. Indeed there are several of them without any real use, demo as well as data. It is more important to have fine-tuned demo and data than a lot of unused or generic demo. LINKS Task ID 2177281 (support tickets directly in event) Prepares Community PR odoo/odoo#43488 Closes Community PR odoo/odoo#44066 --- addons/event/data/event_data.xml | 2 +- addons/event/data/event_demo.xml | 35 +++++++++++--------------------- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/addons/event/data/event_data.xml b/addons/event/data/event_data.xml index 19b153f2621..03df5f2923a 100644 --- a/addons/event/data/event_data.xml +++ b/addons/event/data/event_data.xml @@ -14,13 +14,13 @@ + Online - Physical Event diff --git a/addons/event/data/event_demo.xml b/addons/event/data/event_demo.xml index c05a1db0771..a8db6afd5d0 100644 --- a/addons/event/data/event_demo.xml +++ b/addons/event/data/event_demo.xml @@ -7,27 +7,16 @@ - Seminar - - - Exhibition + - - - Conference - - - - Show - - - + Training + - - + Sport + @@ -39,7 +28,7 @@ limited 500 - + @@ -48,7 +37,7 @@ - + unlimited @@ -59,7 +48,7 @@ - + limited 200 @@ -71,7 +60,7 @@ - + unlimited @@ -82,7 +71,7 @@ - + @@ -92,7 +81,7 @@ - + @@ -101,7 +90,7 @@ - + From 8bc9d7710434df4732bb452bb9efac1fd091ee31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 17 Jan 2020 15:42:41 +0000 Subject: [PATCH 2/6] [IMP] (website_)event: clean fields definition and parameters In this commit we prepare future event model changes by reordering removing unnecessary parameters definitions, notably readonly set to False as it is the default value. Those parameters notably come from 412ff994f1120457c912aad487265e3de8a9f35a . Some reordering is also done in order to better understand future pre / post change model organization. LINKS Task ID 2177281 (support tickets directly in event) Prepares Community PR odoo/odoo#43488 Closes Community PR odoo/odoo#44066 --- addons/event/models/event_event.py | 47 +++++++--------------- addons/website_event/models/event_event.py | 20 +++++---- 2 files changed, 24 insertions(+), 43 deletions(-) diff --git a/addons/event/models/event_event.py b/addons/event/models/event_event.py index 5b0f9dc28b6..23a3de5de24 100644 --- a/addons/event/models/event_event.py +++ b/addons/event/models/event_event.py @@ -48,8 +48,7 @@ class EventType(models.Model): name = fields.Char('Event Category', required=True, translate=True) sequence = fields.Integer() # registration - has_seats_limitation = fields.Boolean( - 'Limited Seats', default=False) + has_seats_limitation = fields.Boolean('Limited Seats') default_registration_min = fields.Integer( 'Minimum Registrations', default=0, help="It will select this default minimum value when you choose this event") @@ -94,28 +93,22 @@ class EventEvent(models.Model): event_stages = self.env['event.stage'].search([]) return event_stages[0] if event_stages else False - name = fields.Char( - string='Event', translate=True, required=True, - readonly=False) + name = fields.Char(string='Event', translate=True, required=True) note = fields.Text(string='Note') + description = fields.Html(string='Description', translate=html_translate, sanitize_attributes=False) active = fields.Boolean(default=True) user_id = fields.Many2one( - 'res.users', string='Responsible', - default=lambda self: self.env.user, - tracking=True, - readonly=False) + 'res.users', string='Responsible', tracking=True, + default=lambda self: self.env.user) company_id = fields.Many2one( 'res.company', string='Company', change_default=True, default=lambda self: self.env.company, - required=False, readonly=False) + required=False) organizer_id = fields.Many2one( - 'res.partner', string='Organizer', - tracking=True, + 'res.partner', string='Organizer', tracking=True, default=lambda self: self.env.company.partner_id, domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]") - event_type_id = fields.Many2one( - 'event.type', string='Category', - readonly=False) + event_type_id = fields.Many2one('event.type', string='Category', ondelete='set null') color = fields.Integer('Kanban Color Index') event_mail_ids = fields.One2many('event.mail', 'event_id', string='Mail Schedule', copy=True) # Kanban fields @@ -154,36 +147,26 @@ class EventEvent(models.Model): string='Number of Expected Attendees', compute_sudo=True, readonly=True, compute='_compute_seats') # Registration fields - registration_ids = fields.One2many( - 'event.registration', 'event_id', string='Attendees', - readonly=False) + auto_confirm = fields.Boolean(string='Autoconfirm Registrations') + registration_ids = fields.One2many('event.registration', 'event_id', string='Attendees') event_registrations_open = fields.Boolean('Registration open', compute='_compute_event_registrations_open') # Date fields date_tz = fields.Selection( _tz_get, string='Timezone', required=True, default=lambda self: self.env.user.tz or 'UTC') - date_begin = fields.Datetime( - string='Start Date', required=True, - tracking=True) - date_end = fields.Datetime( - string='End Date', required=True, - tracking=True) + date_begin = fields.Datetime(string='Start Date', required=True, tracking=True) + date_end = fields.Datetime(string='End Date', required=True, tracking=True) date_begin_located = fields.Char(string='Start Date Located', compute='_compute_date_begin_tz') date_end_located = fields.Char(string='End Date Located', compute='_compute_date_end_tz') is_one_day = fields.Boolean(compute='_compute_field_is_one_day') - auto_confirm = fields.Boolean(string='Autoconfirm Registrations') + # Location and communication is_online = fields.Boolean('Online Event') address_id = fields.Many2one( - 'res.partner', string='Location', + 'res.partner', string='Location', tracking=True, default=lambda self: self.env.company.partner_id, - readonly=False, - domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]", - tracking=True) + domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]") country_id = fields.Many2one('res.country', 'Country', related='address_id.country_id', store=True, readonly=False) twitter_hashtag = fields.Char('Twitter Hashtag') - description = fields.Html( - string='Description', translate=html_translate, sanitize_attributes=False, - readonly=False) # badge fields badge_front = fields.Html(string='Badge Front') badge_back = fields.Html(string='Badge Back') diff --git a/addons/website_event/models/event_event.py b/addons/website_event/models/event_event.py index 0fa062e5162..611ba30263b 100644 --- a/addons/website_event/models/event_event.py +++ b/addons/website_event/models/event_event.py @@ -1,12 +1,11 @@ # -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. -import pytz import werkzeug import json from odoo import api, fields, models, _ from odoo.addons.http_routing.models.ir_http import slug -from odoo.exceptions import UserError GOOGLE_CALENDAR_URL = 'https://www.google.com/calendar/render?' @@ -15,27 +14,26 @@ class EventType(models.Model): _name = 'event.type' _inherit = ['event.type'] - website_menu = fields.Boolean( - 'Display a dedicated menu on Website') + website_menu = fields.Boolean('Display a dedicated menu on Website') class Event(models.Model): _name = 'event.event' _inherit = ['event.event', 'website.seo.metadata', 'website.published.multi.mixin'] - website_published = fields.Boolean(tracking=True) - + # description subtitle = fields.Char('Event Subtitle', translate=True) - + # registration is_participating = fields.Boolean("Is Participating", compute="_compute_is_participating") - + # website + website_published = fields.Boolean(tracking=True) cover_properties = fields.Text( 'Cover Properties', default='{"background-image": "none", "background-color": "oe_blue", "opacity": "0.4", "resize_class": "o_half_screen_height"}') - - website_menu = fields.Boolean('Dedicated Menu', + website_menu = fields.Boolean( + 'Dedicated Menu', copy=False, help="Creates menus Introduction, Location and Register on the page " - " of the event on the website.", copy=False) + " of the event on the website.") menu_id = fields.Many2one('website.menu', 'Event Menu', copy=False) def _compute_is_participating(self): From 3b1c2566ed7ae9a4e7c71533a5ecd8e60c15ad44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 20 Jan 2020 10:35:24 +0000 Subject: [PATCH 3/6] [FIX] event: copy event type mail scheduling only if activated Currently when changing category of an event, its category mail scheduling is copied onto the event even if the category does not enforce its use. We have to check the category use_mail_schedule field before computing the new event mail schedulers. In this commit we also lessen default schedulers from 3 to 2 in order to still help people using them without bloating too much event creation. LINKS Task ID 2177281 (support tickets directly in event) Prepares Community PR odoo/odoo#43488 Closes Community PR odoo/odoo#44066 --- addons/event/models/event_event.py | 8 +------- addons/event/tests/test_event_internals.py | 7 ++++--- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/addons/event/models/event_event.py b/addons/event/models/event_event.py index 23a3de5de24..0e8f6b3cf34 100644 --- a/addons/event/models/event_event.py +++ b/addons/event/models/event_event.py @@ -31,12 +31,6 @@ class EventType(models.Model): 'interval_unit': 'now', 'interval_type': 'after_sub', 'template_id': self.env.ref('event.event_subscription').id, - }), (0, 0, { - 'notification_type': 'mail', - 'interval_nbr': 1, - 'interval_unit': 'days', - 'interval_type': 'before_event', - 'template_id': self.env.ref('event.event_reminder').id, }), (0, 0, { 'notification_type': 'mail', 'interval_nbr': 10, @@ -270,7 +264,7 @@ class EventEvent(models.Model): self.is_online = self.event_type_id.is_online - if self.event_type_id.event_type_mail_ids: + if self.event_type_id.use_mail_schedule and self.event_type_id.event_type_mail_ids: self.event_mail_ids = [(5, 0, 0)] + [ (0, 0, { attribute_name: line[attribute_name] if not isinstance(line[attribute_name], models.BaseModel) else line[attribute_name].id diff --git a/addons/event/tests/test_event_internals.py b/addons/event/tests/test_event_internals.py index 2a79086808a..874422c1eac 100644 --- a/addons/event/tests/test_event_internals.py +++ b/addons/event/tests/test_event_internals.py @@ -99,14 +99,15 @@ class TestEventData(TestEventCommon): @users('user_eventmanager') @mute_logger('odoo.models.unlink') - def test_event_type_configuration(self): + def test_event_configuration_from_type(self): 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']) # TDE FIXME: currently crashing + # Event type does not use mail schedule but data is kept for compatibility and avoid recreating them + self.assertEqual(len(event_type.event_type_mail_ids), 2) event = self.env['event.event'].create({ 'name': 'Event Update Type', @@ -132,7 +133,7 @@ class TestEventData(TestEventCommon): self.assertTrue(event.auto_confirm) self.assertEqual(event.twitter_hashtag, event_type.default_hashtag) self.assertFalse(event.is_online) - # self.assertEqual(event.event_mail_ids, self.env['event.mail']) # TDE FIXME: currently crashing + self.assertEqual(event.event_mail_ids, self.env['event.mail']) event_type.write({ 'use_mail_schedule': True, From dd1551850c583c748e42e40b35a5bfbb05e2bb39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 22 Jan 2020 11:59:32 +0000 Subject: [PATCH 4/6] [FIX] event: fix seats_max field not editable Since 412ff994f1120457c912aad487265e3de8a9f35a seats_max field of event cannot be modified as it is always readonly. It should instead not be readonly as we consider people could change it whenever they want. LINKS Task ID 2177281 (support tickets directly in event) Prepares Community PR odoo/odoo#43488 Closes Community PR odoo/odoo#44066 --- addons/event/models/event_event.py | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/event/models/event_event.py b/addons/event/models/event_event.py index 0e8f6b3cf34..2a3a4597c9d 100644 --- a/addons/event/models/event_event.py +++ b/addons/event/models/event_event.py @@ -117,7 +117,6 @@ class EventEvent(models.Model): # Seats and computation seats_max = fields.Integer( string='Maximum Attendees Number', - readonly=True, help="For each event you can define a maximum registration of seats(number of attendees), above this numbers the registrations are not accepted.") seats_availability = fields.Selection( [('limited', 'Limited'), ('unlimited', 'Unlimited')], From 7caa532341edd533e3e024a4c5331aab1732472e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 20 Jan 2020 09:55:38 +0000 Subject: [PATCH 5/6] [IMP] event(_sale): add some tests before updating models As some event models (event.type and event.ticket notably) are about to be modified let us add some tests to avoid regressions. Security tests are also moved in their own file. Some internals tests defined in event_sale are also moved in their own file. That way we avoid bloating files with unrelated tests. Future commits will add tests for event and event.type models. LINKS Task ID 2177281 (support tickets directly in event) Prepares Community PR odoo/odoo#43488 Closes Community PR odoo/odoo#44066 --- addons/event/tests/__init__.py | 1 + addons/event/tests/common.py | 2 +- addons/event/tests/test_event_internals.py | 113 ++++-------------- addons/event/tests/test_event_security.py | 106 ++++++++++++++++ addons/event_sale/tests/__init__.py | 4 + addons/event_sale/tests/common.py | 19 +++ .../event_sale/tests/test_event_internals.py | 85 +++++++++++++ addons/event_sale/tests/test_event_sale.py | 40 ------- addons/event_sale/tests/test_event_sale_ui.py | 11 +- 9 files changed, 245 insertions(+), 136 deletions(-) create mode 100644 addons/event/tests/test_event_security.py create mode 100644 addons/event_sale/tests/common.py create mode 100644 addons/event_sale/tests/test_event_internals.py diff --git a/addons/event/tests/__init__.py b/addons/event/tests/__init__.py index 881edfc8974..72c2d9abfd9 100644 --- a/addons/event/tests/__init__.py +++ b/addons/event/tests/__init__.py @@ -4,3 +4,4 @@ from . import test_event_flow from . import test_event_internals from . import test_event_mail_schedule +from . import test_event_security diff --git a/addons/event/tests/common.py b/addons/event/tests/common.py index 56c14a78451..44aabb1d5d5 100644 --- a/addons/event/tests/common.py +++ b/addons/event/tests/common.py @@ -44,7 +44,7 @@ class TestEventCommon(common.SavepointCase): cls.customer = cls.env['res.partner'].create({ 'name': 'Constantin Customer', - 'email': 'constantin@example.com', + 'email': 'constantin@test.example.com', 'country_id': cls.env.ref('base.be').id, 'phone': '0485112233', }) diff --git a/addons/event/tests/test_event_internals.py b/addons/event/tests/test_event_internals.py index 874422c1eac..1f388eee3d8 100644 --- a/addons/event/tests/test_event_internals.py +++ b/addons/event/tests/test_event_internals.py @@ -2,11 +2,9 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from datetime import datetime, timedelta -from dateutil.relativedelta import relativedelta from unittest.mock import patch from odoo.addons.event.tests.common import TestEventCommon -from odoo.exceptions import AccessError from odoo.fields import Datetime as FieldsDatetime from odoo.tests.common import users from odoo.tools import mute_logger @@ -100,6 +98,10 @@ class TestEventData(TestEventCommon): @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) @@ -148,97 +150,26 @@ class TestEventData(TestEventCommon): self.assertEqual(event.event_mail_ids.template_id, self.env.ref('event.event_reminder')) -class TestEventSecurity(TestEventCommon): - - @users('user_employee') - @mute_logger('odoo.models.unlink', 'odoo.addons.base.models.ir_model') - def test_event_access_employee(self): - # employee can read events (sure ?) - event = self.event_0.with_user(self.env.user) - event.read(['name']) - # event.stage_id.read(['name', 'description']) - # event.event_type_id.read(['name', 'has_seats_limitation']) - - with self.assertRaises(AccessError): - self.env['event.event'].create({ - 'name': 'TestEvent', - 'date_begin': datetime.now() + relativedelta(days=-1), - 'date_end': datetime.now() + relativedelta(days=1), - 'seats_max': 10, - }) - - with self.assertRaises(AccessError): - event.write({ - 'name': 'TestEvent Modified', - }) - - with self.assertRaises(AccessError): - self.env['event.stage'].create({ - 'name': 'TestStage', - }) - - @users('user_eventuser') - @mute_logger('odoo.models.unlink', 'odoo.addons.base.models.ir_model') - def test_event_access_event_user(self): - event = self.event_0.with_user(self.env.user) - event.read(['name', 'user_id', 'kanban_state_label']) - - with self.assertRaises(AccessError): - self.env['event.event'].create({ - 'name': 'TestEvent', - 'date_begin': datetime.now() + relativedelta(days=-1), - 'date_end': datetime.now() + relativedelta(days=1), - 'seats_max': 10, - }) - - with self.assertRaises(AccessError): - event.write({ - 'name': 'TestEvent Modified', - }) - - # with self.assertRaises(AccessError): - # self.env['event.stage'].create({ - # 'name': 'TestStage', - # }) +class TestEventTypeData(TestEventCommon): @users('user_eventmanager') - @mute_logger('odoo.models.unlink', 'odoo.addons.base.models.ir_model') - def test_event_access_event_manager(self): - # EventManager can do about everything + 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': 'ManagerEventType', - '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')})] + 'name': 'Testing fields computation', + 'has_seats_limitation': True, + 'default_registration_min': 5, + 'default_registration_max': 30, }) - event = self.env['event.event'].create({ - 'name': 'ManagerEvent', - 'date_begin': datetime.now() + relativedelta(days=-1), - 'date_end': datetime.now() + relativedelta(days=1), - }) - event.update({'event_type_id': event_type.id}) - event._onchange_type() - event.flush() + event_type._onchange_has_seats_limitation() + self.assertTrue(event_type.has_seats_limitation) + self.assertEqual(event_type.default_registration_min, 5) + self.assertEqual(event_type.default_registration_max, 30) - registration = self.env['event.registration'].create({'event_id': event.id}) - registration.write({'name': 'Myself'}) - - stage = self.env.ref('event.event_stage_done') - stage.write({'name': 'ManagerEnded'}) - event.write({'stage_id': stage.id}) - - registration.unlink() - event.unlink() - stage.unlink() - event_type.unlink() - - # Settings access rights required to enable some features - self.user_eventmanager.write({'groups_id': [ - (3, self.env.ref('base.group_system').id), - (4, self.env.ref('base.group_erp_manager').id) - ]}) - with self.assertRaises(AccessError): - event_config = self.env['res.config.settings'].with_user(self.user_eventmanager).create({ - }) - event_config.execute() + # reset seats limitation + event_type.write({'has_seats_limitation': False}) + event_type._onchange_has_seats_limitation() + self.assertFalse(event_type.has_seats_limitation) + self.assertEqual(event_type.default_registration_min, 0) + self.assertEqual(event_type.default_registration_max, 0) diff --git a/addons/event/tests/test_event_security.py b/addons/event/tests/test_event_security.py new file mode 100644 index 00000000000..ef056c438b5 --- /dev/null +++ b/addons/event/tests/test_event_security.py @@ -0,0 +1,106 @@ +# -*- 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 odoo.addons.event.tests.common import TestEventCommon +from odoo.exceptions import AccessError +from odoo.tests.common import users +from odoo.tools import mute_logger + + +class TestEventSecurity(TestEventCommon): + + @users('user_employee') + @mute_logger('odoo.models.unlink', 'odoo.addons.base.models.ir_model') + def test_event_access_employee(self): + # employee can read events (sure ?) + event = self.event_0.with_user(self.env.user) + event.read(['name']) + # event.stage_id.read(['name', 'description']) + # event.event_type_id.read(['name', 'has_seats_limitation']) + + with self.assertRaises(AccessError): + self.env['event.event'].create({ + 'name': 'TestEvent', + 'date_begin': datetime.now() + relativedelta(days=-1), + 'date_end': datetime.now() + relativedelta(days=1), + 'seats_max': 10, + }) + + with self.assertRaises(AccessError): + event.write({ + 'name': 'TestEvent Modified', + }) + + with self.assertRaises(AccessError): + self.env['event.stage'].create({ + 'name': 'TestStage', + }) + + @users('user_eventuser') + @mute_logger('odoo.models.unlink', 'odoo.addons.base.models.ir_model') + def test_event_access_event_user(self): + event = self.event_0.with_user(self.env.user) + event.read(['name', 'user_id', 'kanban_state_label']) + + with self.assertRaises(AccessError): + self.env['event.event'].create({ + 'name': 'TestEvent', + 'date_begin': datetime.now() + relativedelta(days=-1), + 'date_end': datetime.now() + relativedelta(days=1), + 'seats_max': 10, + }) + + with self.assertRaises(AccessError): + event.write({ + 'name': 'TestEvent Modified', + }) + + # with self.assertRaises(AccessError): + # self.env['event.stage'].create({ + # 'name': 'TestStage', + # }) + + @users('user_eventmanager') + @mute_logger('odoo.models.unlink', 'odoo.addons.base.models.ir_model') + def test_event_access_event_manager(self): + # EventManager can do about everything + event_type = self.env['event.type'].create({ + 'name': 'ManagerEventType', + '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 = self.env['event.event'].create({ + 'name': 'ManagerEvent', + 'date_begin': datetime.now() + relativedelta(days=-1), + 'date_end': datetime.now() + relativedelta(days=1), + }) + event.update({'event_type_id': event_type.id}) + event._onchange_type() + event.flush() + + registration = self.env['event.registration'].create({'event_id': event.id}) + registration.write({'name': 'Myself'}) + + stage = self.env.ref('event.event_stage_done') + stage.write({'name': 'ManagerEnded'}) + event.write({'stage_id': stage.id}) + + registration.unlink() + event.unlink() + stage.unlink() + event_type.unlink() + + # Settings access rights required to enable some features + self.user_eventmanager.write({'groups_id': [ + (3, self.env.ref('base.group_system').id), + (4, self.env.ref('base.group_erp_manager').id) + ]}) + with self.assertRaises(AccessError): + event_config = self.env['res.config.settings'].with_user(self.user_eventmanager).create({ + }) + event_config.execute() diff --git a/addons/event_sale/tests/__init__.py b/addons/event_sale/tests/__init__.py index c023d41b5dd..47f238b93ad 100644 --- a/addons/event_sale/tests/__init__.py +++ b/addons/event_sale/tests/__init__.py @@ -1,2 +1,6 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import test_event_internals from . import test_event_sale from . import test_event_sale_ui diff --git a/addons/event_sale/tests/common.py b/addons/event_sale/tests/common.py new file mode 100644 index 00000000000..30f437fd760 --- /dev/null +++ b/addons/event_sale/tests/common.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.addons.event.tests.common import TestEventCommon + + +class TestEventSaleCommon(TestEventCommon): + + @classmethod + def setUpClass(cls): + super(TestEventSaleCommon, cls).setUpClass() + + cls.event_product = cls.env['product.product'].create({ + 'name': 'Test Registration Product', + 'list_price': 10, + 'event_ok': True, + 'standard_price': 30.0, + 'type': 'service', + }) diff --git a/addons/event_sale/tests/test_event_internals.py b/addons/event_sale/tests/test_event_internals.py new file mode 100644 index 00000000000..9f8539ec6bd --- /dev/null +++ b/addons/event_sale/tests/test_event_internals.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from datetime import date, datetime, timedelta + +from odoo.addons.event_sale.tests.common import TestEventSaleCommon +from odoo.fields import Datetime as FieldsDatetime +from odoo.tests.common import users + + +class EventSaleTest(TestEventSaleCommon): + + @users('user_eventmanager') + def test_event_configuration_from_type(self): + """ In addition to event test, also test tickets configuration coming + from event_sale capabilities. """ + event_type = self.event_type_complex.with_user(self.env.user) + event_type.write({ + 'use_mail_schedule': False, + 'use_ticketing': False, + }) + # Event type does not use tickets but data is kept for compatibility and avoid recreating them + self.assertEqual(len(event_type.event_ticket_ids), 1) + self.assertEqual(event_type.event_ticket_ids.name, 'Registration') + + 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)), + }) + event._onchange_type() + self.assertEqual(event.event_ticket_ids, self.env['event.event.ticket']) + + event_type.write({ + 'use_ticketing': True, + 'event_ticket_ids': [(5, 0), (0, 0, { + 'name': 'First Ticket', + 'product_id': self.event_product.id, + })] + }) + event_type.event_ticket_ids._onchange_product_id() + event._onchange_type() + self.assertEqual(event.event_ticket_ids.name, 'Registration for %s' % event.name) + self.assertEqual(event.event_ticket_ids.product_id, self.event_product) + self.assertEqual(event.event_ticket_ids.price, self.event_product.list_price) + + def test_event_registrable(self): + """Test if `_compute_event_registrations_open` works properly.""" + test_event = self.env['event.event'].create({ + 'name': 'TestEvent', + 'date_begin': datetime.now() - timedelta(days=5), + 'date_end': datetime.now() + timedelta(days=5), + }) + test_event_ticket = self.env['event.event.ticket'].create({ + 'name': 'TestTicket', + 'event_id': test_event.id, + 'product_id': self.env['product.product'].search([], limit=1).id, + }) + + self.assertEqual(test_event.event_registrations_open, True) + + test_event.write({ + 'date_begin': datetime.now() - timedelta(days=5), + 'date_end': datetime.now() - timedelta(days=1), + }) + + test_event.date_end = datetime.now() - timedelta(days=1) + self.assertEqual(test_event.event_registrations_open, False) + + test_event.write({ + 'date_begin': datetime.now() - timedelta(days=1), + 'date_end': datetime.now() + timedelta(days=5), + }) + + test_event.write({'event_ticket_ids': [(5, 0)]}) + self.assertEqual(test_event.event_registrations_open, False, 'cannot register if no tickets') + + test_event_ticket = self.env['event.event.ticket'].create({ + 'name': 'TestTicket', + 'event_id': test_event.id, + 'product_id': self.env['product.product'].search([], limit=1).id, + }) + test_event_ticket.product_id.active = False + self.assertEqual(test_event.event_registrations_open, False, 'cannot register if product linked to the tickets are all archived') diff --git a/addons/event_sale/tests/test_event_sale.py b/addons/event_sale/tests/test_event_sale.py index 720b3ad7fbf..fb121228bd6 100644 --- a/addons/event_sale/tests/test_event_sale.py +++ b/addons/event_sale/tests/test_event_sale.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -import datetime from odoo.tests import common @@ -68,42 +67,3 @@ class EventSaleTest(common.TransactionCase): # I check if a registration is created registrations = self.EventRegistration.search([('origin', '=', self.sale_order.name)]) self.assertTrue(registrations, "The registration is not created.") - - def test_event_is_registrable(self): - """Test if `_compute_event_registrations_open` works properly.""" - test_event = self.env['event.event'].create({ - 'name': 'TestEvent', - 'date_begin': datetime.datetime.now() - datetime.timedelta(days=5), - 'date_end': datetime.datetime.now() + datetime.timedelta(days=5), - }) - test_event_ticket = self.env['event.event.ticket'].create({ - 'name': 'TestTicket', - 'event_id': test_event.id, - 'product_id': self.env['product.product'].search([], limit=1).id, - }) - - self.assertEqual(test_event.event_registrations_open, True) - - test_event.write({ - 'date_begin': datetime.datetime.now() - datetime.timedelta(days=5), - 'date_end': datetime.datetime.now() - datetime.timedelta(days=1), - }) - - test_event.date_end = datetime.datetime.now() - datetime.timedelta(days=1) - self.assertEqual(test_event.event_registrations_open, False) - - test_event.write({ - 'date_begin': datetime.datetime.now() - datetime.timedelta(days=1), - 'date_end': datetime.datetime.now() + datetime.timedelta(days=5), - }) - - test_event.write({'event_ticket_ids': [(6, 0, [])]}) - self.assertEqual(test_event.event_registrations_open, False, 'cannot register if no tickets') - - test_event_ticket = self.env['event.event.ticket'].create({ - 'name': 'TestTicket', - 'event_id': test_event.id, - 'product_id': self.env['product.product'].search([], limit=1).id, - }) - test_event_ticket.product_id.active = False - self.assertEqual(test_event.event_registrations_open, False, 'cannot register if product linked to the tickets are all archived') diff --git a/addons/event_sale/tests/test_event_sale_ui.py b/addons/event_sale/tests/test_event_sale_ui.py index 79932be0c79..24e68c5dbb8 100644 --- a/addons/event_sale/tests/test_event_sale_ui.py +++ b/addons/event_sale/tests/test_event_sale_ui.py @@ -1,13 +1,16 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. -import odoo.tests from datetime import timedelta + from odoo.fields import Datetime +from odoo.tests import HttpCase, tagged -@odoo.tests.tagged('post_install', '-at_install') -class TestUi(odoo.tests.HttpCase): - def test_01_event_configurator(self): +@tagged('post_install', '-at_install') +class TestUi(HttpCase): + + def test_event_configurator(self): + event = self.env['event.event'].create({ 'name': 'Design Fair Los Angeles', 'date_begin': Datetime.now() + timedelta(days=1), From 553e0cd51eb0f6b3204b05777328d0c71a353b10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 20 Jan 2020 14:49:13 +0000 Subject: [PATCH 6/6] [MOV][IMP] (website_)event_sale: prepare views for ticket model update PURPOSE Integration between event and eCommerce is required only when users handle the entire selling process online. However users may require ticketing support while managing payments outside of Odoo. Purpose of this commit is to prepare support of tickets directly in event application without need of sales. SPECIFICATIONS In this commit we prepare the ticket model split and update by * define views for ticket model. Currently views are directly embedded in o2m of event.type and event.event, leading to complex xpath to modify them. They are now real views; * split templates in website_event_sale, to have templates related to website_event and website_sale separated, leading to more simple diff comprehension; LINKS Task ID 2177281 (support tickets directly in event) Prepares Community PR odoo/odoo#43488 Closes Community PR odoo/odoo#44066 --- addons/event_sale/__manifest__.py | 2 + .../views/event_registration_views.xml | 70 +++++ .../event_sale/views/event_ticket_views.xml | 106 ++++++++ addons/event_sale/views/event_views.xml | 251 ++++-------------- addons/website_event/__manifest__.py | 1 + addons/website_event/views/assets.xml | 21 ++ .../website_event/views/event_templates.xml | 17 -- addons/website_event_sale/__manifest__.py | 6 +- addons/website_event_sale/views/assets.xml | 10 + ...{event_views.xml => event_event_views.xml} | 1 + ...plates.xml => website_event_templates.xml} | 44 --- .../views/website_sale_templates.xml | 43 +++ 12 files changed, 312 insertions(+), 260 deletions(-) create mode 100644 addons/event_sale/views/event_registration_views.xml create mode 100644 addons/event_sale/views/event_ticket_views.xml create mode 100644 addons/website_event/views/assets.xml create mode 100644 addons/website_event_sale/views/assets.xml rename addons/website_event_sale/views/{event_views.xml => event_event_views.xml} (92%) rename addons/website_event_sale/views/{event_templates.xml => website_event_templates.xml} (80%) create mode 100644 addons/website_event_sale/views/website_sale_templates.xml diff --git a/addons/event_sale/__manifest__.py b/addons/event_sale/__manifest__.py index b46b9f091f4..16890176e67 100644 --- a/addons/event_sale/__manifest__.py +++ b/addons/event_sale/__manifest__.py @@ -21,6 +21,8 @@ this event. 'depends': ['event', 'sale_management'], 'data': [ 'views/assets.xml', + 'views/event_ticket_views.xml', + 'views/event_registration_views.xml', 'views/event_views.xml', 'views/product_views.xml', 'views/sale_order_views.xml', diff --git a/addons/event_sale/views/event_registration_views.xml b/addons/event_sale/views/event_registration_views.xml new file mode 100644 index 00000000000..79394c37acf --- /dev/null +++ b/addons/event_sale/views/event_registration_views.xml @@ -0,0 +1,70 @@ + + + + + event.registration.search.inherit + event.registration + + + + + + + + + + event.registration.tree.inherit + event.registration + + + + + + + + + + + event.registration.kanban.inherit + event.registration + + + +
+ +
+
+
+ + + event.registration.form.inherit + event.registration + + + + + + + + + + + + + + + + + + + + +
diff --git a/addons/event_sale/views/event_ticket_views.xml b/addons/event_sale/views/event_ticket_views.xml new file mode 100644 index 00000000000..80e96a5cc5d --- /dev/null +++ b/addons/event_sale/views/event_ticket_views.xml @@ -0,0 +1,106 @@ + + + + + event.event.ticket.view.tree.from_event + event.event.ticket + + + + + + + + + + + + + + + + + event.event.ticket.view.form.from.event + event.event.ticket + + +
+ + + + + + + + + + + + +
+
+
+ + + event.event.ticket.view.kanban.from.event + event.event.ticket + + + + + + + + + + + +
+
+
+ +
+
+
+
+
+ reserved + unconfirmed +
+
+ + + + + + + + event.event.ticket.view.form + event.event.ticket + +
+
+
+ + + + + + + + + + + + + + + + + + +
+
+
+ diff --git a/addons/event_sale/views/event_views.xml b/addons/event_sale/views/event_views.xml index 1d685751a9e..e18cbb1ae3b 100644 --- a/addons/event_sale/views/event_views.xml +++ b/addons/event_sale/views/event_views.xml @@ -1,206 +1,63 @@ - - event.registration.search.inherit - event.registration - - - - - - - - - - event.registration.tree.inherit - event.registration - - - - - - - - - - - event.registration.kanban.inherit - event.registration - - - -
- -
-
-
- - - event.registration.form.inherit - event.registration - - - - - - - - - - - - - - - - - - - - - - event.type.view.form.inherit.sale - event.type - - -
-
-
- -
-
-