[ADD]: Added Upstream Patch for calendar.
This commit is contained in:
parent
804235226e
commit
7cf60bc315
@ -4,7 +4,7 @@ import base64
|
|||||||
|
|
||||||
import babel.dates
|
import babel.dates
|
||||||
import collections
|
import collections
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, MAXYEAR
|
||||||
from dateutil import parser
|
from dateutil import parser
|
||||||
from dateutil import rrule
|
from dateutil import rrule
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
@ -608,7 +608,8 @@ class Meeting(models.Model):
|
|||||||
if not event_date:
|
if not event_date:
|
||||||
event_date = datetime.now()
|
event_date = datetime.now()
|
||||||
|
|
||||||
if self.allday and self.rrule and 'UNTIL' in self.rrule and 'Z' not in self.rrule:
|
use_naive_datetime = self.allday and self.rrule and 'UNTIL' in self.rrule and 'Z' not in self.rrule
|
||||||
|
if use_naive_datetime:
|
||||||
rset1 = rrule.rrulestr(str(self.rrule), dtstart=event_date.replace(tzinfo=None), forceset=True, ignoretz=True)
|
rset1 = rrule.rrulestr(str(self.rrule), dtstart=event_date.replace(tzinfo=None), forceset=True, ignoretz=True)
|
||||||
else:
|
else:
|
||||||
# Convert the event date to saved timezone (or context tz) as it'll
|
# Convert the event date to saved timezone (or context tz) as it'll
|
||||||
@ -617,9 +618,21 @@ class Meeting(models.Model):
|
|||||||
rset1 = rrule.rrulestr(str(self.rrule), dtstart=event_date, forceset=True, tzinfos={})
|
rset1 = rrule.rrulestr(str(self.rrule), dtstart=event_date, forceset=True, tzinfos={})
|
||||||
recurring_meetings = self.search([('recurrent_id', '=', self.id), '|', ('active', '=', False), ('active', '=', True)])
|
recurring_meetings = self.search([('recurrent_id', '=', self.id), '|', ('active', '=', False), ('active', '=', True)])
|
||||||
|
|
||||||
for meeting in recurring_meetings:
|
# We handle a maximum of 50,000 meetings at a time, and clear the cache at each step to
|
||||||
rset1._exdate.append(todate(meeting.recurrent_id_date))
|
# control the memory usage.
|
||||||
return [d.astimezone(pytz.UTC) if d.tzinfo else d for d in rset1]
|
invalidate = False
|
||||||
|
for meetings in self.env.cr.split_for_in_conditions(recurring_meetings, size=50000):
|
||||||
|
if invalidate:
|
||||||
|
self.invalidate_cache()
|
||||||
|
for meeting in meetings:
|
||||||
|
recurring_date = fields.Datetime.from_string(meeting.recurrent_id_date)
|
||||||
|
if use_naive_datetime:
|
||||||
|
recurring_date = recurring_date.replace(tzinfo=None)
|
||||||
|
else:
|
||||||
|
recurring_date = todate(meeting.recurrent_id_date)
|
||||||
|
rset1.exdate(recurring_date)
|
||||||
|
invalidate = True
|
||||||
|
return [d.astimezone(pytz.UTC) if d.tzinfo else d for d in rset1 if d.year < MAXYEAR]
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _get_recurrency_end_date(self):
|
def _get_recurrency_end_date(self):
|
||||||
@ -642,7 +655,13 @@ class Meeting(models.Model):
|
|||||||
}[data['rrule_type']]
|
}[data['rrule_type']]
|
||||||
|
|
||||||
deadline = fields.Datetime.from_string(data['stop'])
|
deadline = fields.Datetime.from_string(data['stop'])
|
||||||
return deadline + relativedelta(**{delay: count * mult})
|
computed_final_date = False
|
||||||
|
while not computed_final_date and count > 0:
|
||||||
|
try: # may crash if year > 9999 (in case of recurring events)
|
||||||
|
computed_final_date = deadline + relativedelta(**{delay: count * mult})
|
||||||
|
except ValueError:
|
||||||
|
count -= data['interval']
|
||||||
|
return computed_final_date or deadline
|
||||||
return final_date
|
return final_date
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@ -883,8 +902,8 @@ class Meeting(models.Model):
|
|||||||
startdate = startdate.astimezone(pytz.utc) # Convert to UTC
|
startdate = startdate.astimezone(pytz.utc) # Convert to UTC
|
||||||
meeting.start = fields.Datetime.to_string(startdate)
|
meeting.start = fields.Datetime.to_string(startdate)
|
||||||
else:
|
else:
|
||||||
meeting.start = meeting.start_datetime
|
meeting.write({'start': meeting.start_datetime,
|
||||||
meeting.stop = meeting.stop_datetime
|
'stop': meeting.stop_datetime})
|
||||||
|
|
||||||
@api.depends('byday', 'recurrency', 'final_date', 'rrule_type', 'month_by', 'interval', 'count', 'end_type', 'mo', 'tu', 'we', 'th', 'fr', 'sa', 'su', 'day', 'week_list')
|
@api.depends('byday', 'recurrency', 'final_date', 'rrule_type', 'month_by', 'interval', 'count', 'end_type', 'mo', 'tu', 'we', 'th', 'fr', 'sa', 'su', 'day', 'week_list')
|
||||||
def _compute_rrule(self):
|
def _compute_rrule(self):
|
||||||
@ -910,9 +929,13 @@ class Meeting(models.Model):
|
|||||||
def _check_closing_date(self):
|
def _check_closing_date(self):
|
||||||
for meeting in self:
|
for meeting in self:
|
||||||
if meeting.start_datetime and meeting.stop_datetime and meeting.stop_datetime < meeting.start_datetime:
|
if meeting.start_datetime and meeting.stop_datetime and meeting.stop_datetime < meeting.start_datetime:
|
||||||
raise ValidationError(_('Ending datetime cannot be set before starting datetime.'))
|
raise ValidationError(_('Ending datetime cannot be set before starting datetime.') + "\n" +
|
||||||
|
_("Meeting '%s' starts '%s' and ends '%s'") % (meeting.name, meeting.start_datetime, meeting.stop_datetime)
|
||||||
|
)
|
||||||
if meeting.start_date and meeting.stop_date and meeting.stop_date < meeting.start_date:
|
if meeting.start_date and meeting.stop_date and meeting.stop_date < meeting.start_date:
|
||||||
raise ValidationError(_('Ending date cannot be set before starting date.'))
|
raise ValidationError(_('Ending date cannot be set before starting date.') + "\n" +
|
||||||
|
_("Meeting '%s' starts '%s' and ends '%s'") % (meeting.name, meeting.start_date, meeting.stop_date)
|
||||||
|
)
|
||||||
|
|
||||||
@api.onchange('start_datetime', 'duration')
|
@api.onchange('start_datetime', 'duration')
|
||||||
def _onchange_duration(self):
|
def _onchange_duration(self):
|
||||||
@ -1141,9 +1164,15 @@ class Meeting(models.Model):
|
|||||||
for key in (order or self._order).split(',')
|
for key in (order or self._order).split(',')
|
||||||
))
|
))
|
||||||
def key(record):
|
def key(record):
|
||||||
|
# we need to deal with undefined fields, as sorted requires an homogeneous iterable
|
||||||
|
def boolean_product(x):
|
||||||
|
x = False if (isinstance(x, models.Model) and not x) else x
|
||||||
|
if isinstance(x, bool):
|
||||||
|
return (x, x)
|
||||||
|
return (True, x)
|
||||||
# first extract the values for each key column (ids need special treatment)
|
# first extract the values for each key column (ids need special treatment)
|
||||||
vals_spec = (
|
vals_spec = (
|
||||||
(any_id2key(record[name]) if name == 'id' else record[name], desc)
|
(any_id2key(record[name]) if name == 'id' else boolean_product(record[name]), desc)
|
||||||
for name, desc in sort_spec
|
for name, desc in sort_spec
|
||||||
)
|
)
|
||||||
# then Reverse if the value matches a "desc" column
|
# then Reverse if the value matches a "desc" column
|
||||||
@ -1218,7 +1247,12 @@ class Meeting(models.Model):
|
|||||||
def _rrule_parse(self, rule_str, data, date_start):
|
def _rrule_parse(self, rule_str, data, date_start):
|
||||||
day_list = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
|
day_list = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
|
||||||
rrule_type = ['yearly', 'monthly', 'weekly', 'daily']
|
rrule_type = ['yearly', 'monthly', 'weekly', 'daily']
|
||||||
rule = rrule.rrulestr(rule_str, dtstart=fields.Datetime.from_string(date_start))
|
ddate = fields.Datetime.from_string(date_start)
|
||||||
|
if 'Z' in rule_str and not ddate.tzinfo:
|
||||||
|
ddate = ddate.replace(tzinfo=pytz.timezone('UTC'))
|
||||||
|
rule = rrule.rrulestr(rule_str, dtstart=ddate)
|
||||||
|
else:
|
||||||
|
rule = rrule.rrulestr(rule_str, dtstart=ddate)
|
||||||
|
|
||||||
if rule._freq > 0 and rule._freq < 4:
|
if rule._freq > 0 and rule._freq < 4:
|
||||||
data['rrule_type'] = rrule_type[rule._freq]
|
data['rrule_type'] = rrule_type[rule._freq]
|
||||||
|
@ -194,7 +194,6 @@
|
|||||||
<group>
|
<group>
|
||||||
<field name="privacy"/>
|
<field name="privacy"/>
|
||||||
<field name="show_as"/>
|
<field name="show_as"/>
|
||||||
<field name="rrule" invisible="1" readonly="0" />
|
|
||||||
<field name="recurrent_id" invisible="1" />
|
<field name="recurrent_id" invisible="1" />
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
|
Loading…
Reference in New Issue
Block a user