agenda: factorize code to compute min/max_booking_time (#52227)
This commit is contained in:
parent
b7f1a2c5ec
commit
918d2c2339
|
@ -505,6 +505,42 @@ class Agenda(models.Model):
|
|||
for weektime_interval in IntervalSet.simple(*time_period_interval) - closed_hours_by_days:
|
||||
yield SharedTimePeriod.from_weektime_interval(weektime_interval, desks=desks)
|
||||
|
||||
@property
|
||||
def max_booking_datetime(self):
|
||||
if self.maximal_booking_delay is None:
|
||||
return None
|
||||
|
||||
# compute middle of today with localtime
|
||||
# 28 Mar 2021 12:00 +01:00
|
||||
t = localtime(now()).replace(hour=12, minute=0)
|
||||
# advance of self.maximal_booking_delay - 1 days
|
||||
# 28 Mar 2021 12:00 +01:00 == 28 Mars 2021 13:00 +02:00 as DST happend on 28 Mar 2021.
|
||||
t += datetime.timedelta(days=self.maximal_booking_delay)
|
||||
# move to midnight of the day before, DST happen between 2h/3h so it
|
||||
# always exists because +/- timedelta does not move the timezone, only
|
||||
# localtime() does it.
|
||||
# 27 Mar 2021 12:00 +01:00 == 28 Mars 2021 01:00 +02:00
|
||||
t = t.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
return localtime(t)
|
||||
|
||||
@property
|
||||
def min_booking_datetime(self):
|
||||
if self.minimal_booking_delay is None:
|
||||
return None
|
||||
|
||||
# compute middle of today with localtime
|
||||
# 28 Mar 2021 12:00 +01:00
|
||||
t = localtime(now()).replace(hour=12, minute=0)
|
||||
# advance of self.maximal_booking_delay - 1 days
|
||||
# 28 Mar 2021 12:00 +01:00 == 28 Mars 2021 13:00 +02:00 as DST happend on 28 Mar 2021.
|
||||
t += datetime.timedelta(days=self.minimal_booking_delay)
|
||||
# move to midnight of the day before, DST happen between 2h/3h so it
|
||||
# always exists because +/- timedelta does not move the timezone, only
|
||||
# localtime() does it.
|
||||
# 27 Mar 2021 12:00 +01:00 == 28 Mars 2021 01:00 +02:00
|
||||
t = t.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
return localtime(t)
|
||||
|
||||
def get_open_events(
|
||||
self,
|
||||
prefetched_queryset=False,
|
||||
|
@ -533,10 +569,7 @@ class Agenda(models.Model):
|
|||
entries = entries.filter(Q(full=False) | Q(primary_event__isnull=False))
|
||||
|
||||
if self.minimal_booking_delay:
|
||||
min_booking_time = localtime(now() + datetime.timedelta(days=self.minimal_booking_delay)).replace(
|
||||
hour=0, minute=0
|
||||
)
|
||||
min_start = max(min_booking_time, min_start) if min_start else min_booking_time
|
||||
min_start = max(self.min_booking_datetime, min_start) if min_start else self.min_booking_datetime
|
||||
|
||||
if min_start:
|
||||
if prefetched_queryset:
|
||||
|
@ -545,10 +578,7 @@ class Agenda(models.Model):
|
|||
entries = entries.filter(start_datetime__gte=min_start)
|
||||
|
||||
if self.maximal_booking_delay:
|
||||
max_booking_time = localtime(now() + datetime.timedelta(days=self.maximal_booking_delay)).replace(
|
||||
hour=0, minute=0
|
||||
)
|
||||
max_start = min(max_booking_time, max_start) if max_start else max_booking_time
|
||||
max_start = min(self.max_booking_datetime, max_start) if max_start else self.max_booking_datetime
|
||||
|
||||
if max_start:
|
||||
if prefetched_queryset:
|
||||
|
@ -1111,16 +1141,12 @@ class Event(models.Model):
|
|||
def in_bookable_period(self):
|
||||
if self.publication_date and localtime(now()).date() < self.publication_date:
|
||||
return False
|
||||
today = localtime(now()).date()
|
||||
event_day = localtime(self.start_datetime).date()
|
||||
days_to_event = event_day - today
|
||||
if self.agenda.maximal_booking_delay:
|
||||
if days_to_event >= datetime.timedelta(days=self.agenda.maximal_booking_delay):
|
||||
return False
|
||||
if self.agenda.maximal_booking_delay and self.start_datetime > self.agenda.max_booking_datetime:
|
||||
return False
|
||||
if self.recurrence_rule is not None:
|
||||
# bookable recurrences probably exist
|
||||
return True
|
||||
if days_to_event < datetime.timedelta(days=self.agenda.minimal_booking_delay):
|
||||
if self.agenda.minimal_booking_delay and self.start_datetime < self.agenda.min_booking_datetime:
|
||||
return False
|
||||
if self.start_datetime < now():
|
||||
# past the event date, we may want in the future to allow for some
|
||||
|
|
|
@ -50,22 +50,18 @@ def get_min_datetime(agenda, start_datetime=None):
|
|||
if agenda.minimal_booking_delay is None:
|
||||
return start_datetime
|
||||
|
||||
min_datetime = localtime(now()) + datetime.timedelta(days=agenda.minimal_booking_delay)
|
||||
min_datetime = min_datetime.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
if start_datetime is None:
|
||||
return min_datetime
|
||||
return max(min_datetime, start_datetime)
|
||||
return agenda.min_booking_datetime
|
||||
return max(agenda.min_booking_datetime, start_datetime)
|
||||
|
||||
|
||||
def get_max_datetime(agenda, end_datetime=None):
|
||||
if agenda.maximal_booking_delay is None:
|
||||
return end_datetime
|
||||
|
||||
max_datetime = localtime(now()) + datetime.timedelta(days=agenda.maximal_booking_delay)
|
||||
max_datetime = max_datetime.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
if end_datetime is None:
|
||||
return max_datetime
|
||||
return min(max_datetime, end_datetime)
|
||||
return agenda.max_booking_datetime
|
||||
return min(agenda.max_booking_datetime, end_datetime)
|
||||
|
||||
|
||||
TimeSlot = collections.namedtuple('TimeSlot', ['start_datetime', 'end_datetime', 'full', 'desk'])
|
||||
|
|
|
@ -6045,3 +6045,23 @@ def test_recurring_events_api_various_times(app, user, mock_now):
|
|||
|
||||
new_event = Booking.objects.get(pk=resp.json['booking_id']).event
|
||||
assert event.start_datetime == new_event.start_datetime
|
||||
|
||||
|
||||
def test_datetimes_dst(app, freezer):
|
||||
agenda = Agenda.objects.create(
|
||||
label='Foo bar', kind='events', minimal_booking_delay=0, maximal_booking_delay=10
|
||||
)
|
||||
event = Event.objects.create(
|
||||
slug='event-slug',
|
||||
start_datetime=make_aware(datetime.datetime(2021, 3, 28, 12, 30)),
|
||||
places=5,
|
||||
agenda=agenda,
|
||||
)
|
||||
|
||||
freezer.move_to('Fri, 18 Mar 2021 23:59:39 +0100')
|
||||
|
||||
# maximal_booking_delay is 10days so last bookable event is on
|
||||
# 2021-03-28T00:00, so event should not be bookable
|
||||
assert not event.in_bookable_period()
|
||||
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
|
||||
assert len(resp.json['data']) == 0
|
||||
|
|
Loading…
Reference in New Issue