chrono/tests/api/fillslot/test_events_multiple_agenda...

775 lines
33 KiB
Python

import datetime
import pytest
from django.db import connection
from django.test.utils import CaptureQueriesContext
from django.utils.timezone import localtime, make_aware, now
from chrono.agendas.models import (
Agenda,
Booking,
Category,
Desk,
Event,
EventsType,
Person,
SharedCustodyAgenda,
SharedCustodyRule,
Subscription,
)
pytestmark = pytest.mark.django_db
@pytest.mark.freeze_time('2021-09-06 12:00')
def test_api_events_fillslots_preserve_past_bookings_multiple_agendas(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'))
params = {'user_external_id': 'user_id', 'slots': 'foo-bar@event,foo-bar@event-2'}
resp = app.post_json('/api/agendas/events/fillslots/?agendas=foo-bar', 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': 'foo-bar@event-2'}
resp = app.post_json('/api/agendas/events/fillslots/?agendas=foo-bar', 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('/api/agendas/events/fillslots/?agendas=foo-bar', 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_multiple_agendas(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'))
params = {'user_external_id': 'user_id', 'slots': 'foo-bar@event,foo-bar@event-2'}
resp = app.post_json('/api/agendas/events/fillslots/?agendas=foo-bar', 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 with multiple agendas API
freezer.move_to('2021-09-10')
params = {'user_external_id': 'user_id', 'slots': 'foo-bar@event-2'}
resp = app.post_json('/api/agendas/events/fillslots/?agendas=foo-bar', 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': 'foo-bar@event-2', 'bypass_delays': True}
resp = app.post_json('/api/agendas/events/fillslots/?agendas=foo-bar', 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('/api/agendas/events/fillslots/?agendas=foo-bar', 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('/api/agendas/events/fillslots/?agendas=foo-bar', 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 with multiple agendas API
freezer.move_to('2021-09-04')
params = {'user_external_id': 'user_id', 'slots': 'foo-bar@event'}
resp = app.post_json('/api/agendas/events/fillslots/?agendas=foo-bar', 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': 'foo-bar@event', 'bypass_delays': True}
resp = app.post_json('/api/agendas/events/fillslots/?agendas=foo-bar', 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_multiple_agendas(app, user):
events_type = EventsType.objects.create(label='Foo')
first_agenda = Agenda.objects.create(label='First agenda', kind='events', events_type=events_type)
Desk.objects.create(agenda=first_agenda, slug='_exceptions_holder')
first_event = Event.objects.create(
label='Event',
start_datetime=now() + datetime.timedelta(days=5),
places=2,
agenda=first_agenda,
)
second_agenda = Agenda.objects.create(label='Second agenda', kind='events')
Desk.objects.create(agenda=second_agenda, slug='_exceptions_holder')
second_event = Event.objects.create(
label='Event',
start_datetime=now() + datetime.timedelta(days=6),
places=2,
agenda=second_agenda,
)
agenda_slugs = '%s,%s' % (first_agenda.slug, second_agenda.slug)
resp = app.get('/api/agendas/datetimes/', params={'agendas': agenda_slugs})
event_slugs = ','.join((resp.json['data'][0]['id'], resp.json['data'][1]['id']))
assert event_slugs == 'first-agenda@event,second-agenda@event'
app.authorization = ('Basic', ('john.doe', 'password'))
params = {'user_external_id': 'user_id', 'check_overlaps': True, 'slots': event_slugs}
with CaptureQueriesContext(connection) as ctx:
resp = app.post_json('/api/agendas/events/fillslots/?agendas=%s' % agenda_slugs, params=params)
assert len(ctx.captured_queries) == 17
assert resp.json['booking_count'] == 2
assert len(resp.json['booked_events']) == 2
assert resp.json['booked_events'][0]['id'] == 'first-agenda@event'
assert (
resp.json['booked_events'][0]['booking']['id']
== Booking.objects.filter(event__agenda=first_agenda, event=first_event).latest('pk').pk
)
assert resp.json['booked_events'][1]['id'] == 'second-agenda@event'
assert (
resp.json['booked_events'][1]['booking']['id']
== Booking.objects.filter(event__agenda=second_agenda, event=second_event).latest('pk').pk
)
assert first_event.booking_set.filter(cancellation_datetime__isnull=True).count() == 1
assert second_event.booking_set.filter(cancellation_datetime__isnull=True).count() == 1
# booking modification
params = {'user_external_id': 'user_id', 'slots': 'first-agenda@event'}
resp = app.post_json('/api/agendas/events/fillslots/?agendas=%s' % agenda_slugs, params=params)
assert resp.json['booking_count'] == 0
assert len(resp.json['booked_events']) == 0
assert resp.json['cancelled_booking_count'] == 1
assert first_event.booking_set.filter(cancellation_datetime__isnull=True).count() == 1
assert second_event.booking_set.filter(cancellation_datetime__isnull=True).count() == 0
params = {'user_external_id': 'user_id_2', 'slots': event_slugs}
resp = app.post_json('/api/agendas/events/fillslots/?agendas=%s' % agenda_slugs, params=params)
assert resp.json['booking_count'] == 2
assert len(resp.json['booked_events']) == 2
assert resp.json['booked_events'][0]['id'] == 'first-agenda@event'
assert (
resp.json['booked_events'][0]['booking']['id']
== Booking.objects.filter(event__agenda=first_agenda, event=first_event).latest('pk').pk
)
assert resp.json['booked_events'][1]['id'] == 'second-agenda@event'
assert (
resp.json['booked_events'][1]['booking']['id']
== Booking.objects.filter(event__agenda=second_agenda, event=second_event).latest('pk').pk
)
assert first_event.booking_set.filter(cancellation_datetime__isnull=True).count() == 2
assert second_event.booking_set.filter(cancellation_datetime__isnull=True).count() == 1
params = {'user_external_id': 'user_id_3', 'slots': event_slugs}
resp = app.post_json('/api/agendas/events/fillslots/?agendas=%s' % agenda_slugs, params=params)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'some events are full: Event'
# invalid agenda slugs in querystring
resp = app.post_json(
'/api/agendas/events/fillslots/?agendas=first-agenda,xxx,yyy', params=params, status=400
)
assert resp.json['errors']['agendas'][0] == 'invalid slugs: xxx, yyy'
# invalid agenda slugs in payload
params = {'user_external_id': 'user_id_3', 'slots': 'first-agenda@event,xxx@event,yyy@event'}
resp = app.post_json(
'/api/agendas/events/fillslots/?agendas=%s' % agenda_slugs, params=params, status=400
)
assert resp.json['errors']['slots'] == ['Events from the following agendas cannot be booked: xxx, yyy']
# missing agendas parameter
resp = app.post_json('/api/agendas/events/fillslots/', params=params, status=400)
assert resp.json['errors']['non_field_errors'] == [
'Either "agendas" or "subscribed" parameter is required.'
]
# valid agendas parameter and event slugs, but mismatch between the two
params = {'user_external_id': 'user_id_3', 'slots': event_slugs}
resp = app.post_json('/api/agendas/events/fillslots/?agendas=first-agenda', params=params, status=400)
assert resp.json['errors']['slots'] == [
'Events from the following agendas cannot be booked: second-agenda'
]
# missing @ in slot
params['slots'] = 'first-agenda'
resp = app.post_json('/api/agendas/events/fillslots/?agendas=first-agenda', params=params, status=400)
assert resp.json['errors']['slots'] == ['Invalid format for slot first-agenda']
# empty event slug
params['slots'] = 'first-agenda@'
resp = app.post_json('/api/agendas/events/fillslots/?agendas=first-agenda', params=params, status=400)
assert resp.json['errors']['slots'] == ['Missing event slug in slot first-agenda@']
# empty agenda slug
params['slots'] = '@event'
resp = app.post_json('/api/agendas/events/fillslots/?agendas=first-agenda', params=params, status=400)
assert resp.json['errors']['slots'] == ['Missing agenda slug in slot @event']
@pytest.mark.freeze_time('2021-09-06 12:00')
def test_api_events_fillslots_multiple_agendas_with_cancelled(app, user):
agenda_1 = Agenda.objects.create(label='Agenda 1', kind='events')
Desk.objects.create(agenda=agenda_1, slug='_exceptions_holder')
event_1 = Event.objects.create(
label='Event 1',
start_datetime=now() + datetime.timedelta(days=1),
places=2,
agenda=agenda_1,
)
agenda_2 = Agenda.objects.create(label='Agenda 2', kind='events')
Desk.objects.create(agenda=agenda_2, slug='_exceptions_holder')
event_2 = Event.objects.create(
label='Event 2',
start_datetime=now() + datetime.timedelta(days=2),
places=2,
agenda=agenda_2,
)
event_3 = Event.objects.create(
label='Event 3',
start_datetime=now() + datetime.timedelta(days=3),
places=2,
agenda=agenda_2,
)
# 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/agendas/events/fillslots/?agendas=%s,%s' % (agenda_1.slug, agenda_2.slug)
params = {'user_external_id': 'user_id', 'slots': 'agenda-1@event-1,agenda-2@event-2,agenda-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'] == 'agenda-1@event-1'
assert (
resp.json['booked_events'][0]['booking']['id']
== Booking.objects.filter(event__agenda=agenda_1, event=event_1).latest('pk').pk
)
assert resp.json['booked_events'][1]['id'] == 'agenda-2@event-3'
assert (
resp.json['booked_events'][1]['booking']['id']
== Booking.objects.filter(event__agenda=agenda_2, event=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': 'agenda-2@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_multiple_agendas_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'))
resp = app.post(
'/api/agendas/events/fillslots/?agendas=foo-bar',
params={'user_external_id': 'user_id', 'slots': 'foo-bar@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(
'/api/agendas/events/fillslots/?agendas=foo-bar',
params={'user_external_id': 'user_id', 'slots': 'foo-bar@event-slug'},
)
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'event not bookable'
agenda.save()
resp = app.post(
'/api/agendas/events/fillslots/?agendas=foo-bar',
params={'user_external_id': 'user_id', 'slots': 'foo-bar@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(
'/api/agendas/events/fillslots/?agendas=foo-bar',
params={'user_external_id': 'user_id', 'slots': 'foo-bar@event-slug'},
)
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'event not bookable'
agenda.save()
resp = app.post(
'/api/agendas/events/fillslots/?agendas=foo-bar',
params={'user_external_id': 'user_id', 'slots': 'foo-bar@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_multiple_agendas_subscribed(app, user):
category = Category.objects.create(label='Category A')
first_agenda = Agenda.objects.create(label='First agenda', kind='events', category=category)
second_agenda = Agenda.objects.create(label='Second agenda', kind='events', category=category)
category = Category.objects.create(label='Category B')
third_agenda = Agenda.objects.create(label='Third agenda', kind='events', category=category)
for agenda in Agenda.objects.all():
Event.objects.create(
slug='event',
start_datetime=now() + datetime.timedelta(days=10),
places=5,
agenda=agenda,
)
Event.objects.create(
slug='event-2',
start_datetime=now() + datetime.timedelta(days=20),
places=5,
agenda=agenda,
)
# add subscriptions to first and second agenda
for agenda in (first_agenda, second_agenda):
Subscription.objects.create(
agenda=agenda,
user_external_id='xxx',
date_start=now(),
date_end=now() + datetime.timedelta(days=10), # too soon
)
# book events
app.authorization = ('Basic', ('john.doe', 'password'))
params = {'user_external_id': 'xxx', 'slots': 'first-agenda@event,second-agenda@event'}
resp = app.post_json('/api/agendas/events/fillslots/?subscribed=category-a', params=params, status=400)
# first event on the last subscription's day
Subscription.objects.all().update(date_end=now() + datetime.timedelta(days=11))
resp = app.post_json('/api/agendas/events/fillslots/?subscribed=category-a', params=params)
assert resp.json['booking_count'] == 2
assert (
Event.objects.get(agenda=first_agenda, slug='event')
.booking_set.filter(cancellation_datetime__isnull=True)
.count()
== 1
)
assert (
Event.objects.get(agenda=second_agenda, slug='event')
.booking_set.filter(cancellation_datetime__isnull=True)
.count()
== 1
)
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 2
# update bookings for category-a
params = {'user_external_id': 'xxx', 'slots': 'second-agenda@event'}
resp = app.post_json('/api/agendas/events/fillslots/?subscribed=category-a', params=params)
assert resp.json['booking_count'] == 0
assert resp.json['cancelled_booking_count'] == 1
assert (
Event.objects.get(agenda=first_agenda, slug='event')
.booking_set.filter(cancellation_datetime__isnull=True)
.count()
== 0
)
assert (
Event.objects.get(agenda=second_agenda, slug='event')
.booking_set.filter(cancellation_datetime__isnull=True)
.count()
== 1
)
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 1
# try to book event from agenda with no subscription TODO messages
params = {'user_external_id': 'xxx', 'slots': 'third-agenda@event'}
for slug in ('all', 'category-a', 'category-b'):
resp = app.post_json('/api/agendas/events/fillslots/?subscribed=%s' % slug, params=params, status=400)
assert (
resp.json['errors']['slots'][0]
== 'Events from the following agendas cannot be booked: third-agenda'
)
# add subscription to third agenda
subscription = Subscription.objects.create(
agenda=third_agenda,
user_external_id='xxx',
date_start=now(),
date_end=now() + datetime.timedelta(days=10),
)
params = {'user_external_id': 'xxx', 'slots': 'third-agenda@event'}
resp = app.post_json('/api/agendas/events/fillslots/?subscribed=category-b', params=params, status=400)
subscription.date_end = now() + datetime.timedelta(days=11)
subscription.save()
resp = app.post_json('/api/agendas/events/fillslots/?subscribed=category-b', params=params)
assert resp.json['booking_count'] == 1
assert (
Event.objects.get(agenda=first_agenda, slug='event')
.booking_set.filter(cancellation_datetime__isnull=True)
.count()
== 0
)
assert (
Event.objects.get(agenda=second_agenda, slug='event')
.booking_set.filter(cancellation_datetime__isnull=True)
.count()
== 1
)
assert (
Event.objects.get(agenda=third_agenda, slug='event')
.booking_set.filter(cancellation_datetime__isnull=True)
.count()
== 1
)
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 2
# add subscription to first agenda (disjoint) spanning event-2
for agenda in (first_agenda, second_agenda):
Subscription.objects.create(
agenda=agenda,
user_external_id='xxx',
date_start=now() + datetime.timedelta(days=15),
date_end=now() + datetime.timedelta(days=25),
)
# book event-2 while updating all bookings
params = {'user_external_id': 'xxx', 'slots': 'first-agenda@event,second-agenda@event-2'}
resp = app.post_json('/api/agendas/events/fillslots/?subscribed=all', params=params)
assert resp.json['booking_count'] == 2
assert resp.json['cancelled_booking_count'] == 2
assert (
Event.objects.get(agenda=first_agenda, slug='event')
.booking_set.filter(cancellation_datetime__isnull=True)
.count()
== 1
)
assert (
Event.objects.get(agenda=second_agenda, slug='event-2')
.booking_set.filter(cancellation_datetime__isnull=True)
.count()
== 1
)
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 2
# other user
for agenda in (first_agenda, second_agenda):
Subscription.objects.create(
agenda=agenda,
user_external_id='yyy',
date_start=now(),
date_end=now() + datetime.timedelta(days=25),
)
params = {'user_external_id': 'yyy', 'slots': 'first-agenda@event,second-agenda@event-2'}
resp = app.post_json('/api/agendas/events/fillslots/?subscribed=all', params=params)
assert resp.json['booking_count'] == 2
assert resp.json['cancelled_booking_count'] == 0
assert (
Event.objects.get(agenda=first_agenda, slug='event')
.booking_set.filter(cancellation_datetime__isnull=True)
.count()
== 2
)
assert (
Event.objects.get(agenda=second_agenda, slug='event-2')
.booking_set.filter(cancellation_datetime__isnull=True)
.count()
== 2
)
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 4
# try to book event outside subscription date range
params = {'user_external_id': 'xxx', 'slots': 'third-agenda@event-2'}
resp = app.post_json('/api/agendas/events/fillslots/?subscribed=all', params=params, status=400)
assert resp.json['err_class'] == 'Some events are outside user subscriptions: third-agenda@event-2'
# mismatch between subscribed parameter and event
params = {'user_external_id': 'xxx', 'slots': 'third-agenda@event'}
resp = app.post_json('/api/agendas/events/fillslots/?subscribed=category-a', params=params, status=400)
assert (
resp.json['errors']['slots'][0] == 'Events from the following agendas cannot be booked: third-agenda'
)
# missing user_external_id
params = {'slots': 'third-agenda@event'}
resp = app.post_json('/api/agendas/events/fillslots/?subscribed=all', params=params, status=400)
assert 'required' in resp.json['errors']['user_external_id'][0]
@pytest.mark.freeze_time('2022-03-07 14:00') # Monday of 10th week
def test_api_events_fillslots_multiple_agendas_shared_custody(app, user):
agenda = Agenda.objects.create(label='First agenda', kind='events')
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
Event.objects.create(
slug='event-wednesday',
start_datetime=make_aware(datetime.datetime(year=2022, month=3, day=9, hour=14, minute=0)),
places=5,
agenda=agenda,
)
Event.objects.create(
slug='event-thursday',
start_datetime=make_aware(datetime.datetime(year=2022, month=3, day=10, hour=14, minute=0)),
places=5,
agenda=agenda,
)
Subscription.objects.create(
agenda=agenda,
user_external_id='child_id',
date_start=now(),
date_end=now() + datetime.timedelta(days=14),
)
father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe')
mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe')
child = Person.objects.create(user_external_id='child_id', first_name='James', last_name='Doe')
agenda = SharedCustodyAgenda.objects.create(
first_guardian=father, second_guardian=mother, child=child, date_start=now()
)
SharedCustodyRule.objects.create(agenda=agenda, guardian=father, days=[0, 1, 2])
SharedCustodyRule.objects.create(agenda=agenda, guardian=mother, days=[3, 4, 5, 6])
app.authorization = ('Basic', ('john.doe', 'password'))
params = {'user_external_id': 'child_id', 'slots': 'first-agenda@event-wednesday'}
resp = app.post_json(
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=father_id', params=params
)
assert resp.json['booking_count'] == 1
resp = app.post_json(
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=mother_id',
params=params,
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'Some events are outside guardian custody: first-agenda@event-wednesday'
params['slots'] = 'first-agenda@event-thursday'
resp = app.post_json(
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=mother_id', params=params
)
assert resp.json['booking_count'] == 1
# unknown guardian
Booking.objects.all().delete()
resp = app.post_json(
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=unknown_id',
params=params,
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'Some events are outside guardian custody: first-agenda@event-thursday'
# guardian_external_id parameter is ignored if there is no custody agenda for child
agenda.delete()
resp = app.post_json(
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=mother_id',
params=params,
)
assert resp.json['booking_count'] == 1
@pytest.mark.freeze_time('2022-03-07 14:00') # Monday of 10th week
def test_api_events_fillslots_multiple_agendas_shared_custody_date_start(app, user):
agenda = Agenda.objects.create(label='First agenda', kind='events')
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
Event.objects.create(
slug='event-wednesday',
start_datetime=make_aware(datetime.datetime(year=2022, month=3, day=9, hour=14, minute=0)),
places=5,
agenda=agenda,
)
Event.objects.create(
slug='event-thursday',
start_datetime=make_aware(datetime.datetime(year=2022, month=3, day=10, hour=14, minute=0)),
places=5,
agenda=agenda,
)
Subscription.objects.create(
agenda=agenda,
user_external_id='child_id',
date_start=now(),
date_end=now() + datetime.timedelta(days=14),
)
father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe')
mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe')
child = Person.objects.create(user_external_id='child_id', first_name='James', last_name='Doe')
agenda = SharedCustodyAgenda.objects.create(
first_guardian=father, second_guardian=mother, child=child, date_start=now()
)
SharedCustodyRule.objects.create(agenda=agenda, guardian=father, days=list(range(7)))
agenda2 = SharedCustodyAgenda.objects.create(
first_guardian=father,
second_guardian=mother,
child=child,
date_start=datetime.date(year=2022, month=3, day=10),
)
SharedCustodyRule.objects.create(agenda=agenda2, guardian=mother, days=list(range(7)))
app.authorization = ('Basic', ('john.doe', 'password'))
params = {'user_external_id': 'child_id', 'slots': 'first-agenda@event-wednesday'}
resp = app.post_json(
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=father_id', params=params
)
assert resp.json['booking_count'] == 1
resp = app.post_json(
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=mother_id',
params=params,
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'Some events are outside guardian custody: first-agenda@event-wednesday'
params['slots'] = 'first-agenda@event-thursday'
resp = app.post_json(
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=mother_id', params=params
)
assert resp.json['booking_count'] == 1
params['slots'] = 'first-agenda@event-thursday'
resp = app.post_json(
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=father_id',
params=params,
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'Some events are outside guardian custody: first-agenda@event-thursday'
# check date_start/date_end params
Booking.objects.all().delete()
resp = app.post_json(
'/api/agendas/events/fillslots/?subscribed=all&guardian_external_id=mother_id',
params={'date_start': '2022-03-09', 'date_end': '2022-03-20', **params},
)
assert resp.json['booking_count'] == 1
@pytest.mark.freeze_time('2021-09-06 12:00')
def test_api_events_fillslots_multiple_agendas_overlapping_events(app, user, freezer):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
Event.objects.create(
label='Event',
start_datetime=now() + datetime.timedelta(days=5),
duration=120,
places=5,
agenda=agenda,
)
second_agenda = Agenda.objects.create(label='Foo bar 2', kind='events')
Event.objects.create(
label='Event 2',
start_datetime=now() + datetime.timedelta(days=5, hours=1),
duration=120,
places=5,
agenda=second_agenda,
)
app.authorization = ('Basic', ('john.doe', 'password'))
fillslots_url = '/api/agendas/events/fillslots/?agendas=%s'
resp = app.post_json(
fillslots_url % ','.join((agenda.slug, second_agenda.slug)),
params={
'user_external_id': 'user_id',
'check_overlaps': True,
'slots': 'foo-bar@event,foo-bar-2@event-2',
},
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'Some events occur at the same time: Event, Event 2'
# events can be booked separately
resp = app.post_json(
fillslots_url % agenda.slug,
params={'user_external_id': 'user_id', 'check_overlaps': True, 'slots': 'foo-bar@event'},
)
assert resp.json['booking_count'] == 1
resp = app.post_json(
fillslots_url % second_agenda.slug,
params={'user_external_id': 'user_id', 'check_overlaps': True, 'slots': 'foo-bar-2@event-2'},
)
assert resp.json['booking_count'] == 1