forked from rc/aircox
fix diff update/delete on schedule change; fix match algorithms
This commit is contained in:
parent
28dab0185a
commit
a0968d35f6
|
@ -527,7 +527,8 @@ class Schedule(models.Model):
|
||||||
This is needed since datetime are stored as UTC date and we want
|
This is needed since datetime are stored as UTC date and we want
|
||||||
to get it as local time.
|
to get it as local time.
|
||||||
"""
|
"""
|
||||||
if not hasattr(self, '_local_date') or self._tz.zone != self.timezone:
|
if not hasattr(self, '_local_date') or \
|
||||||
|
self.changed(fields = ('timezone','date')):
|
||||||
self._local_date = tz.localtime(self.date, self.tz)
|
self._local_date = tz.localtime(self.date, self.tz)
|
||||||
return self._local_date
|
return self._local_date
|
||||||
|
|
||||||
|
@ -549,7 +550,7 @@ class Schedule(models.Model):
|
||||||
# initial cached data
|
# initial cached data
|
||||||
__initial = None
|
__initial = None
|
||||||
|
|
||||||
def changed(self, fields = ['date','duration','frequency']):
|
def changed(self, fields = ['date','duration','frequency','timezone']):
|
||||||
initial = self._Schedule__initial
|
initial = self._Schedule__initial
|
||||||
if not initial:
|
if not initial:
|
||||||
return
|
return
|
||||||
|
@ -573,9 +574,17 @@ class Schedule(models.Model):
|
||||||
Return True if the given datetime matches the schedule
|
Return True if the given datetime matches the schedule
|
||||||
"""
|
"""
|
||||||
date = utils.date_or_default(date)
|
date = utils.date_or_default(date)
|
||||||
if self.date.weekday() == date.weekday() and self.match_week(date):
|
print('match...', date, self.date, self.match_week(date), self.date.weekday() == date.weekday())
|
||||||
return self.date.time() == date.time() if check_time else True
|
if self.date.weekday() != date.weekday() or not self.match_week(date):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
if not check_time:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# we check against a normalized version (norm_date will have
|
||||||
|
# schedule's date.
|
||||||
|
norm_date = self.normalize(date)
|
||||||
|
return date == norm_date
|
||||||
|
|
||||||
def match_week(self, date = None):
|
def match_week(self, date = None):
|
||||||
"""
|
"""
|
||||||
|
@ -601,13 +610,13 @@ class Schedule(models.Model):
|
||||||
# weeks of month
|
# weeks of month
|
||||||
if week == 4:
|
if week == 4:
|
||||||
# fifth week: return if for every week
|
# fifth week: return if for every week
|
||||||
return self.frequency == 0b1111
|
return self.frequency == self.Frequency.every
|
||||||
return (self.frequency & (0b0001 << week) > 0)
|
return (self.frequency & (0b0001 << week) > 0)
|
||||||
|
|
||||||
def normalize(self, date):
|
def normalize(self, date):
|
||||||
"""
|
"""
|
||||||
Set the time of a datetime to the schedule's one
|
Return a new datetime with schedule time. Timezone is handled
|
||||||
Ensure timezone awareness.
|
using `schedule.timezone`.
|
||||||
"""
|
"""
|
||||||
local_date = self.local_date
|
local_date = self.local_date
|
||||||
date = tz.datetime(date.year, date.month, date.day,
|
date = tz.datetime(date.year, date.month, date.day,
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
from django.db.models.signals import post_save, pre_save, pre_delete, m2m_changed
|
import pytz
|
||||||
from django.contrib.auth.models import User, Group, Permission
|
|
||||||
|
|
||||||
from django.dispatch import receiver
|
from django.contrib.auth.models import User, Group, Permission
|
||||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
from django.db.models import F
|
||||||
|
from django.db.models.signals import post_save, pre_save, pre_delete, m2m_changed
|
||||||
|
from django.dispatch import receiver
|
||||||
|
from django.utils import timezone as tz
|
||||||
|
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||||
|
|
||||||
import aircox.models as models
|
import aircox.models as models
|
||||||
import aircox.utils as utils
|
import aircox.utils as utils
|
||||||
|
@ -36,9 +39,10 @@ def user_default_groups(sender, instance, created, *args, **kwargs):
|
||||||
|
|
||||||
# FIXME: avoid copy of the code in schedule_post_saved and
|
# FIXME: avoid copy of the code in schedule_post_saved and
|
||||||
# schedule_pre_delete
|
# schedule_pre_delete
|
||||||
|
|
||||||
@receiver(post_save, sender=models.Schedule)
|
@receiver(post_save, sender=models.Schedule)
|
||||||
def schedule_post_saved(sender, instance, created, *args, **kwargs):
|
def schedule_post_saved(sender, instance, created, *args, **kwargs):
|
||||||
# TODO: case instance.program has changed
|
# TODO: case instance.program | instance.frequency has changed
|
||||||
if not instance.program.sync:
|
if not instance.program.sync:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -46,29 +50,28 @@ def schedule_post_saved(sender, instance, created, *args, **kwargs):
|
||||||
if not initial or not instance.changed(['date','duration', 'frequency']):
|
if not initial or not instance.changed(['date','duration', 'frequency']):
|
||||||
return
|
return
|
||||||
|
|
||||||
if not initial.get('date') or not initial.get('duration') or not initial.get('frequency'):
|
if not initial.get('date') or not initial.get('duration') \
|
||||||
|
or not initial.get('frequency'):
|
||||||
return
|
return
|
||||||
|
|
||||||
# old schedule and timedelta
|
# old schedule and timedelta
|
||||||
old_sched = models.Schedule(
|
old = models.Schedule(**{ key: initial.get(key)
|
||||||
program = instance.program,
|
for key in ('date','timezone','duration','frequency')
|
||||||
date = initial['date'],
|
})
|
||||||
duration = initial['duration'],
|
start_delta = instance.local_date - old.local_date
|
||||||
frequency = initial['frequency'],
|
|
||||||
)
|
|
||||||
delta = instance.date - old_sched.date
|
|
||||||
|
|
||||||
# update diffusions...
|
old.date = old.local_date.astimezone(pytz.UTC)
|
||||||
qs = models.Diffusion.objects.after(
|
|
||||||
|
qs = models.Diffusion.objects.station(
|
||||||
instance.program.station,
|
instance.program.station,
|
||||||
program = instance.program
|
|
||||||
)
|
)
|
||||||
for diff in qs:
|
|
||||||
if not old_sched.match(diff.date):
|
pks = [ item.pk for item in qs if old.match(item.date) ]
|
||||||
continue
|
qs.filter(pk__in = pks).update(
|
||||||
diff.start += delta
|
start = F('start') + start_delta,
|
||||||
diff.end = diff.start + utils.to_timedelta(instance.duration)
|
end = F('start') + start_delta + utils.to_timedelta(instance.duration)
|
||||||
diff.save()
|
)
|
||||||
|
return
|
||||||
|
|
||||||
@receiver(pre_delete, sender=models.Schedule)
|
@receiver(pre_delete, sender=models.Schedule)
|
||||||
def schedule_pre_delete(sender, instance, *args, **kwargs):
|
def schedule_pre_delete(sender, instance, *args, **kwargs):
|
||||||
|
@ -79,17 +82,14 @@ def schedule_pre_delete(sender, instance, *args, **kwargs):
|
||||||
if not initial or not instance.changed(['date','duration', 'frequency']):
|
if not initial or not instance.changed(['date','duration', 'frequency']):
|
||||||
return
|
return
|
||||||
|
|
||||||
old_sched = models.Schedule(
|
old = models.Schedule(**{ key: initial.get(key)
|
||||||
date = initial['date'],
|
for key in ('date','timezone','duration','frequency')
|
||||||
duration = initial['duration'],
|
})
|
||||||
frequency = initial['frequency'],
|
|
||||||
|
qs = models.Diffusion.objects.station(
|
||||||
|
instance.program.station,
|
||||||
)
|
)
|
||||||
|
|
||||||
qs = models.Diffusion.objects.after(instance.program.station).filter(
|
pks = [ item.pk for item in qs if old.match(item.date) ]
|
||||||
program = instance.program
|
qs.filter(pk__in = pks).delete()
|
||||||
)
|
|
||||||
for diff in qs:
|
|
||||||
if not old_sched.match(diff.date):
|
|
||||||
continue
|
|
||||||
diff.delete()
|
|
||||||
|
|
||||||
|
|
|
@ -277,13 +277,14 @@ class BaseList(models.Model):
|
||||||
|
|
||||||
def __get_related(self, qs):
|
def __get_related(self, qs):
|
||||||
related = self.related and self.related.specific
|
related = self.related and self.related.specific
|
||||||
|
|
||||||
filter = self.RelationFilter
|
filter = self.RelationFilter
|
||||||
|
|
||||||
if self.relation in (filter.subpages, filter.subpages_or_siblings):
|
if self.relation in (filter.subpages, filter.subpages_or_siblings):
|
||||||
qs = qs.descendant_of(related)
|
qs_ = qs.descendant_of(related)
|
||||||
if not qs.count() and self.relation == filter.subpages_or_siblings:
|
if self.relation == filter.subpages_or_siblings and \
|
||||||
qs = qs.sibling_of(related)
|
not qs.count():
|
||||||
|
qs_ = qs.sibling_of(related)
|
||||||
|
qs = qs_
|
||||||
else:
|
else:
|
||||||
qs = qs.sibling_of(related)
|
qs = qs.sibling_of(related)
|
||||||
|
|
||||||
|
@ -393,7 +394,7 @@ class BaseList(models.Model):
|
||||||
'asc': self.asc,
|
'asc': self.asc,
|
||||||
'date_filter': self.get_date_filter_display(),
|
'date_filter': self.get_date_filter_display(),
|
||||||
'model': self.model and self.model.model,
|
'model': self.model and self.model.model,
|
||||||
'relation': self.get_relation_display(),
|
'relation': self.relation,
|
||||||
'search': self.search,
|
'search': self.search,
|
||||||
'tags': self.tags
|
'tags': self.tags
|
||||||
}
|
}
|
||||||
|
@ -437,7 +438,13 @@ class BaseList(models.Model):
|
||||||
"""
|
"""
|
||||||
date_filter = request.GET.get('date_filter')
|
date_filter = request.GET.get('date_filter')
|
||||||
model = request.GET.get('model')
|
model = request.GET.get('model')
|
||||||
|
|
||||||
relation = request.GET.get('relation')
|
relation = request.GET.get('relation')
|
||||||
|
if relation is not None:
|
||||||
|
try:
|
||||||
|
relation = int(relation)
|
||||||
|
except:
|
||||||
|
relation = None
|
||||||
|
|
||||||
related_= request.GET.get('related')
|
related_= request.GET.get('related')
|
||||||
if related_:
|
if related_:
|
||||||
|
@ -459,10 +466,7 @@ class BaseList(models.Model):
|
||||||
DiffusionPage if model == 'diffusion' else
|
DiffusionPage if model == 'diffusion' else
|
||||||
EventPage if model == 'event' else None,
|
EventPage if model == 'event' else None,
|
||||||
'related': related_,
|
'related': related_,
|
||||||
'relation':
|
'relation': relation,
|
||||||
int(getattr(cl.RelationFilter, relation))
|
|
||||||
if relation and hasattr(cl.RelationFilter, relation)
|
|
||||||
else None,
|
|
||||||
'tags': request.GET.get('tags'),
|
'tags': request.GET.get('tags'),
|
||||||
'search': request.GET.get('search'),
|
'search': request.GET.get('search'),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user