# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. from datetime import datetime, timedelta, time from odoo.addons.base.tests.common import HttpCaseWithUserDemo, HttpCaseWithUserPortal from odoo.addons.base.tests.test_ir_cron import CronMixinCase from odoo.addons.event.tests.common import EventCase from odoo.addons.event_crm.tests.common import EventCrmCase from odoo.addons.mail.tests.common import mail_new_test_user, MailCommon from odoo.addons.sales_team.tests.common import TestSalesCommon from odoo.addons.sms.tests.common import SMSCase from odoo.addons.website.tests.test_website_visitor import MockVisitor class TestEventFullCommon(EventCrmCase, TestSalesCommon, MockVisitor): @classmethod def setUpClass(cls): super(TestEventFullCommon, cls).setUpClass() # Context data: dates # ------------------------------------------------------------ # Mock dates to have reproducible computed fields based on time cls.reference_now = datetime(2021, 12, 1, 10, 0, 0) cls.reference_today = datetime(2021, 12, 1) # Users and contacts # ------------------------------------------------------------ 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, 'email': 'info@yourcompany.com', }) cls.event_user = mail_new_test_user( cls.env, company_id=cls.company_admin.id, company_ids=[(4, cls.company_admin.id)], country_id=cls.env.ref('base.be').id, groups='base.group_user,base.group_partner_manager,event.group_event_user', email='e.e@example.com', login='event_user', name='Ernest Employee', notification_type='inbox', signature='--\nErnest', ) cls.customer = cls.env['res.partner'].create({ 'country_id': cls.env.ref('base.be').id, 'email': 'customer.test@example.com', 'name': 'Test Customer', 'mobile': '0456123456', 'phone': '0456123456', }) # make a SO for a customer, selling some tickets cls.customer_so = cls.env['sale.order'].with_user(cls.user_sales_salesman).create({ 'partner_id': cls.event_customer.id, }) # Side records for event main records # ------------------------------------------------------------ cls.ticket_product = cls.env['product.product'].create({ 'description_sale': 'Ticket Product Description', 'type': 'service', 'service_tracking': 'event', 'list_price': 10, 'name': 'Test Registration Product', 'standard_price': 30.0, }) cls.booth_product = cls.env['product.product'].create({ 'description_sale': 'Booth Product Description', 'type': 'service', 'service_tracking': 'event_booth', 'list_price': 20, 'name': 'Test Booth Product', 'standard_price': 60.0, }) cls.tag_categories = cls.env['event.tag.category'].create([ {'is_published': True, 'name': 'Published Category'}, {'is_published': False, 'name': 'Unpublished Category'}, ]) cls.tags = cls.env['event.tag'].create([ {'category_id': cls.tag_categories[0].id, 'name': 'PubTag1'}, {'category_id': cls.tag_categories[0].id, 'color': 0, 'name': 'PubTag2'}, {'category_id': cls.tag_categories[1].id, 'name': 'UnpubTag1'}, ]) cls.event_booth_categories = cls.env['event.booth.category'].create([ {'description': '

Standard

', 'name': 'Standard', 'product_id': cls.booth_product.id, }, {'description': '

Premium

', 'name': 'Premium', 'product_id': cls.booth_product.id, 'price': 90, } ]) cls.sponsor_types = cls.env['event.sponsor.type'].create([ {'name': 'GigaTop', 'sequence': 1, } ]) cls.sponsor_partners = cls.env['res.partner'].create([ {'country_id': cls.env.ref('base.be').id, 'email': 'event.sponsor@example.com', 'name': 'EventSponsor', 'phone': '04856112233', } ]) # Event type # ------------------------------------------------------------ test_registration_report = cls.env.ref('test_event_full.event_registration_report_test') subscription_template = cls.env.ref('event.event_subscription') subscription_template.write({'report_template_ids': [(6, 0, test_registration_report.ids)]}) cls.test_event_type = cls.env['event.type'].create({ 'default_timezone': 'Europe/Paris', 'event_type_booth_ids': [ (0, 0, {'booth_category_id': cls.event_booth_categories[0].id, 'name': 'Standard Booth', } ), (0, 0, {'booth_category_id': cls.event_booth_categories[0].id, 'name': 'Standard Booth 2', } ), (0, 0, {'booth_category_id': cls.event_booth_categories[1].id, 'name': 'Premium Booth', } ), (0, 0, {'booth_category_id': cls.event_booth_categories[1].id, 'name': 'Premium Booth 2', } ), ], 'event_type_mail_ids': [ (0, 0, {'interval_unit': 'now', # right at subscription 'interval_type': 'after_sub', 'template_ref': 'mail.template,%i' % subscription_template.id, } ), (0, 0, {'interval_nbr': 1, # 1 days before event 'interval_unit': 'days', 'interval_type': 'before_event', 'template_ref': 'mail.template,%i' % cls.env['ir.model.data']._xmlid_to_res_id('event.event_reminder'), } ), (0, 0, {'interval_nbr': 1, # 1 days after event 'interval_unit': 'days', 'interval_type': 'after_event', 'template_ref': 'sms.template,%i' % cls.env['ir.model.data']._xmlid_to_res_id('event_sms.sms_template_data_event_reminder'), } ), ], 'event_type_ticket_ids': [ (0, 0, {'description': 'Ticket1 Description', 'name': 'Ticket1', 'product_id': cls.ticket_product.id, 'seats_max': 10, } ), (0, 0, {'description': 'Ticket2 Description', 'name': 'Ticket2', 'product_id': cls.ticket_product.id, 'price': 45, } ) ], 'has_seats_limitation': True, 'name': 'Test Type', 'note': '

Template note

', 'question_ids': [ (0, 0, {'answer_ids': [(0, 0, {'name': 'Q1-Answer1'}), (0, 0, {'name': 'Q1-Answer2'}), ], 'question_type': 'simple_choice', 'once_per_order': False, 'title': 'Question1', } ), (0, 0, {'answer_ids': [(0, 0, {'name': 'Q2-Answer1'}), (0, 0, {'name': 'Q2-Answer2'}), ], 'question_type': 'simple_choice', 'once_per_order': False, 'title': 'Question2', } ), (0, 0, {'question_type': 'text_box', 'once_per_order': True, 'title': 'Question3', } ), ], 'seats_max': 30, 'tag_ids': [(4, tag.id) for tag in cls.tags], 'ticket_instructions': '

Ticket Instructions

', 'website_menu': True, }) # Stages cls.stage_def = cls.env['event.stage'].create({ 'name': 'First Stage', 'sequence': 0, }) # Event data # ------------------------------------------------------------ cls.event_base_vals = { 'name': 'Test Event', 'date_begin': cls.reference_now + timedelta(days=1), 'date_end': cls.reference_now + timedelta(days=5), 'is_published': True, } with cls.mock_datetime_and_now(cls, cls.reference_now): cls.test_event = cls.env['event.event'].create({ 'name': 'Test Event', 'date_begin': datetime.now() + timedelta(days=1), 'date_end': datetime.now() + timedelta(days=5), 'date_tz': 'Europe/Brussels', 'event_type_id': cls.test_event_type.id, 'is_published': True, }) # update post-synchronize data ticket_1 = cls.test_event.event_ticket_ids.filtered(lambda t: t.name == 'Ticket1') ticket_2 = cls.test_event.event_ticket_ids.filtered(lambda t: t.name == 'Ticket2') ticket_1.start_sale_datetime = cls.reference_now + timedelta(hours=1) ticket_2.start_sale_datetime = cls.reference_now + timedelta(hours=2) # Website data # ------------------------------------------------------------ cls.website = cls.env['website'].search([ ('company_id', '=', cls.company_admin.id) ], limit=1) cls.customer_data = [ {'email': f'customer.email.{idx:02d}@test.example.com', 'name': f'My Customer {idx:02d}', 'partner_id': False, 'phone': f'04560000{idx:02d}', } for idx in range(0, 10) ] cls.website_customer_data = [ {'email': f'website.email.{idx:02d}@test.example.com', 'name': f'My Customer {idx:02d}', 'partner_id': cls.env.ref('base.public_partner').id, 'phone': f'04560000{idx:02d}', 'registration_answer_ids': [ (0, 0, { 'question_id': cls.test_event.question_ids[0].id, 'value_answer_id': cls.test_event.question_ids[0].answer_ids[(idx % 2)].id, }), (0, 0, { 'question_id': cls.test_event.question_ids[1].id, 'value_answer_id': cls.test_event.question_ids[1].answer_ids[(idx % 2)].id, }), (0, 0, { 'question_id': cls.test_event.question_ids[2].id, 'value_text_box': f'CustomerAnswer{idx}', }) ], } for idx in range(0, 10) ] cls.partners = cls.env['res.partner'].create([ {'email': f'partner.email.{idx:02d}@test.example.com', 'name': f'PartnerCustomer {idx:02d}', 'mobile': f'04569999{idx:02d}', 'phone': f'04560000{idx:02d}', } for idx in range(0, 10) ]) def assertLeadConvertion(self, rule, registrations, partner=None, **expected): super(TestEventFullCommon, self).assertLeadConvertion(rule, registrations, partner=partner, **expected) lead = self.env['crm.lead'].sudo().search([ ('registration_ids', 'in', registrations.ids), ('event_lead_rule_id', '=', rule.id) ]) for registration in registrations: if not registration.registration_answer_ids: continue for answer in registration.registration_answer_ids: self.assertIn(answer.question_id.title, lead.description) if answer.question_type == 'simple_choice': self.assertIn(answer.value_answer_id.name, lead.description) else: self.assertIn(answer.value_text_box, lead.description) # better: check multi line class TestEventMailCommon(EventCase, SMSCase, MailCommon, CronMixinCase): @classmethod def setUpClass(cls): super().setUpClass() cls.event_cron_id = cls.env.ref('event.event_mail_scheduler') # deactivate other schedulers to avoid messing with crons cls.env['event.mail'].search([]).unlink() # consider asynchronous sending as default sending cls.env["ir.config_parameter"].set_param("event.event_mail_async", False) cls.env.company.write({ 'email': 'info@yourcompany.example.com', 'name': 'YourCompany', }) # prepare SMS templates cls.sms_template_sub = cls.env['sms.template'].create({ 'name': 'Test SMS Subscription', 'model_id': cls.env.ref('event.model_event_registration').id, 'body': '{{ object.event_id.organizer_id.name }} registration confirmation.', 'lang': '{{ object.partner_id.lang }}' }) cls.sms_template_rem = cls.env['sms.template'].create({ 'name': 'Test SMS Reminder', 'model_id': cls.env.ref('event.model_event_registration').id, 'body': '{{ object.event_id.organizer_id.name }} reminder', 'lang': '{{ object.partner_id.lang }}' }) # 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 cls.reference_now = datetime(2021, 3, 20, 14, 30, 15, 123456) cls.event_date_begin = datetime(2021, 3, 25, 8, 0, 0) cls.event_date_end = datetime(2021, 3, 28, 18, 0, 0) cls._setup_test_reports() with cls.mock_datetime_and_now(cls, cls.reference_now): cls.test_event = cls.env['event.event'].create({ 'name': 'TestEventMail', 'user_id': cls.user_eventmanager.id, 'date_begin': cls.event_date_begin, 'date_end': cls.event_date_end, 'event_mail_ids': [ (0, 0, { # right at subscription: mail 'interval_unit': 'now', 'interval_type': 'after_sub', 'notification_type': 'mail', 'template_ref': f'mail.template,{cls.template_subscription.id}', }), (0, 0, { # right at subscription: sms 'interval_unit': 'now', 'interval_type': 'after_sub', 'notification_type': 'sms', 'template_ref': f'sms.template,{cls.sms_template_sub.id}', }), (0, 0, { # 3 days before event: mail 'interval_nbr': 3, 'interval_unit': 'days', 'interval_type': 'before_event', 'notification_type': 'mail', 'template_ref': f'mail.template,{cls.template_reminder.id}', }), (0, 0, { # 3 days before event: SMS 'interval_nbr': 3, 'interval_unit': 'days', 'interval_type': 'before_event', 'notification_type': 'sms', 'template_ref': f'sms.template,{cls.sms_template_rem.id}', }), (0, 0, { # 1h after event: mail 'interval_nbr': 1, 'interval_unit': 'hours', 'interval_type': 'after_event', 'notification_type': 'mail', 'template_ref': f'mail.template,{cls.template_reminder.id}', }), (0, 0, { # 1h after event: SMS 'interval_nbr': 1, 'interval_unit': 'hours', 'interval_type': 'after_event', 'notification_type': 'sms', 'template_ref': f'sms.template,{cls.sms_template_rem.id}', }), ], }) class TestWEventCommon(HttpCaseWithUserDemo, HttpCaseWithUserPortal, MockVisitor): def setUp(self): super(TestWEventCommon, self).setUp() # Context data: dates # ------------------------------------------------------------ # Mock dates to have reproducible computed fields based on time self.reference_now = datetime(2021, 12, 1, 10, 0, 0) self.reference_today = datetime(2021, 12, 1) self.event_product = self.env['product.product'].create({ 'name': 'Test Event Registration', 'default_code': 'EVENT_REG', 'description_sale': 'Mighty Description', 'list_price': 10, 'standard_price': 30.0, 'type': 'service', 'service_tracking': 'event', }) self.event_tag_category_1 = self.env['event.tag.category'].create({ 'name': 'Type', 'sequence': 2, }) self.event_tag_category_1_tag_1 = self.env['event.tag'].create({ 'name': 'Online', 'sequence': 10, 'category_id': self.event_tag_category_1.id, 'color': 8, }) self.env['event.event'].search( [('name', 'like', 'Online Reveal')] ).write( {'name': 'Do not click on me'} ) self.event = self.env['event.event'].create({ 'name': 'Online Reveal TestEvent', 'stage_id': self.env.ref('event.event_stage_booked').id, 'address_id': False, 'user_id': self.user_demo.id, 'tag_ids': [(4, self.event_tag_category_1_tag_1.id)], # event if 8-18 in Europe/Brussels (DST) (first day: begins at 7, last day: ends at 17) 'date_tz': 'Europe/Brussels', 'date_begin': datetime.combine(self.reference_now, time(5, 0)) - timedelta(days=1), 'date_end': datetime.combine(self.reference_now, time(15, 0)) + timedelta(days=1), # ticket informations 'event_ticket_ids': [ (0, 0, { 'name': 'Standard', 'product_id': self.event_product.id, 'price': 0, }), (0, 0, { 'name': 'VIP', 'product_id': self.event_product.id, 'seats_max': 10, }) ], # activate menus 'is_published': True, 'website_menu': True, 'website_track': True, 'website_track_proposal': True, 'exhibitor_menu': True, 'community_menu': True, }) self.event_customer = self.env['res.partner'].create({ 'name': 'Constantin Customer', 'email': 'constantin@test.example.com', 'country_id': self.env.ref('base.be').id, 'phone': '0485112233', 'mobile': False, }) self.event_speaker = self.env['res.partner'].create({ 'name': 'Brandon Freeman', 'email': 'brandon.freeman55@example.com', 'phone': '(355)-687-3262', }) # ------------------------------------------------------------ # QUESTIONS # ------------------------------------------------------------ self.event_question_1 = self.env['event.question'].create({ 'title': 'Which field are you working in', 'question_type': 'simple_choice', 'event_id': self.event.id, 'once_per_order': False, 'answer_ids': [ (0, 0, {'name': 'Consumers'}), (0, 0, {'name': 'Sales'}), (0, 0, {'name': 'Research'}), ], }) self.event_question_2 = self.env['event.question'].create({ 'title': 'How did you hear about us ?', 'question_type': 'text_box', 'event_id': self.event.id, 'once_per_order': True, }) # ------------------------------------------------------------ # TRACKS # ------------------------------------------------------------ self.track_0 = self.env['event.track'].create({ 'name': 'What This Event Is All About', 'event_id': self.event.id, 'stage_id': self.env.ref('website_event_track.event_track_stage3').id, 'date': self.reference_now + timedelta(hours=1), 'duration': 2, 'is_published': True, 'wishlisted_by_default': True, 'user_id': self.user_admin.id, 'partner_id': self.event_speaker.id, }) self.track_1 = self.env['event.track'].create({ 'name': 'Live Testimonial', 'event_id': self.event.id, 'stage_id': self.env.ref('website_event_track.event_track_stage3').id, 'date': self.reference_now - timedelta(minutes=30), 'duration': 0.75, 'is_published': True, 'user_id': self.user_admin.id, 'partner_id': self.event_speaker.id, }) self.track_2 = self.env['event.track'].create({ 'name': 'Our Last Day Together!', 'event_id': self.event.id, 'stage_id': self.env.ref('website_event_track.event_track_stage3').id, 'date': self.reference_now + timedelta(days=1), 'duration': 0.75, 'is_published': True, 'user_id': self.user_admin.id, 'partner_id': self.event_speaker.id, }) # ------------------------------------------------------------ # MEETING ROOMS # ---------------------------------------------------------- self.env['event.meeting.room'].create({ 'name': 'Best wood for furniture', 'summary': 'Let\'s talk about wood types for furniture', 'target_audience': 'wood expert(s)', 'is_pinned': True, 'website_published': True, 'event_id': self.event.id, 'room_lang_id': self.env.ref('base.lang_en').id, 'room_max_capacity': '12', 'room_participant_count': 9, }) self.env.flush_all()