0001-agendas-factorize-recurrent-event-update-code-57305.patch
chrono/agendas/models.py | ||
---|---|---|
17 | 17 |
import collections |
18 | 18 |
import copy |
19 | 19 |
import datetime |
20 | 20 |
import functools |
21 | 21 |
import itertools |
22 | 22 |
import math |
23 | 23 |
import sys |
24 | 24 |
import uuid |
25 |
from contextlib import contextmanager |
|
25 | 26 | |
26 | 27 |
import requests |
27 | 28 |
import vobject |
28 | 29 |
from dateutil.rrule import DAILY, WEEKLY, rrule, rruleset |
29 | 30 |
from django.conf import settings |
30 | 31 |
from django.contrib.auth.models import Group |
31 | 32 |
from django.contrib.postgres.fields import ArrayField, JSONField |
32 | 33 |
from django.core.exceptions import FieldDoesNotExist, ValidationError |
... | ... | |
1404 | 1405 |
def save(self, seen_slugs=None, *args, **kwargs): |
1405 | 1406 |
assert self.agenda.kind != 'virtual', "an event can't reference a virtual agenda" |
1406 | 1407 |
assert not (self.slug and self.slug.isdigit()), 'slug cannot be a number' |
1407 | 1408 |
self.start_datetime = self.start_datetime.replace(second=0, microsecond=0) |
1408 | 1409 |
if not self.slug: |
1409 | 1410 |
self.slug = generate_slug(self, seen_slugs=seen_slugs, agenda=self.agenda) |
1410 | 1411 |
return super().save(*args, **kwargs) |
1411 | 1412 | |
1413 |
@contextmanager |
|
1414 |
def update_recurrences( |
|
1415 |
self, changed_data=None, cleaned_data=None, protected_fields=None, more_protected_fields=None |
|
1416 |
): |
|
1417 |
changed_data = changed_data or [] |
|
1418 |
cleaned_data = cleaned_data or {} |
|
1419 |
protected_fields = protected_fields or [] |
|
1420 |
more_protected_fields = more_protected_fields or [] |
|
1421 | ||
1422 |
with transaction.atomic(): |
|
1423 |
if any(field for field in changed_data if field in protected_fields): |
|
1424 |
self.recurrences.all().delete() |
|
1425 |
elif self.recurrence_days: |
|
1426 |
protected_fields = list(protected_fields) + more_protected_fields |
|
1427 |
update_fields = { |
|
1428 |
field: value for field, value in cleaned_data.items() if field not in protected_fields |
|
1429 |
} |
|
1430 |
self.recurrences.update(**update_fields) |
|
1431 |
yield |
|
1432 | ||
1433 |
if self.recurrence_end_date: |
|
1434 |
self.recurrences.filter(start_datetime__gt=self.recurrence_end_date).delete() |
|
1435 |
excluded_datetimes = [evt.datetime_slug for evt in self.recurrences.all()] |
|
1436 |
self.create_all_recurrences(excluded_datetimes) |
|
1437 | ||
1412 | 1438 |
@property |
1413 | 1439 |
def base_slug(self): |
1414 | 1440 |
# label can be empty |
1415 | 1441 |
return slugify(self.label or ('%s-event' % self.agenda.label)) |
1416 | 1442 | |
1417 | 1443 |
def main_list_full(self): |
1418 | 1444 |
return bool(self.booked_places >= self.places) |
1419 | 1445 |
chrono/manager/forms.py | ||
---|---|---|
19 | 19 |
import csv |
20 | 20 |
import datetime |
21 | 21 | |
22 | 22 |
import django_filters |
23 | 23 |
from django import forms |
24 | 24 |
from django.conf import settings |
25 | 25 |
from django.contrib.auth.models import Group |
26 | 26 |
from django.core.exceptions import FieldDoesNotExist |
27 |
from django.db import transaction |
|
28 | 27 |
from django.forms import ValidationError |
29 | 28 |
from django.utils.encoding import force_text |
30 | 29 |
from django.utils.six import StringIO |
31 | 30 |
from django.utils.timezone import make_aware, now |
32 | 31 |
from django.utils.translation import ugettext_lazy as _ |
33 | 32 | |
34 | 33 |
from chrono.agendas.models import ( |
35 | 34 |
WEEKDAYS_LIST, |
... | ... | |
275 | 274 |
): |
276 | 275 |
raise ValidationError(_('Bookings exist after this date.')) |
277 | 276 | |
278 | 277 |
if self.cleaned_data.get('frequency') == 'unique': |
279 | 278 |
self.cleaned_data['recurrence_days'] = None |
280 | 279 |
self.cleaned_data['recurrence_end_date'] = None |
281 | 280 | |
282 | 281 |
def save(self, *args, **kwargs): |
283 |
with transaction.atomic(): |
|
284 |
if any(field for field in self.changed_data if field in self.protected_fields): |
|
285 |
self.instance.recurrences.all().delete() |
|
286 |
elif self.instance.recurrence_days: |
|
287 |
protected_fields = list(self.protected_fields) + ['recurrence_end_date', 'frequency'] |
|
288 |
update_fields = { |
|
289 |
field: value |
|
290 |
for field, value in self.cleaned_data.items() |
|
291 |
if field not in protected_fields |
|
292 |
} |
|
293 |
self.instance.recurrences.update(**update_fields) |
|
294 | ||
282 |
with self.instance.update_recurrences( |
|
283 |
self.changed_data, self.cleaned_data, self.protected_fields, ['recurrence_end_date', 'frequency'] |
|
284 |
): |
|
295 | 285 |
super().save(*args, **kwargs) |
296 |
if self.instance.recurrence_end_date: |
|
297 |
self.instance.recurrences.filter( |
|
298 |
start_datetime__gt=self.instance.recurrence_end_date |
|
299 |
).delete() |
|
300 |
excluded_datetimes = [event.datetime_slug for event in self.instance.recurrences.all()] |
|
301 |
self.instance.create_all_recurrences(excluded_datetimes) |
|
302 | 286 |
return self.instance |
303 | 287 | |
304 | 288 | |
305 | 289 |
class BookingCheckFilterSet(django_filters.FilterSet): |
306 | 290 |
class Meta: |
307 | 291 |
model = Booking |
308 | 292 |
fields = [] |
309 | 293 | |
310 |
- |