diff --git a/addons/event/security/event_security.xml b/addons/event/security/event_security.xml index 613625f2c78..1059c26c9c0 100644 --- a/addons/event/security/event_security.xml +++ b/addons/event/security/event_security.xml @@ -29,27 +29,18 @@ Event: multi-company - ['|', - ('company_id', '=', False), - ('company_id', 'in', company_ids), - ] - + ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)] Event/Registration: multi-company - ['|', - ('company_id', '=', False), - ('company_id', 'in', company_ids), - ] - + ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)] - - Event/Registration: Portal - - - ['|', ('email', '=', user.partner_id.email), ('partner_id', '=', user.partner_id.id)] - + + Event/Ticket: multi-company + + ['|', ('event_id.company_id', '=', False), ('event_id.company_id', 'in', company_ids)] + diff --git a/addons/event/security/ir.model.access.csv b/addons/event/security/ir.model.access.csv index 909f21e4b80..3bc63e6c9e4 100644 --- a/addons/event/security/ir.model.access.csv +++ b/addons/event/security/ir.model.access.csv @@ -9,8 +9,7 @@ access_event_event_manager,event.event.manager,model_event_event,event.group_eve access_event_event_ticket_user,event.event.ticket.user,model_event_event_ticket,event.group_event_user,1,0,0,0 access_event_event_ticket_manager,event.event.ticket.manager,model_event_event_ticket,event.group_event_manager,1,1,1,1 access_event_registration,event.registration,model_event_registration,event.group_event_user,1,1,1,1 -access_event_registration_employee,event.registration,model_event_registration,base.group_user,1,0,0,0 -access_event_registration_portal,event.registration,model_event_registration,base.group_portal,1,0,0,0 +access_event_registration_all,event.registration,model_event_registration,,0,0,0,0 access_event_mail,event.mail,model_event_mail,event.group_event_user,1,0,0,0 access_event_mail_manager,event.mail manager,model_event_mail,event.group_event_manager,1,1,1,1 access_event_mail_registration,event.mail.registration,model_event_mail_registration,event.group_event_user,1,0,0,0 @@ -21,5 +20,5 @@ access_event_stage_user,event.stage.user,model_event_stage,event.group_event_use access_event_stage_manager,event.stage.manager,model_event_stage,event.group_event_manager,1,1,1,1 access_event_category,event.tag.category,model_event_tag_category,event.group_event_user,1,0,0,0 access_event_category_manager,event.tag.category manager,model_event_tag_category,event.group_event_manager,1,1,1,1 -access_event_tag,event.tag,model_event_tag,event.group_event_user,1,0,0,0 +access_event_tag,event.tag,model_event_tag,event.group_event_user,1,1,0,0 access_event_tag_manager,event.tag manager,model_event_tag,event.group_event_manager,1,1,1,1 diff --git a/addons/event/static/src/js/tours/event_tour.js b/addons/event/static/src/js/tours/event_tour.js index 0ab5bd475ab..7c40cf6f1ce 100644 --- a/addons/event/static/src/js/tours/event_tour.js +++ b/addons/event/static/src/js/tours/event_tour.js @@ -96,6 +96,7 @@ tour.register('event_tour', { }, { trigger: 'button.o_kanban_add', content: _t("Click add to create a new stage."), + position: 'bottom', width: 200, run: 'click', }].filter(Boolean)); diff --git a/addons/event/tests/test_event_security.py b/addons/event/tests/test_event_security.py index 019458e2fd9..573dc57a515 100644 --- a/addons/event/tests/test_event_security.py +++ b/addons/event/tests/test_event_security.py @@ -58,11 +58,6 @@ class TestEventSecurity(TestEventCommon): '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): diff --git a/addons/event_sale/models/event_ticket.py b/addons/event_sale/models/event_ticket.py index 0b899f79269..7759a547d84 100644 --- a/addons/event_sale/models/event_ticket.py +++ b/addons/event_sale/models/event_ticket.py @@ -24,7 +24,7 @@ class EventTemplateTicket(models.Model): digits='Product Price', readonly=False, store=True) price_reduce = fields.Float( string="Price Reduce", compute="_compute_price_reduce", - digits='Product Price') + compute_sudo=True, digits='Product Price') @api.depends('product_id') def _compute_price(self): @@ -47,7 +47,7 @@ class EventTemplateTicket(models.Model): def _compute_price_reduce(self): for ticket in self: product = ticket.product_id - discount = product.lst_price and (product.lst_price - product.price) / product.lst_price or 0.0 + discount = (product.lst_price - product.price) / product.lst_price if product.lst_price else 0.0 ticket.price_reduce = (1.0 - discount) * ticket.price def _init_column(self, column_name): @@ -97,14 +97,16 @@ class EventTicket(models.Model): _order = "event_id, price" # product - price_reduce_taxinc = fields.Float(string='Price Reduce Tax inc', compute='_compute_price_reduce_taxinc') + price_reduce_taxinc = fields.Float( + string='Price Reduce Tax inc', compute='_compute_price_reduce_taxinc', + compute_sudo=True) def _compute_price_reduce_taxinc(self): - for record in self: + for event in self: # sudo necessary here since the field is most probably accessed through the website - tax_ids = record.sudo().product_id.taxes_id.filtered(lambda r: r.company_id == record.event_id.company_id) - taxes = tax_ids.compute_all(record.price_reduce, record.event_id.company_id.currency_id, 1.0, product=record.product_id) - record.price_reduce_taxinc = taxes['total_included'] + tax_ids = event.product_id.taxes_id.filtered(lambda r: r.company_id == event.event_id.company_id) + taxes = tax_ids.compute_all(event.price_reduce, event.event_id.company_id.currency_id, 1.0, product=event.product_id) + event.price_reduce_taxinc = taxes['total_included'] @api.depends('product_id.active') def _compute_sale_available(self): diff --git a/addons/test_event_full/static/src/js/tours/wevent_register_tour.js b/addons/test_event_full/static/src/js/tours/wevent_register_tour.js index 5d1ba5102f7..7d24c0ef0c6 100644 --- a/addons/test_event_full/static/src/js/tours/wevent_register_tour.js +++ b/addons/test_event_full/static/src/js/tours/wevent_register_tour.js @@ -91,9 +91,12 @@ var registerSteps = [{ $("input[name='1-name']").val("Raoulette Poiluchette"); $("input[name='1-phone']").val("0456112233"); $("input[name='1-email']").val("raoulette@example.com"); + $("select[name*='question_answer-1']").val($("select[name*='question_answer-1'] option:contains('Consumers')").val()); $("input[name='2-name']").val("Michel Tractopelle"); $("input[name='2-phone']").val("0456332211"); $("input[name='2-email']").val("michel@example.com"); + $("select[name*='question_answer-2']").val($("select[name*='question_answer-1'] option:contains('Research')").val()); + $("textarea[name*='question_answer']").text("An unicorn told me about you. I ate it afterwards."); }, }, { content: "Validate attendees details", @@ -101,8 +104,15 @@ var registerSteps = [{ trigger: 'button:contains("Continue")', run: 'click', }, { - trigger: 'h3:contains("Registration confirmed!")', + trigger: 'div.o_wereg_confirmed_attendees span:contains("Raoulette Poiluchette")', run: function () {} // check +}, { + trigger: 'div.o_wereg_confirmed_attendees span:contains("Michel Tractopelle")', + run: function () {} // check +}, { + content: "Click on 'register favorites talks' button", + trigger: 'a:contains("register to your favorites talks now")', + run: 'click', }]; /** diff --git a/addons/test_event_full/tests/common.py b/addons/test_event_full/tests/common.py index dfdfb9914be..ab729cb9fa7 100644 --- a/addons/test_event_full/tests/common.py +++ b/addons/test_event_full/tests/common.py @@ -3,7 +3,6 @@ from datetime import datetime, timedelta, time -from odoo import fields from odoo.addons.base.tests.common import HttpCaseWithUserDemo, HttpCaseWithUserPortal from odoo.addons.event_crm.tests.common import TestEventCrmCommon from odoo.addons.sales_team.tests.common import TestSalesCommon @@ -209,27 +208,18 @@ class TestWEventCommon(HttpCaseWithUserDemo, HttpCaseWithUserPortal, EventDtPatc # ------------------------------------------------------------ self.event_question_1 = self.env['event.question'].create({ - 'title': 'Question1', + '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': 'Q1-Answer1'}), - (0, 0, {'name': 'Q1-Answer2'}) + (0, 0, {'name': 'Consumers'}), + (0, 0, {'name': 'Sales'}), + (0, 0, {'name': 'Research'}), ], }) self.event_question_2 = self.env['event.question'].create({ - 'title': 'Question2', - 'question_type': 'simple_choice', - 'event_id': self.event.id, - 'once_per_order': True, - 'answer_ids': [ - (0, 0, {'name': 'Q2-Answer1'}), - (0, 0, {'name': 'Q2-Answer2'}) - ], - }) - self.event_question_3 = self.env['event.question'].create({ - 'title': 'Question3', + 'title': 'How did you hear about us ?', 'question_type': 'text_box', 'event_id': self.event.id, 'once_per_order': True, diff --git a/addons/test_event_full/tests/test_wevent_register.py b/addons/test_event_full/tests/test_wevent_register.py index cd880ec0652..b1f34d102cd 100644 --- a/addons/test_event_full/tests/test_wevent_register.py +++ b/addons/test_event_full/tests/test_wevent_register.py @@ -16,3 +16,29 @@ class TestWEventRegister(TestWEventCommon): 'odoo.__DEBUG__.services["web_tour.tour"].tours.wevent_register.ready', login=None ) + new_registrations = self.event.registration_ids + visitor = new_registrations.visitor_id + + # check registration content + self.assertEqual(len(new_registrations), 2) + self.assertEqual( + set(new_registrations.mapped("name")), + set(["Raoulette Poiluchette", "Michel Tractopelle"]) + ) + self.assertEqual( + set(new_registrations.mapped("phone")), + set(["0456112233", "0456332211"]) + ) + self.assertEqual( + set(new_registrations.mapped("email")), + set(["raoulette@example.com", "michel@example.com"]) + ) + + # check visitor stored information + self.assertEqual(visitor.name, "Raoulette Poiluchette") + self.assertEqual(visitor.event_registration_ids, new_registrations) + self.assertEqual(visitor.partner_id, self.env['res.partner']) + self.assertEqual(visitor.mobile, "0456112233") + self.assertEqual(visitor.email, "raoulette@example.com") + self.assertFalse(visitor.parent_id) + self.assertTrue(visitor.active) diff --git a/addons/website_event/__manifest__.py b/addons/website_event/__manifest__.py index ddc64074e1c..db44af018fd 100644 --- a/addons/website_event/__manifest__.py +++ b/addons/website_event/__manifest__.py @@ -16,6 +16,7 @@ 'views/event_templates.xml', 'views/event_templates_misc_pages.xml', 'views/event_templates_registration.xml', + 'views/website_templates.xml', 'views/event_views.xml', 'security/ir.model.access.csv', 'security/event_security.xml', diff --git a/addons/website_event/controllers/main.py b/addons/website_event/controllers/main.py index 31a930d6e66..0665dce85bb 100644 --- a/addons/website_event/controllers/main.py +++ b/addons/website_event/controllers/main.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- +import collections import babel.dates import re import werkzeug from werkzeug.datastructures import OrderedMultiDict +from werkzeug.exceptions import NotFound from ast import literal_eval from collections import defaultdict @@ -13,6 +15,7 @@ from dateutil.relativedelta import relativedelta from odoo import fields, http, _ from odoo.addons.http_routing.models.ir_http import slug from odoo.addons.website.controllers.main import QueryURL +from odoo.addons.event.controllers.main import EventController from odoo.http import request from odoo.osv import expression from odoo.tools.misc import get_lang, format_date @@ -27,7 +30,7 @@ class WebsiteEventController(http.Controller): @http.route(['/event', '/event/page/', '/events', '/events/page/'], type='http', auth="public", website=True, sitemap=sitemap_event) def events(self, page=1, **searches): Event = request.env['event.event'] - EventType = request.env['event.type'] + SudoEventType = request.env['event.type'].sudo() searches.setdefault('search', '') searches.setdefault('date', 'all') @@ -95,7 +98,7 @@ class WebsiteEventController(http.Controller): current_date = date[1] if searches["type"] != 'all': - current_type = EventType.browse(int(searches['type'])) + current_type = SudoEventType.browse(int(searches['type'])) domain_search["type"] = [("event_type_id", "=", int(searches["type"]))] if searches["country"] != 'all' and searches["country"] != 'online': @@ -296,6 +299,9 @@ class WebsiteEventController(http.Controller): @http.route(['/event//registration/new'], type='json', auth="public", methods=['POST'], website=True) def registration_new(self, event, **post): + if not event.can_access_from_current_website(): + raise werkzeug.exceptions.NotFound() + tickets = self._process_tickets_form(event, post) availability_check = True if event.seats_limited: @@ -311,14 +317,16 @@ class WebsiteEventController(http.Controller): def _process_attendees_form(self, event, form_details): """ Process data posted from the attendee details form. - :param details: posted data from frontend registration form, like + :param form_details: posted data from frontend registration form, like {'1-name': 'r', '1-email': 'r@r.com', '1-phone': '', '1-event_ticket_id': '1'} """ - registration_fields = request.env['event.registration']._fields + allowed_fields = {'name', 'phone', 'email', 'mobile', 'event_id', 'partner_id', 'event_ticket_id'} + registration_fields = {key: v for key, v in request.env['event.registration']._fields.items() if key in allowed_fields} registrations = {} global_values = {} for key, value in form_details.items(): - counter, field_name = key.split('-', 1) + counter, attr_name = key.split('-', 1) + field_name = attr_name.split('-')[0] if field_name not in registration_fields: continue elif isinstance(registration_fields[field_name], (fields.Many2one, fields.Integer)): @@ -327,12 +335,13 @@ class WebsiteEventController(http.Controller): value = value if counter == '0': - global_values[field_name] = value + global_values[attr_name] = value else: - registrations.setdefault(counter, dict())[field_name] = value + registrations.setdefault(counter, dict())[attr_name] = value for key, value in global_values.items(): for registration in registrations.values(): registration[key] = value + return list(registrations.values()) def _create_attendees_from_registration_post(self, event, registration_data): @@ -351,11 +360,11 @@ class WebsiteEventController(http.Controller): raise werkzeug.exceptions.NotFound() registrations = self._process_attendees_form(event, post) - attendees = self._create_attendees_from_registration_post(event, registrations) + attendees_sudo = self._create_attendees_from_registration_post(event, registrations) urls = event._get_event_resource_urls() return request.render("website_event.registration_complete", { - 'attendees': attendees, + 'attendees': attendees_sudo, 'event': event, 'google_url': urls.get('google_url'), 'iCal_url': urls.get('iCal_url') @@ -369,6 +378,6 @@ class WebsiteEventController(http.Controller): except: pass else: - # perform a search to filter on existing / valid tags implicitely + # perform a search to filter on existing / valid tags implicitely + apply rules on color tags = request.env['event.tag'].search([('id', 'in', tag_ids)]) return tags diff --git a/addons/website_event/i18n/website_event.pot b/addons/website_event/i18n/website_event.pot index 6a35067dfc1..af1b772770a 100644 --- a/addons/website_event/i18n/website_event.pot +++ b/addons/website_event/i18n/website_event.pot @@ -131,7 +131,9 @@ msgstr "" #. module: website_event #: model_terms:ir.ui.view,arch_db:website_event.layout -msgid "All Events" +msgid "" +"\n" +" All Events" msgstr "" #. module: website_event @@ -165,6 +167,14 @@ msgstr "" msgid "Events" msgstr "" +#. module: website_event +#: model_terms:ir.ui.view,arch_db:website_event.registration_template +msgid "" +"\n" +" Registered\n" +" " +msgstr "" + #. module: website_event #: model_terms:ir.ui.view,arch_db:website_event.registration_template msgid "" @@ -177,14 +187,6 @@ msgstr "" msgid "Qty" msgstr "" -#. module: website_event -#: model_terms:ir.ui.view,arch_db:website_event.registration_template -msgid "" -"\n" -" Registered\n" -" " -msgstr "" - #. module: website_event #: model_terms:ir.ui.view,arch_db:website_event.registration_template msgid "" @@ -628,6 +630,16 @@ msgstr "" msgid "Sales start on" msgstr "" +#. module: website_event +#: model_terms:ir.ui.view,arch_db:website_event.layout +msgid "Search an event ..." +msgstr "" + +#. module: website_event +#: model_terms:ir.ui.view,arch_db:website_event.index_topbar +msgid "Search an event..." +msgstr "" + #. module: website_event #: model_terms:ir.ui.view,arch_db:website_event.country_events_list msgid "See all events from" diff --git a/addons/website_event/models/event_event.py b/addons/website_event/models/event_event.py index 01d76489777..925aed32996 100644 --- a/addons/website_event/models/event_event.py +++ b/addons/website_event/models/event_event.py @@ -45,7 +45,7 @@ class Event(models.Model): email = self.env.user.partner_id.email for event in self: domain = ['&', '|', ('email', '=', email), ('partner_id', '=', self.env.user.partner_id.id), ('event_id', '=', event.id)] - event.is_participating = self.env['event.registration'].search_count(domain) + event.is_participating = self.env['event.registration'].sudo().search_count(domain) else: self.is_participating = False @@ -193,6 +193,10 @@ class Event(models.Model): # ------------------------------------------------------------ def google_map_link(self, zoom=8): + """ Temporary method for stable """ + return self._google_map_link(zoom=zoom) + + def _google_map_link(self, zoom=8): self.ensure_one() if self.address_id: return self.sudo().address_id.google_map_link(zoom=zoom) diff --git a/addons/website_event/security/event_security.xml b/addons/website_event/security/event_security.xml index d34a1f76a48..857e758e9c0 100644 --- a/addons/website_event/security/event_security.xml +++ b/addons/website_event/security/event_security.xml @@ -2,7 +2,7 @@ - event: Public + Event: public/portal: published read [('website_published', '=', True)] @@ -13,7 +13,7 @@ - Event ticket: public/portal may read published + Event Ticket: public/portal: published read [('event_id.website_published', '=', True)] diff --git a/addons/website_event/security/ir.model.access.csv b/addons/website_event/security/ir.model.access.csv index e55cfc58bbf..985c14e5190 100644 --- a/addons/website_event/security/ir.model.access.csv +++ b/addons/website_event/security/ir.model.access.csv @@ -1,7 +1,7 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_event_event_public,event.event.public,event.model_event_event,base.group_public,1,0,0,0 access_event_event_portal,event.event.portal,event.model_event_event,base.group_portal,1,0,0,0 -access_event_type_public,event.type.public,event.model_event_type,,1,0,0,0 +access_event_type_public,event.type.public,event.model_event_type,,0,0,0,0 access_event_event_ticket_public,event.event.ticket.public,event.model_event_event_ticket,base.group_public,1,0,0,0 access_event_event_ticket_portal,event.event.ticket.portal,event.model_event_event_ticket,base.group_portal,1,0,0,0 access_event_category_public,event.tag.category.public,event.model_event_tag_category,,1,0,0,0 diff --git a/addons/website_event/static/src/scss/website_event.scss b/addons/website_event/static/src/scss/website_event.scss index 1b06d02d7ad..48b2342b806 100644 --- a/addons/website_event/static/src/scss/website_event.scss +++ b/addons/website_event/static/src/scss/website_event.scss @@ -151,7 +151,7 @@ // Multi-line event title, even in mobile mode nav > div > a.navbar-brand { text-overflow: revert; - white-space: break-spaces; + white-space: normal; overflow: hidden; max-width: calc(100% - 80px); } diff --git a/addons/website_event/tests/__init__.py b/addons/website_event/tests/__init__.py index 6986da4eab7..41f5bb1157f 100644 --- a/addons/website_event/tests/__init__.py +++ b/addons/website_event/tests/__init__.py @@ -5,3 +5,4 @@ from . import common from . import test_event_internals from . import test_ui from . import test_website_event +from . import test_website_event_access diff --git a/addons/website_event/tests/test_website_event_access.py b/addons/website_event/tests/test_website_event_access.py new file mode 100644 index 00000000000..64da6f4c6c5 --- /dev/null +++ b/addons/website_event/tests/test_website_event_access.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from functools import partial +from datetime import datetime, timedelta + +from odoo.tests import HttpCase, new_test_user, tagged +from odoo.tools import mute_logger + + +@tagged('post_install', '-at_install') +class TestWebsiteEventAccess(HttpCase): + def setUp(self): + super(TestWebsiteEventAccess, self).setUp() + + self.events = self.env['event.event'].create([{ + 'name': 'Event 0 - Sitemap test', + 'website_published': True, + 'date_begin': datetime.today() - timedelta(days=1), + 'date_end': datetime.today() + timedelta(days=1), + }, { + 'name': 'Event 1 - Sitemap test', + 'website_published': True, + 'date_begin': datetime.today() - timedelta(days=1), + 'date_end': datetime.today() + timedelta(days=1), + }, { + 'name': 'Event 2 - Sitemap test', + 'date_begin': datetime.today() - timedelta(days=1), + 'date_end': datetime.today() + timedelta(days=1), + }]) + + event_new_test_user = partial(new_test_user, context={'mail_create_nolog': True, 'mail_create_nosubscribe': True, 'mail_notrack': True, 'no_reset_password': True}) + self.event_manager = event_new_test_user( + self.env, name='Gandalf le blanc', login='event_manager', password='event_manager', email='event.manager@example.com', + groups='event.group_event_manager,base.group_user' + ) + + self.event_user = event_new_test_user( + self.env, name='Frodon Sacquet', login='event_user', password='event_user', email='event.user@example.com', + groups='event.group_event_user,base.group_user' + ) + + self.portal_user = event_new_test_user( + self.env, name='Smeagol', login='user_portal', password='user_portal', email='portal@example.com', + groups='base.group_portal' + ) + + def test_sitemap(self): + resp = self.url_open('/sitemap.xml') + self.assertTrue('/event/event-0' in resp.text, 'Published events must be present in the sitemap') + self.assertTrue('/event/event-1' in resp.text, 'Published events must be present in the sitemap') + self.assertFalse('/event/event-2' in resp.text, 'Unpublished events must not be present in the sitemap') + + def test_events_access_1(self): + """Access to a published event with public user.""" + published_events = self.events.filtered(lambda event: event.website_published) + resp = self.url_open('/event/%i' % published_events[0].id) + self.assertEqual(resp.status_code, 200, 'We must have access to published event') + + def test_events_access_2(self): + """Access to an unpublished event with public user.""" + with mute_logger('odoo.addons.http_routing.models.ir_http'): + unpublished_events = self.events.filtered(lambda event: not event.website_published) + resp = self.url_open('/event/%i' % unpublished_events[0].id) + self.assertEqual(resp.status_code, 403, 'We must not have access to unpublished event') + + def test_events_access_3(self): + """Access to an published event with admin user.""" + self.authenticate('event_manager', 'event_manager') + published_events = self.events.filtered(lambda event: event.website_published) + resp = self.url_open('/event/%i' % published_events[0].id) + self.assertEqual(resp.status_code, 200, 'Admin must have access to published event.') + + def test_events_access_4(self): + """Access to an unpublished event with admin user.""" + self.authenticate('event_manager', 'event_manager') + unpublished_events = self.events.filtered(lambda event: not event.website_published) + resp = self.url_open('/event/%i' % unpublished_events[0].id) + self.assertEqual(resp.status_code, 200, 'Admin must have access to unpublished event.') + + def test_events_access_5(self): + """Access to an published event with event user.""" + self.authenticate('event_user', 'event_user') + published_events = self.events.filtered(lambda event: event.website_published) + resp = self.url_open('/event/%i' % published_events[0].id) + self.assertEqual(resp.status_code, 200, 'Event user must have access to published event.') + + def test_events_access_6(self): + """Access to an unpublished event with event user.""" + self.authenticate('event_user', 'event_user') + unpublished_events = self.events.filtered(lambda event: not event.website_published) + resp = self.url_open('/event/%i' % unpublished_events[0].id) + self.assertEqual(resp.status_code, 200, 'Event user must have access to unpublished event.') + + def test_events_access_7(self): + """Access to an published event with portal user.""" + self.authenticate('user_portal', 'user_portal') + published_events = self.events.filtered(lambda event: event.website_published) + resp = self.url_open('/event/%i' % published_events[0].id) + self.assertEqual(resp.status_code, 200, 'Portal user must have access to published event.') + + def test_events_access_8(self): + """Access to an unpublished event with portal user.""" + with mute_logger('odoo.addons.http_routing.models.ir_http'): + self.authenticate('user_portal', 'user_portal') + unpublished_events = self.events.filtered(lambda event: not event.website_published) + resp = self.url_open('/event/%i' % unpublished_events[0].id) + self.assertEqual(resp.status_code, 403, 'Portal user must not have access to unpublished event.') + + def test_events_home_page_1(self): + """Portal can only view the published events.""" + self.authenticate('user_portal', 'user_portal') + published_event = self.events.filtered(lambda event: event.website_published)[0] + unpublished_event = self.events.filtered(lambda event: not event.website_published)[0] + resp = self.url_open('/event') + self.assertTrue(unpublished_event.name not in resp.text, 'Portal should not see the unpublished events.') + self.assertTrue(published_event.name in resp.text, 'Portal must see the published events.') + + def test_events_home_page_2(self): + """Admin can see all the events.""" + self.authenticate('event_manager', 'event_manager') + published_event = self.events.filtered(lambda event: event.website_published)[0] + unpublished_event = self.events.filtered(lambda event: not event.website_published)[0] + resp = self.url_open('/event') + self.assertTrue(unpublished_event.name in resp.text, 'Admin must see the unpublished events.') + self.assertTrue(published_event.name in resp.text, 'Admin must see the published events.') diff --git a/addons/website_event/views/event_templates.xml b/addons/website_event/views/event_templates.xml index c3cf0609461..0ff048ad730 100644 --- a/addons/website_event/views/event_templates.xml +++ b/addons/website_event/views/event_templates.xml @@ -51,7 +51,7 @@ - + Search an event... @@ -346,29 +346,35 @@ + + - - - All Events + + + + All Events - - + + - + - + - - - - + + + + + Search an event ... + + @@ -461,7 +467,7 @@ "fields": ["phone", "mobile", "email"] }'/> - Get the direction + Get the direction diff --git a/addons/website_event/views/event_templates_misc_pages.xml b/addons/website_event/views/event_templates_misc_pages.xml index b20eba9943a..50bfc4cb637 100644 --- a/addons/website_event/views/event_templates_misc_pages.xml +++ b/addons/website_event/views/event_templates_misc_pages.xml @@ -54,4 +54,18 @@ + + + + + + Event not found! + Sorry, the requested event is not available anymore. + Return to the event list. + + + + + + diff --git a/addons/website_event/views/website_templates.xml b/addons/website_event/views/website_templates.xml new file mode 100644 index 00000000000..28d4593c57c --- /dev/null +++ b/addons/website_event/views/website_templates.xml @@ -0,0 +1,21 @@ + + + + + + + + + + event.group_event_manager + + + + + + + + + + + diff --git a/addons/website_event_meet/static/src/xml/website_event_meeting_room.xml b/addons/website_event_meet/static/src/xml/website_event_meeting_room.xml index bb08735c4ee..b742d989b86 100644 --- a/addons/website_event_meet/static/src/xml/website_event_meeting_room.xml +++ b/addons/website_event_meet/static/src/xml/website_event_meeting_room.xml @@ -10,6 +10,7 @@ class="text-dark" method="POST"> Launch a new topic + Be sure you are ready to spend at least 10 minutes in the room if you want to initiate a new topic. Room Topic diff --git a/addons/website_event_meet/views/event_meet_templates_list.xml b/addons/website_event_meet/views/event_meet_templates_list.xml index 2ca4ab38b37..700cfd4bf8e 100644 --- a/addons/website_event_meet/views/event_meet_templates_list.xml +++ b/addons/website_event_meet/views/event_meet_templates_list.xml @@ -26,10 +26,10 @@ - + Join a room - ▼ @@ -38,7 +38,7 @@ - + Choose a topic that interests you and start talking with the community. Don't forget to setup your camera and microphone. @@ -130,7 +130,7 @@ - + @@ -151,10 +151,9 @@ - Launch a new topic + Start a topic Want to create your own discussion room ? - Be sure you are ready to spend at least 10 minutes in the room if you want to initiate a new topic. - Leaderboard + Leaderboard View all diff --git a/addons/website_event_online/__manifest__.py b/addons/website_event_online/__manifest__.py index b35d80dda85..d391ea3346b 100644 --- a/addons/website_event_online/__manifest__.py +++ b/addons/website_event_online/__manifest__.py @@ -15,6 +15,7 @@ ], 'data': [ 'security/ir.model.access.csv', + 'security/event_security.xml', 'views/assets.xml', 'views/event_event_views.xml', 'views/event_registration_views.xml', diff --git a/addons/website_event_online/models/website_visitor.py b/addons/website_event_online/models/website_visitor.py index bd767cab171..078e4f03296 100644 --- a/addons/website_event_online/models/website_visitor.py +++ b/addons/website_event_online/models/website_visitor.py @@ -43,7 +43,7 @@ class WebsiteVisitor(models.Model): self.flush() for visitor in self.filtered(lambda visitor: not visitor.email or not visitor.mobile): - linked_registrations = visitor.event_registration_ids.sorted('create_date', reverse=True) + linked_registrations = visitor.event_registration_ids.sorted(lambda reg: (reg.create_date, reg.id), reverse=False) if not visitor.email: visitor.email = next((reg.email for reg in linked_registrations if reg.email), False) if not visitor.mobile: diff --git a/addons/website_event_online/security/event_security.xml b/addons/website_event_online/security/event_security.xml new file mode 100644 index 00000000000..d7e1c0d29cb --- /dev/null +++ b/addons/website_event_online/security/event_security.xml @@ -0,0 +1,15 @@ + + + + + Event Tag: public/portal: color = published + + ['&', ('color', '!=', False), ('color', '!=', 0)] + + + + + + + + diff --git a/addons/website_event_questions/__manifest__.py b/addons/website_event_questions/__manifest__.py index c0c913a28ee..10bd9acb673 100644 --- a/addons/website_event_questions/__manifest__.py +++ b/addons/website_event_questions/__manifest__.py @@ -13,6 +13,7 @@ 'views/event_registration_views.xml', 'views/event_question_views.xml', 'views/event_templates.xml', + 'security/security.xml', 'security/ir.model.access.csv', ], 'demo': [ diff --git a/addons/website_event_questions/controllers/main.py b/addons/website_event_questions/controllers/main.py index fdcc1f66313..885866ab1b0 100644 --- a/addons/website_event_questions/controllers/main.py +++ b/addons/website_event_questions/controllers/main.py @@ -23,14 +23,14 @@ class WebsiteEvent(WebsiteEventController): for key, value in form_details.items(): if 'question_answer' in key and value: dummy, registration_index, question_id = key.split('-') - question = request.env['event.question'].browse(int(question_id)) + question_sudo = request.env['event.question'].browse(int(question_id)) answer_values = None - if question.question_type == 'simple_choice': + if question_sudo.question_type == 'simple_choice': answer_values = { 'question_id': int(question_id), 'value_answer_id': int(value) } - elif question.question_type == 'text_box': + elif question_sudo.question_type == 'text_box': answer_values = { 'question_id': int(question_id), 'value_text_box': value diff --git a/addons/website_event_questions/data/event_question_demo.xml b/addons/website_event_questions/data/event_question_demo.xml index 021763bd8a3..16772d46bb3 100644 --- a/addons/website_event_questions/data/event_question_demo.xml +++ b/addons/website_event_questions/data/event_question_demo.xml @@ -66,4 +66,34 @@ 3 + + + + Which field are you working in + simple_choice + + + + + Consumers + 1 + + + + Sales + 2 + + + + Research + 3 + + + + How did you hear about us ? + text_box + + + + diff --git a/addons/website_event_questions/security/security.xml b/addons/website_event_questions/security/security.xml new file mode 100644 index 00000000000..8c44829ca6b --- /dev/null +++ b/addons/website_event_questions/security/security.xml @@ -0,0 +1,46 @@ + + + + + Event Question: not event groups: event published read + + [('event_id.is_published', '=', True)] + + + + + + + + Event Question: event user: read all + + [(1, '=', 1)] + + + + + + + + + Event Question Answer: not event groups: event published read + + [('question_id.event_id.is_published', '=', True)] + + + + + + + + Event Question Answer: event user: read all + + [(1, '=', 1)] + + + + + + + + diff --git a/addons/website_event_questions/static/tests/tours/tickets_questions.js b/addons/website_event_questions/static/tests/tours/tickets_questions.js index 458ecc7eb90..dc28df2e3aa 100644 --- a/addons/website_event_questions/static/tests/tours/tickets_questions.js +++ b/addons/website_event_questions/static/tests/tours/tickets_questions.js @@ -44,7 +44,7 @@ tour.register('test_tickets_questions', { trigger: 'div:contains("Ticket #2").modal-body select[name*="question_answer"]', run: 'text Pastafarian' }, { - trigger: 'div:contains("General questions").modal-body select[name*="question_answer"]', + trigger: 'div.o_wevent_registration_question_global select[name*="question_answer"]', run: 'text A friend' }, { trigger: 'button:contains("Continue")', diff --git a/addons/website_event_questions/views/event_templates.xml b/addons/website_event_questions/views/event_templates.xml index ef6d1a4c791..02c21b99b34 100644 --- a/addons/website_event_questions/views/event_templates.xml +++ b/addons/website_event_questions/views/event_templates.xml @@ -17,8 +17,7 @@ - - General questions + diff --git a/addons/website_event_sale/__manifest__.py b/addons/website_event_sale/__manifest__.py index d13f7aa59cc..20e062d011d 100644 --- a/addons/website_event_sale/__manifest__.py +++ b/addons/website_event_sale/__manifest__.py @@ -15,7 +15,6 @@ Sell event tickets through eCommerce app. 'views/event_event_views.xml', 'views/website_event_templates.xml', 'views/website_sale_templates.xml', - 'security/ir.model.access.csv', 'security/website_event_sale_security.xml', ], 'auto_install': True diff --git a/addons/website_event_sale/security/ir.model.access.csv b/addons/website_event_sale/security/ir.model.access.csv deleted file mode 100644 index 74efdec9621..00000000000 --- a/addons/website_event_sale/security/ir.model.access.csv +++ /dev/null @@ -1,3 +0,0 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_event_product_product_public,event.product.product.public,product.model_product_product,base.group_public,1,0,0,0 -access_event_product_template_public,event.product.template.public,product.model_product_template,base.group_public,1,0,0,0 diff --git a/addons/website_event_sale/tests/test_frontend_buy_tickets.py b/addons/website_event_sale/tests/test_frontend_buy_tickets.py index a64dca5d4ad..3740b46bb28 100644 --- a/addons/website_event_sale/tests/test_frontend_buy_tickets.py +++ b/addons/website_event_sale/tests/test_frontend_buy_tickets.py @@ -19,6 +19,7 @@ class TestUi(HttpCaseWithUserDemo): 'user_id': self.env.ref('base.user_admin').id, 'date_begin': (Datetime.today() + timedelta(days=5)).strftime('%Y-%m-%d 07:00:00'), 'date_end': (Datetime.today() + timedelta(days=5)).strftime('%Y-%m-%d 16:30:00'), + 'website_published': True, }) self.env['event.event.ticket'].create([{ diff --git a/addons/website_event_track/security/event_track_security.xml b/addons/website_event_track/security/event_track_security.xml index 7ccae1c6f4c..ca240e2cca4 100644 --- a/addons/website_event_track/security/event_track_security.xml +++ b/addons/website_event_track/security/event_track_security.xml @@ -1,15 +1,26 @@ - - event tracks: Public - - [('website_published', '=', True)] - - - - - - + + Event Tracks: public/portal: published + + [('website_published', '=', True)] + + + + + + + + + Event Track Tag: public/portal: color = published + + ['&', ('color', '!=', False), ('color', '!=', 0)] + + + + + + diff --git a/addons/website_event_track/security/ir.model.access.csv b/addons/website_event_track/security/ir.model.access.csv index 8c5e7569aba..a3c950c9457 100644 --- a/addons/website_event_track/security/ir.model.access.csv +++ b/addons/website_event_track/security/ir.model.access.csv @@ -1,6 +1,7 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_event_track_manager,event.track manager,model_event_track,event.group_event_manager,1,1,1,1 access_event_track_tag_public,event.track.tag public,model_event_track_tag,,1,0,0,0 +access_event_track_tag_user,event.track.tag public,model_event_track_tag,event.group_event_user,1,1,0,0 access_event_track_tag_manager,event.track.tag manager,model_event_track_tag,event.group_event_manager,1,1,1,1 access_event_track_location_public,event.track.location public,model_event_track_location,,1,0,0,0 access_event_track_location_manager,event.track.location manager,model_event_track_location,event.group_event_manager,1,1,1,1 diff --git a/addons/website_event_track/views/event_track_templates.xml b/addons/website_event_track/views/event_track_templates.xml index d6545080495..0430f6670e7 100644 --- a/addons/website_event_track/views/event_track_templates.xml +++ b/addons/website_event_track/views/event_track_templates.xml @@ -239,8 +239,10 @@ Practical Info Date - - () + + + () + Duration diff --git a/addons/website_event_track/views/event_track_views.xml b/addons/website_event_track/views/event_track_views.xml index 522a9477a66..79cc864a5c7 100644 --- a/addons/website_event_track/views/event_track_views.xml +++ b/addons/website_event_track/views/event_track_views.xml @@ -331,7 +331,7 @@ event.track.stage - + diff --git a/addons/website_event_track_exhibitor/controllers/exhibitor.py b/addons/website_event_track_exhibitor/controllers/exhibitor.py index b9083548877..9e37ae03d2e 100644 --- a/addons/website_event_track_exhibitor/controllers/exhibitor.py +++ b/addons/website_event_track_exhibitor/controllers/exhibitor.py @@ -2,7 +2,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from ast import literal_eval -from random import randint +from random import randint, sample from werkzeug.exceptions import NotFound, Forbidden from odoo import exceptions, http @@ -82,7 +82,7 @@ class ExhibitorController(WebsiteEventTrackController): sponsor_categories = [ dict({ 'sponsorship': sponsor_category, - 'sponsors': sponsors, + 'sponsors': sample(sponsors, len(sponsors)), }) for sponsor_category, sponsors in sponsor_categories.items()] # return rendering values @@ -154,7 +154,7 @@ class ExhibitorController(WebsiteEventTrackController): 'sponsor': sponsor, 'hide_sponsors': True, # sidebar - 'sponsors_other': sponsors_other, + 'sponsors_other': sponsors_other[:30], # options 'option_widescreen': option_widescreen, 'option_can_edit': request.env.user.has_group('event.group_event_manager'), diff --git a/addons/website_event_track_exhibitor/views/event_exhibitor_templates_list.xml b/addons/website_event_track_exhibitor/views/event_exhibitor_templates_list.xml index 373a017c82a..84ec83632a1 100644 --- a/addons/website_event_track_exhibitor/views/event_exhibitor_templates_list.xml +++ b/addons/website_event_track_exhibitor/views/event_exhibitor_templates_list.xml @@ -142,7 +142,7 @@ - + @@ -176,7 +176,12 @@ - Connect + + + Register + + Connect + - Connect + + + Register + + Connect +
Sorry, the requested event is not available anymore.
Return to the event list.
Be sure you are ready to spend at least 10 minutes in the room if you want to initiate a new topic.
Choose a topic that interests you and start talking with the community. Don't forget to setup your camera and microphone.
Want to create your own discussion room ?