This commit refactors mail.thread message_subscribe method. It is done for two purposes. First one is to optimize performance by using the new followers computation methods introduced recently. Second purpose is to clean the API of message_subscribe to make it simpler to use. This commit splits message_subscribe in two main parts : * _message_subscribe is a private method calling the follower new subscription methods and updating the record set; * message_subscribe is a public wrapper on _message_subscribe that adds access rights checks; Simplification comes by removing message_subscribe_users that was a shortcut to message_subscribe. Having a method to subscribe partners and channels is sufficient as we would like to avoid bloating the public API of mail.thread. A force parameter is also removed from message_subscribe as this implementation detail can be induced in the computation. Various addons using the removed methods are updated in order to use the new subscription API. They have the same functional behavior. This commit has a great impact when subscribing several followers. In a more general way all code using message_post is also optimized as posting a message generally implies subscribing followers. It also improves activity use as posting a message and subscribing new followers are common process in activities.
144 lines
6.4 KiB
Python
144 lines
6.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import babel
|
|
import collections
|
|
import datetime
|
|
import pytz
|
|
|
|
from odoo import fields, http
|
|
from odoo.http import request
|
|
from odoo.tools import html_escape as escape, html2plaintext
|
|
|
|
|
|
class WebsiteEventTrackController(http.Controller):
|
|
|
|
@http.route(['''/event/<model("event.event"):event>/track/<model("event.track", "[('event_id','=',event[0])]"):track>'''], type='http', auth="public", website=True)
|
|
def event_track_view(self, event, track, **post):
|
|
track = track.sudo().with_context(tz=event.date_tz or 'UTC')
|
|
values = {'track': track, 'event': track.event_id, 'main_object': track}
|
|
return request.render("website_event_track.track_view", values)
|
|
|
|
def _get_locale_time(self, dt_time, lang_code):
|
|
""" Get locale time from datetime object
|
|
|
|
:param dt_time: datetime object
|
|
:param lang_code: language code (eg. en_US)
|
|
"""
|
|
locale = babel.Locale.parse(lang_code)
|
|
return babel.dates.format_time(dt_time, format='short', locale=locale)
|
|
|
|
def _prepare_calendar(self, event, event_track_ids):
|
|
local_tz = pytz.timezone(event.date_tz or 'UTC')
|
|
lang_code = request.env.context.get('lang')
|
|
locations = {} # { location: [track, start_date, end_date, rowspan]}
|
|
dates = [] # [ (date, {}) ]
|
|
for track in event_track_ids:
|
|
locations.setdefault(track.location_id or False, [])
|
|
|
|
forcetr = True
|
|
for track in event_track_ids:
|
|
start_date = fields.Datetime.from_string(track.date).replace(tzinfo=pytz.utc).astimezone(local_tz)
|
|
end_date = start_date + datetime.timedelta(hours=(track.duration or 0.5))
|
|
location = track.location_id or False
|
|
locations.setdefault(location, [])
|
|
|
|
# New TR, align all events
|
|
if forcetr or (start_date>dates[-1][0]) or not location:
|
|
formatted_time = self._get_locale_time(start_date, lang_code)
|
|
dates.append((start_date, {}, bool(location), formatted_time))
|
|
for loc in list(locations):
|
|
if locations[loc] and (locations[loc][-1][2] > start_date):
|
|
locations[loc][-1][3] += 1
|
|
elif not locations[loc] or locations[loc][-1][2] <= start_date:
|
|
locations[loc].append([False, locations[loc] and locations[loc][-1][2] or dates[0][0], start_date, 1])
|
|
dates[-1][1][loc] = locations[loc][-1]
|
|
forcetr = not bool(location)
|
|
|
|
# Add event
|
|
if locations[location] and locations[location][-1][1] > start_date:
|
|
locations[location][-1][3] -= 1
|
|
locations[location].append([track, start_date, end_date, 1])
|
|
dates[-1][1][location] = locations[location][-1]
|
|
return {
|
|
'locations': locations,
|
|
'dates': dates
|
|
}
|
|
|
|
@http.route(['''/event/<model("event.event"):event>/agenda'''], type='http', auth="public", website=True, sitemap=False)
|
|
def event_agenda(self, event, tag=None, **post):
|
|
event = event.with_context(tz=event.date_tz or 'UTC')
|
|
local_tz = pytz.timezone(event.date_tz or 'UTC')
|
|
days_tracks = collections.defaultdict(lambda: [])
|
|
for track in event.track_ids.sorted(lambda track: (track.date or '', bool(track.location_id))):
|
|
if not track.date:
|
|
continue
|
|
date = fields.Datetime.from_string(track.date).replace(tzinfo=pytz.utc).astimezone(local_tz)
|
|
days_tracks[str(date)[:10]].append(track)
|
|
|
|
days = {}
|
|
tracks_by_days = {}
|
|
for day, tracks in days_tracks.items():
|
|
tracks_by_days[day] = tracks
|
|
days[day] = self._prepare_calendar(event, tracks)
|
|
|
|
return request.render("website_event_track.agenda", {
|
|
'event': event,
|
|
'days': days,
|
|
'tracks_by_days': tracks_by_days,
|
|
'tag': tag
|
|
})
|
|
|
|
@http.route([
|
|
'''/event/<model("event.event"):event>/track''',
|
|
'''/event/<model("event.event"):event>/track/tag/<model("event.track.tag"):tag>'''
|
|
], type='http', auth="public", website=True, sitemap=False)
|
|
def event_tracks(self, event, tag=None, **post):
|
|
event = event.with_context(tz=event.date_tz or 'UTC')
|
|
searches = {}
|
|
if tag:
|
|
searches.update(tag=tag.id)
|
|
tracks = event.track_ids.filtered(lambda track: tag in track.tag_ids)
|
|
else:
|
|
tracks = event.track_ids
|
|
|
|
values = {
|
|
'event': event,
|
|
'main_object': event,
|
|
'tracks': tracks,
|
|
'tags': event.tracks_tag_ids,
|
|
'searches': searches,
|
|
'html2plaintext': html2plaintext
|
|
}
|
|
return request.render("website_event_track.tracks", values)
|
|
|
|
@http.route(['''/event/<model("event.event"):event>/track_proposal'''], type='http', auth="public", website=True, sitemap=False)
|
|
def event_track_proposal(self, event, **post):
|
|
return request.render("website_event_track.event_track_proposal", {'event': event})
|
|
|
|
@http.route(['/event/<model("event.event"):event>/track_proposal/post'], type='http', auth="public", methods=['POST'], website=True)
|
|
def event_track_proposal_post(self, event, **post):
|
|
tags = []
|
|
for tag in event.allowed_track_tag_ids:
|
|
if post.get('tag_' + str(tag.id)):
|
|
tags.append(tag.id)
|
|
|
|
track = request.env['event.track'].sudo().create({
|
|
'name': post['track_name'],
|
|
'partner_name': post['partner_name'],
|
|
'partner_email': post['email_from'],
|
|
'partner_phone': post['phone'],
|
|
'partner_biography': escape(post['biography']),
|
|
'event_id': event.id,
|
|
'tag_ids': [(6, 0, tags)],
|
|
'user_id': False,
|
|
'description': escape(post['description'])
|
|
})
|
|
if request.env.user != request.website.user_id:
|
|
track.sudo().message_subscribe(partner_ids=request.env.user.partner_id.ids)
|
|
else:
|
|
partner = request.env['res.partner'].sudo().search([('email', '=', post['email_from'])])
|
|
if partner:
|
|
track.sudo().message_subscribe(partner_ids=partner.ids)
|
|
return request.render("website_event_track.event_track_proposal_success", {'track': track, 'event': event})
|