A recent fix c41d1d2 was made to select the related pricelist
to show the correct price of an event product.
This fix creates another bug in case of Ecommerce app
not installed, because the method get_current_pricelist
is defined in website_sale module.
We need to move the fix from website_event to website_event_sale module.
closes odoo/odoo#31953
Signed-off-by: Jorge Pinna Puissant (jpp) <jpp@odoo.com>
298 lines
13 KiB
Python
298 lines
13 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
import babel.dates
|
|
import re
|
|
import werkzeug
|
|
import json
|
|
|
|
from datetime import datetime, timedelta
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
from odoo import fields, http, _
|
|
from odoo.addons.http_routing.models.ir_http import slug
|
|
from odoo.http import content_disposition, request
|
|
|
|
|
|
class WebsiteEventController(http.Controller):
|
|
|
|
def sitemap_event(env, rule, qs):
|
|
if not qs or qs.lower() in '/events':
|
|
yield {'loc': '/events'}
|
|
|
|
@http.route(['/event', '/event/page/<int:page>', '/events', '/events/page/<int: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']
|
|
|
|
searches.setdefault('date', 'all')
|
|
searches.setdefault('type', 'all')
|
|
searches.setdefault('country', 'all')
|
|
|
|
|
|
def sdn(date):
|
|
return fields.Datetime.to_string(date.replace(hour=23, minute=59, second=59))
|
|
|
|
def sd(date):
|
|
return fields.Datetime.to_string(date)
|
|
today = datetime.today()
|
|
dates = [
|
|
['all', _('Next Events'), [("date_end", ">", sd(today))], 0],
|
|
['today', _('Today'), [
|
|
("date_end", ">", sd(today)),
|
|
("date_begin", "<", sdn(today))],
|
|
0],
|
|
['week', _('This Week'), [
|
|
("date_end", ">=", sd(today + relativedelta(days=-today.weekday()))),
|
|
("date_begin", "<", sdn(today + relativedelta(days=6-today.weekday())))],
|
|
0],
|
|
['nextweek', _('Next Week'), [
|
|
("date_end", ">=", sd(today + relativedelta(days=7-today.weekday()))),
|
|
("date_begin", "<", sdn(today + relativedelta(days=13-today.weekday())))],
|
|
0],
|
|
['month', _('This month'), [
|
|
("date_end", ">=", sd(today.replace(day=1))),
|
|
("date_begin", "<", (today.replace(day=1) + relativedelta(months=1)).strftime('%Y-%m-%d 00:00:00'))],
|
|
0],
|
|
['nextmonth', _('Next month'), [
|
|
("date_end", ">=", sd(today.replace(day=1) + relativedelta(months=1))),
|
|
("date_begin", "<", (today.replace(day=1) + relativedelta(months=2)).strftime('%Y-%m-%d 00:00:00'))],
|
|
0],
|
|
['old', _('Past Events'), [
|
|
("date_end", "<", today.strftime('%Y-%m-%d 00:00:00'))],
|
|
0],
|
|
]
|
|
|
|
# search domains
|
|
domain_search = {'website_specific': request.website.website_domain()}
|
|
current_date = None
|
|
current_type = None
|
|
current_country = None
|
|
for date in dates:
|
|
if searches["date"] == date[0]:
|
|
domain_search["date"] = date[2]
|
|
if date[0] != 'all':
|
|
current_date = date[1]
|
|
if searches["type"] != 'all':
|
|
current_type = EventType.browse(int(searches['type']))
|
|
domain_search["type"] = [("event_type_id", "=", int(searches["type"]))]
|
|
|
|
if searches["country"] != 'all' and searches["country"] != 'online':
|
|
current_country = request.env['res.country'].browse(int(searches['country']))
|
|
domain_search["country"] = ['|', ("country_id", "=", int(searches["country"])), ("country_id", "=", False)]
|
|
elif searches["country"] == 'online':
|
|
domain_search["country"] = [("country_id", "=", False)]
|
|
|
|
def dom_without(without):
|
|
domain = [('state', "in", ['draft', 'confirm', 'done'])]
|
|
for key, search in domain_search.items():
|
|
if key != without:
|
|
domain += search
|
|
return domain
|
|
|
|
# count by domains without self search
|
|
for date in dates:
|
|
if date[0] != 'old':
|
|
date[3] = Event.search_count(dom_without('date') + date[2])
|
|
|
|
domain = dom_without('type')
|
|
types = Event.read_group(domain, ["id", "event_type_id"], groupby=["event_type_id"], orderby="event_type_id")
|
|
types.insert(0, {
|
|
'event_type_id_count': sum([int(type['event_type_id_count']) for type in types]),
|
|
'event_type_id': ("all", _("All Categories"))
|
|
})
|
|
|
|
domain = dom_without('country')
|
|
countries = Event.read_group(domain, ["id", "country_id"], groupby="country_id", orderby="country_id")
|
|
countries.insert(0, {
|
|
'country_id_count': sum([int(country['country_id_count']) for country in countries]),
|
|
'country_id': ("all", _("All Countries"))
|
|
})
|
|
|
|
step = 10 # Number of events per page
|
|
event_count = Event.search_count(dom_without("none"))
|
|
pager = request.website.pager(
|
|
url="/event",
|
|
url_args={'date': searches.get('date'), 'type': searches.get('type'), 'country': searches.get('country')},
|
|
total=event_count,
|
|
page=page,
|
|
step=step,
|
|
scope=5)
|
|
|
|
order = 'date_begin'
|
|
if searches.get('date', 'all') == 'old':
|
|
order = 'date_begin desc'
|
|
if searches["country"] != 'all': # if we are looking for a specific country
|
|
order = 'is_online, ' + order # show physical events first
|
|
order = 'is_published desc, ' + order
|
|
events = Event.search(dom_without("none"), limit=step, offset=pager['offset'], order=order)
|
|
|
|
values = {
|
|
'current_date': current_date,
|
|
'current_country': current_country,
|
|
'current_type': current_type,
|
|
'event_ids': events, # event_ids used in website_event_track so we keep name as it is
|
|
'dates': dates,
|
|
'types': types,
|
|
'countries': countries,
|
|
'pager': pager,
|
|
'searches': searches,
|
|
'search_path': "?%s" % werkzeug.url_encode(searches),
|
|
}
|
|
|
|
return request.render("website_event.index", values)
|
|
|
|
@http.route(['''/event/<model("event.event", "[('website_id', 'in', (False, current_website_id))]"):event>/page/<path:page>'''], type='http', auth="public", website=True, sitemap=False)
|
|
def event_page(self, event, page, **post):
|
|
if not event.can_access_from_current_website():
|
|
raise werkzeug.exceptions.NotFound()
|
|
|
|
values = {
|
|
'event': event,
|
|
'main_object': event
|
|
}
|
|
|
|
if '.' not in page:
|
|
page = 'website_event.%s' % page
|
|
|
|
try:
|
|
request.website.get_template(page)
|
|
except ValueError:
|
|
# page not found
|
|
values['path'] = re.sub(r"^website_event\.", '', page)
|
|
values['from_template'] = 'website_event.default_page' # .strip('website_event.')
|
|
page = 'website.%s' % (request.website.is_publisher() and 'page_404' or '404')
|
|
|
|
return request.render(page, values)
|
|
|
|
@http.route(['''/event/<model("event.event", "[('website_id', 'in', (False, current_website_id))]"):event>'''], type='http', auth="public", website=True)
|
|
def event(self, event, **post):
|
|
if not event.can_access_from_current_website():
|
|
raise werkzeug.exceptions.NotFound()
|
|
|
|
if event.menu_id and event.menu_id.child_id:
|
|
target_url = event.menu_id.child_id[0].url
|
|
else:
|
|
target_url = '/event/%s/register' % str(event.id)
|
|
if post.get('enable_editor') == '1':
|
|
target_url += '?enable_editor=1'
|
|
return request.redirect(target_url)
|
|
|
|
@http.route(['''/event/<model("event.event", "[('website_id', 'in', (False, current_website_id))]"):event>/register'''], type='http', auth="public", website=True, sitemap=False)
|
|
def event_register(self, event, **post):
|
|
if not event.can_access_from_current_website():
|
|
raise werkzeug.exceptions.NotFound()
|
|
|
|
values = {
|
|
'event': event,
|
|
'main_object': event,
|
|
'range': range,
|
|
'registrable': event.sudo()._is_event_registrable()
|
|
}
|
|
return request.render("website_event.event_description_full", values)
|
|
|
|
@http.route('/event/add_event', type='json', auth="user", methods=['POST'], website=True)
|
|
def add_event(self, event_name="New Event", **kwargs):
|
|
event = self._add_event(event_name, request.context)
|
|
return "/event/%s/register?enable_editor=1" % slug(event)
|
|
|
|
def _add_event(self, event_name=None, context=None, **kwargs):
|
|
if not event_name:
|
|
event_name = _("New Event")
|
|
date_begin = datetime.today() + timedelta(days=(14))
|
|
vals = {
|
|
'name': event_name,
|
|
'date_begin': fields.Date.to_string(date_begin),
|
|
'date_end': fields.Date.to_string((date_begin + timedelta(days=(1)))),
|
|
'seats_available': 1000,
|
|
'website_id': request.website.id,
|
|
}
|
|
return request.env['event.event'].with_context(context or {}).create(vals)
|
|
|
|
def get_formated_date(self, event):
|
|
start_date = fields.Datetime.from_string(event.date_begin).date()
|
|
end_date = fields.Datetime.from_string(event.date_end).date()
|
|
month = babel.dates.get_month_names('abbreviated', locale=event.env.context.get('lang') or 'en_US')[start_date.month]
|
|
return ('%s %s%s') % (month, start_date.strftime("%e"), (end_date != start_date and ("-" + end_date.strftime("%e")) or ""))
|
|
|
|
@http.route('/event/get_country_event_list', type='json', auth='public', website=True)
|
|
def get_country_events(self, **post):
|
|
Event = request.env['event.event']
|
|
country_code = request.session['geoip'].get('country_code')
|
|
result = {'events': [], 'country': False}
|
|
events = None
|
|
domain = request.website.website_domain()
|
|
if country_code:
|
|
country = request.env['res.country'].search([('code', '=', country_code)], limit=1)
|
|
events = Event.search(domain + ['|', ('address_id', '=', None), ('country_id.code', '=', country_code), ('date_begin', '>=', '%s 00:00:00' % fields.Date.today()), ('state', '=', 'confirm')], order="date_begin")
|
|
if not events:
|
|
events = Event.search(domain + [('date_begin', '>=', '%s 00:00:00' % fields.Date.today()), ('state', '=', 'confirm')], order="date_begin")
|
|
for event in events:
|
|
if country_code and event.country_id.code == country_code:
|
|
result['country'] = country
|
|
result['events'].append({
|
|
"date": self.get_formated_date(event),
|
|
"event": event,
|
|
"url": event.website_url})
|
|
return request.env['ir.ui.view'].render_template("website_event.country_events_list", result)
|
|
|
|
def _process_tickets_details(self, data):
|
|
nb_register = int(data.get('nb_register-0', 0))
|
|
if nb_register:
|
|
return [{'id': 0, 'name': 'Registration', 'quantity': nb_register, 'price': 0}]
|
|
return []
|
|
|
|
@http.route(['/event/<model("event.event"):event>/registration/new'], type='json', auth="public", methods=['POST'], website=True)
|
|
def registration_new(self, event, **post):
|
|
tickets = self._process_tickets_details(post)
|
|
if not tickets:
|
|
return False
|
|
return request.env['ir.ui.view'].render_template("website_event.registration_attendee_details", {'tickets': tickets, 'event': event})
|
|
|
|
def _process_registration_details(self, details):
|
|
''' Process data posted from the attendee details form. '''
|
|
registrations = {}
|
|
global_values = {}
|
|
for key, value in details.items():
|
|
counter, field_name = key.split('-', 1)
|
|
if counter == '0':
|
|
global_values[field_name] = value
|
|
else:
|
|
registrations.setdefault(counter, dict())[field_name] = value
|
|
for key, value in global_values.items():
|
|
for registration in registrations.values():
|
|
registration[key] = value
|
|
return list(registrations.values())
|
|
|
|
@http.route(['''/event/<model("event.event", "[('website_id', 'in', (False, current_website_id))]"):event>/registration/confirm'''], type='http', auth="public", methods=['POST'], website=True)
|
|
def registration_confirm(self, event, **post):
|
|
if not event.can_access_from_current_website():
|
|
raise werkzeug.exceptions.NotFound()
|
|
|
|
Attendees = request.env['event.registration']
|
|
registrations = self._process_registration_details(post)
|
|
|
|
for registration in registrations:
|
|
registration['event_id'] = event
|
|
Attendees += Attendees.sudo().create(
|
|
Attendees._prepare_attendee_values(registration))
|
|
|
|
urls = event._get_event_resource_urls(Attendees.ids)
|
|
return request.render("website_event.registration_complete", {
|
|
'attendees': Attendees.sudo(),
|
|
'event': event,
|
|
'google_url': urls.get('google_url'),
|
|
'iCal_url': urls.get('iCal_url')
|
|
})
|
|
|
|
@http.route(['''/event/<model("event.event", "[('website_id', 'in', (False, current_website_id))]"):event>/ics'''], type='http', auth="public", website=True)
|
|
def make_event_ics_file(self, event, **kwargs):
|
|
if not event or not event.registration_ids:
|
|
return request.not_found()
|
|
files = event._get_ics_file()
|
|
content = files[event.id]
|
|
return request.make_response(content, [
|
|
('Content-Type', 'application/octet-stream'),
|
|
('Content-Length', len(content)),
|
|
('Content-Disposition', content_disposition('%s.ics' % event.name))
|
|
])
|