550 lines
24 KiB
Python
550 lines
24 KiB
Python
import datetime
|
|
|
|
import pytest
|
|
from django.db import connection
|
|
from django.test.utils import CaptureQueriesContext
|
|
|
|
from chrono.agendas.models import Agenda, Booking, Event, EventsType
|
|
from chrono.utils.timezone import localtime, now
|
|
|
|
pytestmark = pytest.mark.django_db
|
|
|
|
|
|
@pytest.mark.freeze_time('2021-09-06 12:00')
|
|
def test_api_events_fillslots(app, user):
|
|
events_type = EventsType.objects.create(label='Foo')
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events', events_type=events_type)
|
|
event = Event.objects.create(
|
|
label='Event',
|
|
start_datetime=now() + datetime.timedelta(days=1),
|
|
places=2,
|
|
waiting_list_places=1,
|
|
agenda=agenda,
|
|
)
|
|
second_event = Event.objects.create(
|
|
label='Event 2', start_datetime=now() + datetime.timedelta(days=2), places=2, agenda=agenda
|
|
)
|
|
third_event = Event.objects.create(
|
|
label='Event 3', start_datetime=now() + datetime.timedelta(days=3), places=2, agenda=agenda
|
|
)
|
|
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
fillslots_url = '/api/agenda/%s/events/fillslots/' % agenda.slug
|
|
params = {'user_external_id': 'user_id', 'check_overlaps': True, 'slots': 'event,event-2'}
|
|
with CaptureQueriesContext(connection) as ctx:
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert len(ctx.captured_queries) == 12
|
|
assert resp.json['booking_count'] == 2
|
|
assert len(resp.json['booked_events']) == 2
|
|
assert resp.json['booked_events'][0]['id'] == 'event'
|
|
assert (
|
|
resp.json['booked_events'][0]['booking']['id'] == Booking.objects.filter(event=event).latest('pk').pk
|
|
)
|
|
assert resp.json['booked_events'][1]['id'] == 'event-2'
|
|
assert (
|
|
resp.json['booked_events'][1]['booking']['id']
|
|
== Booking.objects.filter(event=second_event).latest('pk').pk
|
|
)
|
|
assert len(resp.json['waiting_list_events']) == 0
|
|
|
|
events = Event.objects.all()
|
|
assert events.filter(booked_places=1).count() == 2
|
|
|
|
params['user_external_id'] = 'user_id_2'
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 2
|
|
assert len(resp.json['booked_events']) == 2
|
|
assert len(resp.json['waiting_list_events']) == 0
|
|
assert resp.json['booked_events'][0]['id'] == 'event'
|
|
assert (
|
|
resp.json['booked_events'][0]['booking']['id'] == Booking.objects.filter(event=event).latest('pk').pk
|
|
)
|
|
assert resp.json['booked_events'][1]['id'] == 'event-2'
|
|
assert (
|
|
resp.json['booked_events'][1]['booking']['id']
|
|
== Booking.objects.filter(event=second_event).latest('pk').pk
|
|
)
|
|
|
|
params['user_external_id'] = 'user_id_3'
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'some events are full: Event 2'
|
|
|
|
params['slots'] = 'event'
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 1
|
|
assert len(resp.json['booked_events']) == 0
|
|
assert len(resp.json['waiting_list_events']) == 1
|
|
assert resp.json['waiting_list_events'][0]['slug'] == event.slug
|
|
assert (
|
|
resp.json['waiting_list_events'][0]['booking']['id']
|
|
== Booking.objects.filter(event=event).latest('pk').pk
|
|
)
|
|
assert Booking.objects.filter(in_waiting_list=True, event=event).count() == 1
|
|
|
|
# change bookings
|
|
params = {'user_external_id': 'user_id', 'slots': 'event-2,event-3'}
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 1
|
|
assert resp.json['cancelled_booking_count'] == 1
|
|
|
|
user_bookings = Booking.objects.filter(user_external_id='user_id', cancellation_datetime__isnull=True)
|
|
assert {b.event.slug for b in user_bookings} == {'event-2', 'event-3'}
|
|
assert event.booking_set.filter(cancellation_datetime__isnull=True).count() == 2
|
|
assert second_event.booking_set.count() == 2
|
|
assert third_event.booking_set.count() == 1
|
|
|
|
# increase waiting_list_places to make "Event" bookable again
|
|
event.waiting_list_places = 2
|
|
event.save()
|
|
|
|
# specify time range so that "Event 3" is not cancelled
|
|
params['slots'] = 'event,event-2'
|
|
resp = app.post_json(fillslots_url + '?date_start=2021-09-06&date_end=2021-09-09', params=params)
|
|
assert resp.json['booking_count'] == 1
|
|
assert resp.json['cancelled_booking_count'] == 0
|
|
|
|
user_bookings = Booking.objects.filter(user_external_id='user_id')
|
|
assert {b.event.slug for b in user_bookings} == {'event', 'event-2', 'event-3'}
|
|
assert event.booking_set.count() == 3
|
|
assert second_event.booking_set.count() == 2
|
|
assert third_event.booking_set.count() == 1
|
|
|
|
# new event booking went in waiting list despite free slots on main list
|
|
assert Booking.objects.filter(in_waiting_list=True, event=event).count() == 2
|
|
|
|
# passing empty slots cancels all bookings
|
|
params['slots'] = ''
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['cancelled_booking_count'] == 3
|
|
assert Booking.objects.filter(user_external_id='user_id', cancellation_datetime__isnull=True).count() == 0
|
|
|
|
resp = app.post('/api/agenda/foobar/events/fillslots/', status=404)
|
|
resp = app.post('/api/agenda/0/events/fillslots/', status=404)
|
|
|
|
params = {'user_external_id': 'user_id', 'slots': 'event,event-2', 'foo': 'bar'}
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 2
|
|
assert [b.extra_data for b in Booking.objects.order_by('-pk')[:2]] == [{'foo': 'bar'}, {'foo': 'bar'}]
|
|
|
|
params.update({'foo': ['bar', 'baz']})
|
|
resp = app.post_json(fillslots_url, params=params, status=400)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_class'] == 'wrong type for extra_data foo value'
|
|
|
|
params.update({'foo': {'bar': 'baz'}})
|
|
resp = app.post_json(fillslots_url, params=params, status=400)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_class'] == 'wrong type for extra_data foo value'
|
|
|
|
|
|
@pytest.mark.freeze_time('2021-09-06 12:00')
|
|
def test_api_events_fillslots_with_cancelled(app, user):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
|
event_1 = Event.objects.create(
|
|
label='Event 1',
|
|
start_datetime=now() + datetime.timedelta(days=1),
|
|
places=2,
|
|
agenda=agenda,
|
|
)
|
|
event_2 = Event.objects.create(
|
|
label='Event 2',
|
|
start_datetime=now() + datetime.timedelta(days=2),
|
|
places=2,
|
|
agenda=agenda,
|
|
)
|
|
Event.objects.create(
|
|
label='Event 3',
|
|
start_datetime=now() + datetime.timedelta(days=3),
|
|
places=2,
|
|
agenda=agenda,
|
|
)
|
|
|
|
# create cancelled booking for the user
|
|
booking_1 = Booking.objects.create(event=event_1, user_external_id='user_id')
|
|
booking_1.cancel()
|
|
assert booking_1.cancellation_datetime is not None
|
|
# and non cancelled booking for the user
|
|
booking_2 = Booking.objects.create(event=event_2, user_external_id='user_id')
|
|
assert booking_2.cancellation_datetime is None
|
|
# secondary booking for this one
|
|
booking_2_secondary = Booking.objects.create(event=event_2, primary_booking=booking_2)
|
|
# and bookings for another user
|
|
Booking.objects.create(event=event_1, user_external_id='user_id_foobar')
|
|
other_booking = Booking.objects.create(event=event_2, user_external_id='user_id_foobar')
|
|
other_booking.cancel()
|
|
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
fillslots_url = '/api/agenda/%s/events/fillslots/' % agenda.slug
|
|
|
|
params = {'user_external_id': 'user_id', 'slots': 'event-1,event-2,event-3'}
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 2
|
|
assert len(resp.json['booked_events']) == 2
|
|
assert resp.json['cancelled_booking_count'] == 0
|
|
assert resp.json['booked_events'][0]['id'] == 'event-1'
|
|
assert (
|
|
resp.json['booked_events'][0]['booking']['id']
|
|
== Booking.objects.filter(event__slug='event-1').latest('pk').pk
|
|
)
|
|
assert resp.json['booked_events'][1]['id'] == 'event-3'
|
|
assert (
|
|
resp.json['booked_events'][1]['booking']['id']
|
|
== Booking.objects.filter(event__slug='event-3').latest('pk').pk
|
|
)
|
|
assert Booking.objects.filter(user_external_id='user_id').count() == 3
|
|
assert Booking.objects.filter(user_external_id='user_id', cancellation_datetime__isnull=True).count() == 3
|
|
|
|
assert Booking.objects.filter(pk=booking_1.pk).exists() is False # cancelled booking deleted
|
|
booking_2.refresh_from_db()
|
|
booking_2_secondary.refresh_from_db()
|
|
assert booking_2.cancellation_datetime is None
|
|
assert booking_2_secondary.cancellation_datetime is None
|
|
|
|
params = {'user_external_id': 'user_id', 'slots': 'event-3'}
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 0
|
|
assert resp.json['cancelled_booking_count'] == 2
|
|
assert Booking.objects.filter(user_external_id='user_id').count() == 3
|
|
assert Booking.objects.filter(user_external_id='user_id', cancellation_datetime__isnull=True).count() == 1
|
|
|
|
assert Booking.objects.filter(pk=booking_1.pk).exists() is False # cancelled booking deleted
|
|
booking_2.refresh_from_db()
|
|
booking_2_secondary.refresh_from_db()
|
|
assert booking_2.cancellation_datetime is not None
|
|
assert booking_2_secondary.cancellation_datetime is not None
|
|
|
|
|
|
def test_api_events_fillslots_check_delays(app, user):
|
|
agenda = Agenda.objects.create(
|
|
label='Foo bar', kind='events', minimal_booking_delay=0, maximal_booking_delay=7
|
|
)
|
|
Event.objects.create(
|
|
slug='event-slug',
|
|
start_datetime=localtime() + datetime.timedelta(days=5),
|
|
places=5,
|
|
agenda=agenda,
|
|
)
|
|
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
fillslots_url = '/api/agenda/%s/events/fillslots/' % agenda.slug
|
|
resp = app.post(fillslots_url, params={'user_external_id': 'user_id', 'slots': 'event-slug'})
|
|
assert resp.json['err'] == 0
|
|
booking = Booking.objects.latest('pk')
|
|
assert booking.out_of_min_delay is False
|
|
booking.delete()
|
|
|
|
# test minimal_booking_delay
|
|
agenda.minimal_booking_delay = 6
|
|
agenda.save()
|
|
resp = app.post(fillslots_url, params={'user_external_id': 'user_id', 'slots': 'event-slug'})
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_class'] == 'event not bookable'
|
|
agenda.save()
|
|
resp = app.post(
|
|
fillslots_url, params={'user_external_id': 'user_id', 'slots': 'event-slug', 'bypass_delays': True}
|
|
)
|
|
assert resp.json['err'] == 0
|
|
booking = Booking.objects.latest('pk')
|
|
assert booking.out_of_min_delay is True
|
|
booking.delete()
|
|
|
|
# test maximal_booking_delay
|
|
agenda.minimal_booking_delay = 0
|
|
agenda.maximal_booking_delay = 3
|
|
agenda.save()
|
|
resp = app.post(fillslots_url, params={'user_external_id': 'user_id', 'slots': 'event-slug'})
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_class'] == 'event not bookable'
|
|
agenda.save()
|
|
resp = app.post(
|
|
fillslots_url, params={'user_external_id': 'user_id', 'slots': 'event-slug', 'bypass_delays': True}
|
|
)
|
|
assert resp.json['err'] == 0
|
|
booking = Booking.objects.latest('pk')
|
|
assert booking.out_of_min_delay is False
|
|
|
|
|
|
@pytest.mark.freeze_time('2021-09-06 12:00')
|
|
def test_api_events_fillslots_past_event(app, user):
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
agenda = Agenda.objects.create(
|
|
label='Foo bar', kind='events', minimal_booking_delay=0, maximal_booking_delay=30
|
|
)
|
|
event1 = Event.objects.create(
|
|
label='Today before now',
|
|
start_datetime=localtime(now() - datetime.timedelta(hours=1)),
|
|
places=5,
|
|
agenda=agenda,
|
|
)
|
|
event2 = Event.objects.create(
|
|
label='Today after now',
|
|
start_datetime=localtime(now() + datetime.timedelta(hours=1)),
|
|
places=5,
|
|
agenda=agenda,
|
|
)
|
|
|
|
params = {'user_external_id': 'user_id', 'slots': ','.join((event1.slug, event2.slug))}
|
|
resp = app.post_json('/api/agenda/%s/events/fillslots/' % agenda.slug, params=params)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'event %s is not bookable' % event1.slug
|
|
|
|
params['events'] = 'future'
|
|
resp = app.post_json('/api/agenda/%s/events/fillslots/' % agenda.slug, params=params)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'event %s is not bookable' % event1.slug
|
|
|
|
params['events'] = 'past'
|
|
resp = app.post_json('/api/agenda/%s/events/fillslots/' % agenda.slug, params=params)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'event %s is not bookable' % event2.slug
|
|
|
|
params['events'] = 'all'
|
|
resp = app.post_json('/api/agenda/%s/events/fillslots/' % agenda.slug, params=params)
|
|
assert resp.json['err'] == 0
|
|
|
|
|
|
@pytest.mark.freeze_time('2021-09-06 12:00')
|
|
def test_api_events_fillslots_preserve_past_bookings(app, user, freezer):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
|
event = Event.objects.create(
|
|
label='Event', start_datetime=now() + datetime.timedelta(days=5), places=2, agenda=agenda
|
|
)
|
|
second_event = Event.objects.create(
|
|
label='Event 2', start_datetime=now() + datetime.timedelta(days=10), places=2, agenda=agenda
|
|
)
|
|
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
fillslots_url = '/api/agenda/%s/events/fillslots/' % agenda.slug
|
|
params = {'user_external_id': 'user_id', 'slots': 'event,event-2'}
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 2
|
|
assert resp.json['cancelled_booking_count'] == 0
|
|
|
|
# book only second event while first event is in the past
|
|
freezer.move_to('2021-09-12')
|
|
params = {'user_external_id': 'user_id', 'slots': 'event-2'}
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 0
|
|
assert resp.json['cancelled_booking_count'] == 0
|
|
assert event.booking_set.count() == 1
|
|
assert second_event.booking_set.count() == 1
|
|
|
|
# cancel all future bookings
|
|
params = {'user_external_id': 'user_id', 'slots': ''}
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 0
|
|
assert resp.json['cancelled_booking_count'] == 1
|
|
assert event.booking_set.count() == 1
|
|
assert second_event.booking_set.filter(cancellation_datetime__isnull=True).count() == 0
|
|
|
|
|
|
@pytest.mark.freeze_time('2021-09-06 12:00')
|
|
def test_api_events_fillslots_preserve_out_of_delays_bookings(app, user, freezer):
|
|
agenda = Agenda.objects.create(
|
|
label='Foo bar', kind='events', minimal_booking_delay=2, maximal_booking_delay=10
|
|
)
|
|
event = Event.objects.create(
|
|
label='Event', start_datetime=now() + datetime.timedelta(days=5), places=2, agenda=agenda
|
|
)
|
|
second_event = Event.objects.create(
|
|
label='Event 2', start_datetime=now() + datetime.timedelta(days=9), places=2, agenda=agenda
|
|
)
|
|
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
fillslots_url = '/api/agenda/%s/events/fillslots/' % agenda.slug
|
|
params = {'user_external_id': 'user_id', 'slots': 'event,event-2'}
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 2
|
|
assert resp.json['cancelled_booking_count'] == 0
|
|
assert event.booking_set.get().out_of_min_delay is False
|
|
assert second_event.booking_set.get().out_of_min_delay is False
|
|
|
|
# book only second event while first event is out of delay
|
|
freezer.move_to('2021-09-10')
|
|
params = {'user_external_id': 'user_id', 'slots': 'event-2'}
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 0
|
|
assert resp.json['cancelled_booking_count'] == 0
|
|
assert event.booking_set.filter(cancellation_datetime__isnull=True).count() == 1
|
|
assert event.booking_set.get().out_of_min_delay is False
|
|
assert second_event.booking_set.filter(cancellation_datetime__isnull=True).count() == 1
|
|
assert second_event.booking_set.get().out_of_min_delay is False
|
|
booking = event.booking_set.get()
|
|
# except if we want to bypass delays
|
|
params = {'user_external_id': 'user_id', 'slots': 'event-2', 'bypass_delays': True}
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 0
|
|
assert resp.json['cancelled_booking_count'] == 1
|
|
assert event.booking_set.filter(cancellation_datetime__isnull=True).count() == 0
|
|
assert event.booking_set.get().out_of_min_delay is True
|
|
assert second_event.booking_set.filter(cancellation_datetime__isnull=True).count() == 1
|
|
assert second_event.booking_set.get().out_of_min_delay is False
|
|
booking.save() # reset
|
|
|
|
# cancel all bookings in delays
|
|
params = {'user_external_id': 'user_id', 'slots': ''}
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 0
|
|
assert resp.json['cancelled_booking_count'] == 1
|
|
assert event.booking_set.count() == 1
|
|
assert event.booking_set.get().out_of_min_delay is False
|
|
assert second_event.booking_set.filter(cancellation_datetime__isnull=True).count() == 0
|
|
assert second_event.booking_set.get().out_of_min_delay is False
|
|
# bypass delays
|
|
params = {'user_external_id': 'user_id', 'slots': '', 'bypass_delays': True}
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 0
|
|
assert resp.json['cancelled_booking_count'] == 1
|
|
assert event.booking_set.filter(cancellation_datetime__isnull=True).count() == 0
|
|
assert event.booking_set.get().out_of_min_delay is True
|
|
assert second_event.booking_set.filter(cancellation_datetime__isnull=True).count() == 0
|
|
assert second_event.booking_set.get().out_of_min_delay is False
|
|
booking.save() # reset
|
|
|
|
# book only first event while second event is out of delay
|
|
freezer.move_to('2021-09-04')
|
|
params = {'user_external_id': 'user_id', 'slots': 'event'}
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 0
|
|
assert resp.json['cancelled_booking_count'] == 0
|
|
assert event.booking_set.filter(cancellation_datetime__isnull=True).count() == 1
|
|
assert second_event.booking_set.filter(cancellation_datetime__isnull=True).count() == 0
|
|
# bypass_delays has no effect on maximal_booking_delay
|
|
params = {'user_external_id': 'user_id', 'slots': 'event', 'bypass_delays': True}
|
|
resp = app.post_json(fillslots_url, params=params)
|
|
assert resp.json['booking_count'] == 0
|
|
assert resp.json['cancelled_booking_count'] == 0
|
|
assert event.booking_set.filter(cancellation_datetime__isnull=True).count() == 1
|
|
assert second_event.booking_set.filter(cancellation_datetime__isnull=True).count() == 0
|
|
|
|
|
|
@pytest.mark.freeze_time('2021-09-06 12:00')
|
|
def test_api_events_fillslots_overlapping_events(app, user, freezer):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
|
first_event = Event.objects.create(
|
|
label='Event 12-14',
|
|
start_datetime=now() + datetime.timedelta(days=5),
|
|
duration=120,
|
|
places=5,
|
|
agenda=agenda,
|
|
)
|
|
second_event = Event.objects.create(
|
|
label='Event 13-15',
|
|
start_datetime=now() + datetime.timedelta(days=5, hours=1),
|
|
duration=120,
|
|
places=5,
|
|
agenda=agenda,
|
|
)
|
|
Event.objects.create(
|
|
label='Event 14-16',
|
|
start_datetime=now() + datetime.timedelta(days=5, hours=2),
|
|
duration=120,
|
|
places=5,
|
|
agenda=agenda,
|
|
)
|
|
Event.objects.create(
|
|
label='Event no duration',
|
|
start_datetime=now() + datetime.timedelta(days=5, hours=1),
|
|
places=5,
|
|
agenda=agenda,
|
|
)
|
|
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
fillslots_url = '/api/agenda/foo-bar/events/fillslots/'
|
|
params = {'user_external_id': 'user_id', 'check_overlaps': True}
|
|
resp = app.post_json(fillslots_url, params={**params, 'slots': 'event-12-14'})
|
|
assert resp.json['booking_count'] == 1
|
|
|
|
# booking the same event is still allowed
|
|
resp = app.post_json(fillslots_url, params={**params, 'slots': 'event-12-14'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['booking_count'] == 0
|
|
|
|
# changing booking to second event is allowed
|
|
resp = app.post_json(fillslots_url, params={**params, 'slots': 'event-13-15'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['booking_count'] == 1
|
|
assert resp.json['cancelled_booking_count'] == 1
|
|
|
|
# events are not overlapping if one ends when the other starts
|
|
resp = app.post_json(fillslots_url, params={**params, 'slots': 'event-12-14,event-14-16'})
|
|
assert resp.json['booking_count'] == 2
|
|
assert resp.json['cancelled_booking_count'] == 1
|
|
|
|
# booking overlapping events is allowed if one has no duration
|
|
resp = app.post_json(fillslots_url, params={**params, 'slots': 'event-12-14,event-no-duration'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['booking_count'] == 1
|
|
assert resp.json['cancelled_booking_count'] == 1
|
|
|
|
# default behavior does not check for overlaps
|
|
resp = app.post_json(
|
|
fillslots_url, params={'user_external_id': 'user_id', 'slots': 'event-12-14,event-13-15'}
|
|
)
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['booking_count'] == 1
|
|
assert resp.json['cancelled_booking_count'] == 1
|
|
|
|
# clearing overlapping bookings is allowed
|
|
resp = app.post_json(fillslots_url, params={**params, 'slots': ''})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['booking_count'] == 0
|
|
assert resp.json['cancelled_booking_count'] == 2
|
|
|
|
# booking overlapping events with durations is forbidden
|
|
resp = app.post_json(fillslots_url, params={**params, 'slots': 'event-12-14,event-13-15'})
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'Some events occur at the same time: Event 12-14, Event 13-15'
|
|
|
|
# still overlaps but start before
|
|
second_event.start_datetime -= datetime.timedelta(hours=2)
|
|
second_event.save()
|
|
|
|
resp = app.post_json(fillslots_url, params={**params, 'slots': 'event-12-14,event-13-15'})
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'Some events occur at the same time: Event 12-14, Event 13-15'
|
|
|
|
# still overlaps but contains first event
|
|
second_event.start_datetime = first_event.start_datetime - datetime.timedelta(minutes=10)
|
|
second_event.save()
|
|
second_event.duration = first_event.duration + 10
|
|
second_event.save()
|
|
|
|
resp = app.post_json(fillslots_url, params={**params, 'slots': 'event-12-14,event-13-15'})
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'Some events occur at the same time: Event 12-14, Event 13-15'
|
|
|
|
# still overlaps but contained by first event
|
|
second_event.start_datetime = first_event.start_datetime + datetime.timedelta(minutes=10)
|
|
second_event.save()
|
|
second_event.duration = first_event.duration - 10
|
|
second_event.save()
|
|
|
|
resp = app.post_json(fillslots_url, params={**params, 'slots': 'event-12-14,event-13-15'})
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'Some events occur at the same time: Event 12-14, Event 13-15'
|
|
|
|
# no more overlap
|
|
second_event.start_datetime -= datetime.timedelta(hours=5)
|
|
second_event.save()
|
|
|
|
resp = app.post_json(fillslots_url, params={**params, 'slots': 'event-12-14,event-13-15'})
|
|
assert resp.json['booking_count'] == 2
|
|
|
|
|
|
@pytest.mark.freeze_time('2021-09-06 12:00')
|
|
def test_api_events_fillslots_exclude_user_forbidden(app, user):
|
|
events_type = EventsType.objects.create(label='Foo')
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events', events_type=events_type)
|
|
Event.objects.create(
|
|
label='Event', start_datetime=now() + datetime.timedelta(days=1), places=2, agenda=agenda
|
|
)
|
|
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
fillslots_url = '/api/agenda/%s/events/fillslots/' % agenda.slug
|
|
params = {'user_external_id': 'user_id', 'slots': 'xxx', 'exclude_user': True}
|
|
resp = app.post_json(fillslots_url, params=params, status=400)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['errors']['exclude_user'][0] == 'This parameter is not supported.'
|