chrono/tests/api/test_booking.py

1557 lines
64 KiB
Python

import datetime
from unittest import mock
import pytest
from django.db import connection
from django.test.utils import CaptureQueriesContext
from chrono.agendas.models import Agenda, Booking, BookingColor, Category, Desk, Event, MeetingType
from chrono.utils.lingo import CheckType
from chrono.utils.timezone import localtime, make_aware, now
pytestmark = pytest.mark.django_db
def test_booking_ics(app, some_data, meetings_agenda, user, settings, rf):
agenda = Agenda.objects.filter(label='Foo bar')[0]
event = [x for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()][0]
booking = Booking.objects.create(event=event)
formatted_start_date = event.start_datetime.strftime('%Y%m%dT%H%M%S')
booking_ics = booking.get_ics()
assert 'UID:%s-%s-%s\r\n' % (event.start_datetime.isoformat(), agenda.pk, booking.pk) in booking_ics
assert 'SUMMARY:\r\n' in booking_ics
assert 'DTSTART:%sZ\r\n' % formatted_start_date in booking_ics
assert 'DTEND:' not in booking_ics
assert 'ORGANIZER;CN=chrono:mailto:chrono@example.net\r\n' in booking_ics
booking_ics = booking.get_ics(rf.get('/?organizer=no'))
assert 'ORGANIZER' not in booking_ics
settings.TEMPLATE_VARS = {
'global_title': 'meeting server',
'default_from_email': 'donotanswer@meeting-server.com',
}
# test with additional data
booking.label = 'foo'
booking.user_last_name = 'bar'
booking.backoffice_url = 'http://example.net/'
booking.extra_data = {'url': 'http://example.com/booking'}
booking.save()
booking_ics = booking.get_ics()
assert 'SUMMARY:foo\r\n' in booking_ics
assert 'ATTENDEE:bar\r\n' in booking_ics
assert 'URL:http://example.com/booking\r\n' in booking_ics
assert 'ORGANIZER;CN=meeting server:mailto:donotanswer@meeting-server.com\r\n' in booking_ics
# test with user_label in additionnal data
booking.user_first_name = 'foo'
booking.user_last_name = 'bar'
booking.user_display_label = 'your booking'
booking.save()
booking_ics = booking.get_ics()
assert 'SUMMARY:your booking\r\n' in booking_ics
assert 'ATTENDEE:foo bar\r\n' in booking_ics
assert 'URL:http://example.com/booking\r\n' in booking_ics
# extra data stored in extra_data field
booking.label = 'l'
booking.extra_data = {
'backoffice_url': '',
'location': 'bar',
'comment': 'booking comment',
'description': 'booking description',
}
booking.save()
booking_ics = booking.get_ics()
assert 'COMMENT:booking comment\r\n' in booking_ics
assert 'LOCATION:bar\r\n' in booking_ics
assert 'DESCRIPTION:booking description\r\n' in booking_ics
# unauthenticated
app.authorization = None
app.get('/api/booking/%s/ics/' % booking.pk, status=401)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/booking/%s/ics/' % booking.pk)
assert resp.headers['Content-Type'] == 'text/calendar'
params = {
'description': 'custom booking description',
'location': 'custom booking location',
'comment': 'custom comment',
'url': 'http://example.com/custom',
}
resp = app.get('/api/booking/%s/ics/' % booking.pk, params=params)
assert 'DESCRIPTION:custom booking description\r\n' in resp.text
assert 'LOCATION:custom booking location\r\n' in resp.text
assert 'COMMENT:custom comment\r\n' in resp.text
assert 'URL:http://example.com/custom\r\n' in resp.text
meeting_type = MeetingType.objects.get(agenda=meetings_agenda)
resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
event = resp.json['data'][2]
resp = app.post('/api/agenda/%s/fillslot/%s/' % (meetings_agenda.pk, event['id']))
assert Booking.objects.count() == 2
booking = Booking.objects.get(id=resp.json['booking_id'])
booking_ics = booking.get_ics()
start = booking.event.start_datetime.strftime('%Y%m%dT%H%M%S')
end = (
booking.event.start_datetime + datetime.timedelta(minutes=booking.event.meeting_type.duration)
).strftime('%Y%m%dT%H%M%S')
assert 'DTSTART:%sZ\r\n' % start in booking_ics
assert 'DTEND:%sZ\r\n' % end in booking_ics
def test_bookings_api(app, user):
events_agenda = Agenda.objects.create(label='Foo bar', kind='events')
events_event = Event.objects.create(
label='Event A', agenda=events_agenda, start_datetime=now() + datetime.timedelta(days=3), places=10
)
events_booking1 = Booking.objects.create(event=events_event, user_external_id='enfant-1234')
events_booking2 = Booking.objects.create(event=events_event, user_external_id='enfant-1234')
Booking.objects.create(event=events_event, user_external_id='foobar')
Booking.objects.create(event=events_event)
cancelled = Booking.objects.create(event=events_event, user_external_id='enfant-1234')
cancelled.cancel()
Booking.objects.create(
event=events_event, user_external_id='enfant-1234', primary_booking=events_booking1
)
meetings_agenda = Agenda.objects.create(kind='meetings')
desk = Desk.objects.create(agenda=meetings_agenda, label='Desk', slug='desk')
meeting_type = MeetingType.objects.create(agenda=meetings_agenda, label='Foo Bar', slug='foo-bar')
meetings_event = Event.objects.create(
agenda=meetings_agenda, start_datetime=now(), places=1, desk=desk, meeting_type=meeting_type
)
meetings_booking1 = Booking.objects.create(event=meetings_event, user_external_id='enfant-1234')
Booking.objects.create(event=meetings_event, user_external_id='baz')
Booking.objects.create(event=meetings_event, user_external_id='baz')
Booking.objects.create(event=meetings_event)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/')
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'missing param user_external_id'
assert resp.json['err_desc'] == 'missing param user_external_id'
resp = app.get('/api/bookings/', params={'user_external_id': ''})
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'missing param user_external_id'
assert resp.json['err_desc'] == 'missing param user_external_id'
with CaptureQueriesContext(connection) as ctx:
resp = app.get('/api/bookings/', params={'user_external_id': 'enfant-1234'})
assert len(ctx.captured_queries) == 3
assert resp.json['err'] == 0
assert resp.json['data'] == [
{
'id': meetings_booking1.pk,
'in_waiting_list': False,
'user_first_name': '',
'user_last_name': '',
'user_email': '',
'user_phone_number': '',
'use_color_for': None,
'extra_data': None,
'cancellation_datetime': None,
'creation_datetime': localtime(meetings_booking1.creation_datetime).isoformat(),
'label': '',
'desk': {
'slug': 'desk',
'label': 'Desk',
},
},
{
'id': events_booking1.pk,
'in_waiting_list': False,
'user_first_name': '',
'user_last_name': '',
'user_email': '',
'user_phone_number': '',
'user_was_present': None,
'user_absence_reason': None,
'user_presence_reason': None,
'use_color_for': None,
'extra_data': None,
'event': resp.json['data'][1]['event'],
'cancellation_datetime': None,
'creation_datetime': localtime(events_booking1.creation_datetime).isoformat(),
'label': '',
},
{
'id': events_booking2.pk,
'in_waiting_list': False,
'user_first_name': '',
'user_last_name': '',
'user_email': '',
'user_phone_number': '',
'user_was_present': None,
'user_absence_reason': None,
'user_presence_reason': None,
'use_color_for': None,
'extra_data': None,
'event': resp.json['data'][1]['event'],
'cancellation_datetime': None,
'creation_datetime': localtime(events_booking2.creation_datetime).isoformat(),
'label': '',
},
]
event_details = resp.json['data'][1]['event']
assert event_details['label'] == 'Event A'
assert event_details['places']['available'] == 5
assert event_details['api']['backoffice_url'].startswith('http')
def test_bookings_api_filter_agenda(app, user):
bookings = []
for label in ['foobar', 'foobaz']:
agenda = Agenda.objects.create(label=label)
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
bookings.append(Booking.objects.create(event=event, user_external_id='42'))
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'agenda': 'foo'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'agenda': 'foobar'})
assert [b['id'] for b in resp.json['data']] == [bookings[0].pk]
def test_bookings_api_filter_category(app, user):
bookings = []
for label in ['foobar', 'foobaz']:
category = Category.objects.create(label=label)
agenda = Agenda.objects.create(label='Foo bar', category=category)
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
bookings.append(Booking.objects.create(event=event, user_external_id='42'))
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'category': 'foo'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'category': 'foobar'})
assert [b['id'] for b in resp.json['data']] == [bookings[0].pk]
def test_bookings_api_filter_date_start(app, user):
agenda = Agenda.objects.create(label='Foo bar')
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
)
booking = Booking.objects.create(event=event, user_external_id='42')
app.authorization = ('Basic', ('john.doe', 'password'))
for value in ['foo', '2017-05-42']:
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': value}, status=400)
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'invalid payload'
assert resp.json['err_desc'] == 'invalid payload'
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-21'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-22'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-23'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
event.start_datetime = make_aware(datetime.datetime(2017, 5, 22, 23, 59))
event.save()
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-21'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-22'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-23'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
def test_bookings_api_filter_date_end(app, user):
agenda = Agenda.objects.create(label='Foo bar')
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
)
booking = Booking.objects.create(event=event, user_external_id='42')
app.authorization = ('Basic', ('john.doe', 'password'))
for value in ['foo', '2017-05-42']:
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': value}, status=400)
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'invalid payload'
assert resp.json['err_desc'] == 'invalid payload'
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-21'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-22'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-23'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking.pk]
event.start_datetime = make_aware(datetime.datetime(2017, 5, 22, 23, 59))
event.save()
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-21'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-22'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-23'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking.pk]
def test_bookings_api_filter_user_was_present(app, user):
agenda = Agenda.objects.create(label='Foo bar')
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
)
Booking.objects.create(event=event, user_external_id='42')
booking2 = Booking.objects.create(event=event, user_external_id='42', user_was_present=True)
booking3 = Booking.objects.create(event=event, user_external_id='42', user_was_present=False)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_was_present': True})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking2.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_was_present': False})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking3.pk]
def test_bookings_api_filter_user_absence_reason(app, user):
agenda = Agenda.objects.create(label='Foo bar')
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
)
Booking.objects.create(event=event, user_external_id='42', user_was_present=False)
booking2 = Booking.objects.create(
event=event,
user_external_id='42',
user_was_present=False,
user_check_type_slug='foo-bar',
user_check_type_label='Foo bar',
)
Booking.objects.create(
event=event,
user_external_id='42',
user_was_present=True,
user_check_type_slug='foo-bar-2',
user_check_type_label='Foo bar 2',
)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'foo'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'foo-bar'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking2.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'Foo bar'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking2.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'foo-bar-2'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
Booking.objects.update(user_was_present=True)
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'Foo bar 2'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
def test_bookings_api_filter_user_presence_reason(app, user):
agenda = Agenda.objects.create(label='Foo bar')
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
)
Booking.objects.create(event=event, user_external_id='42', user_was_present=True)
booking2 = Booking.objects.create(
event=event,
user_external_id='42',
user_was_present=True,
user_check_type_slug='foo-bar',
user_check_type_label='Foo bar',
)
Booking.objects.create(
event=event,
user_external_id='42',
user_was_present=False,
user_check_type_slug='foo-bar-2',
user_check_type_label='Foo bar 2',
)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': 'foo'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': 'foo-bar'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking2.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': 'Foo bar'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking2.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': 'foo-bar-2'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
Booking.objects.update(user_was_present=False)
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': 'Foo bar 2'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
def test_bookings_api_filter_in_waiting_list(app, user):
agenda = Agenda.objects.create(label='Foo bar')
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
)
booking_main_list = Booking.objects.create(event=event, user_external_id='42')
booking_waiting_list = Booking.objects.create(event=event, user_external_id='42', in_waiting_list=True)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/', params={'user_external_id': '42'})
assert resp.json['err'] == 0
assert len(resp.json['data']) == 2
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'in_waiting_list': False})
assert resp.json['err'] == 0
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['id'] == booking_main_list.id
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'in_waiting_list': True})
assert resp.json['err'] == 0
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['id'] == booking_waiting_list.id
@pytest.mark.freeze_time('2021-05-06 14:00')
def test_bookings_api_filter_event(app, user):
agenda = Agenda.objects.create(label='Foo bar')
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
normal_event = Event.objects.create(slug='normal_event', agenda=agenda, start_datetime=now(), places=10)
recurring_event = Event.objects.create(
slug='recurring-event',
start_datetime=now(),
recurrence_days=list(range(1, 8)),
places=2,
waiting_list_places=1,
agenda=agenda,
recurrence_end_date=now() + datetime.timedelta(days=30),
)
recurring_event.create_all_recurrences()
Booking.objects.create(event=normal_event, user_external_id='42')
for recurrence in recurring_event.recurrences.all()[:5]:
Booking.objects.create(event=recurrence, user_external_id='42')
resp = app.get('/api/bookings/', params={'user_external_id': '42'})
assert resp.json['err'] == 0
assert len(resp.json['data']) == 6
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'event': normal_event.slug})
assert resp.json['err'] == 0
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['event']['slug'] == normal_event.slug
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'event': recurring_event.slug})
assert resp.json['err'] == 0
assert len(resp.json['data']) == 5
slugs = [booking['event']['slug'] for booking in resp.json['data']]
assert slugs == [
'recurring-event--2021-05-06-1600',
'recurring-event--2021-05-07-1600',
'recurring-event--2021-05-08-1600',
'recurring-event--2021-05-09-1600',
'recurring-event--2021-05-10-1600',
]
@pytest.mark.parametrize('flag', [True, False, None])
def test_booking_api_present(app, user, flag):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event, user_was_present=flag, user_check_type_slug='foo-bar')
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/booking/%s/' % booking.pk)
assert resp.json['booking_id'] == booking.pk
assert resp.json['user_was_present'] == flag
assert resp.json['user_absence_reason'] == ('foo-bar' if flag is False else None)
assert resp.json['user_presence_reason'] == ('foo-bar' if flag is True else None)
@pytest.mark.parametrize('flag', [True, False])
def test_booking_api_waiting_list(app, user, flag):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event, in_waiting_list=flag)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/booking/%s/' % booking.pk)
assert resp.json['booking_id'] == booking.pk
assert resp.json['in_waiting_list'] == flag
def test_booking_api_error(app, user):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event)
app.authorization = ('Basic', ('john.doe', 'password'))
# unknown
booking.cancel()
for method in ['get', 'delete', 'patch']:
getattr(app, method)('/api/booking/0/', status=404)
# cancelled
booking.cancel()
for method in ['get', 'delete', 'patch']:
resp = getattr(app, method)('/api/booking/%s/' % booking.pk)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'booking is cancelled'
# not a primary booking
secondary = Booking.objects.create(event=event, primary_booking=booking)
for method in ['get', 'delete', 'patch']:
resp = getattr(app, method)('/api/booking/%s/' % secondary.pk)
assert resp.json['err'] == 2
assert resp.json['err_desc'] == 'secondary booking'
# in waiting list
booking.cancellation_datetime = None
booking.in_waiting_list = True
booking.save()
resp = app.get('/api/booking/%s/' % booking.pk)
assert resp.json['err'] == 0
resp = app.patch('/api/booking/%s/' % booking.pk)
assert resp.json['err'] == 3
assert resp.json['err_desc'] == 'booking is in waiting list'
resp = app.delete('/api/booking/%s/' % booking.pk)
assert resp.json['err'] == 0
def test_booking_patch_api(app, user):
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.patch('/api/booking/%s/' % booking.pk)
assert resp.json['err'] == 0
resp = app.patch('/api/booking/%s/' % booking.pk, params={'user_was_present': 'foobar'}, status=400)
assert resp.json['err'] == 4
assert resp.json['err_desc'] == 'invalid payload'
resp = app.patch('/api/booking/%s/' % booking.pk, params={'label': 'foobar'})
booking.refresh_from_db()
assert booking.label == 'foobar'
resp = app.patch('/api/booking/%s/' % booking.pk, params={'label': 'the most important booking'})
booking.refresh_from_db()
assert booking.label == 'the most important booking'
resp = app.patch('/api/booking/%s/' % booking.pk, params={'label': ''})
booking.refresh_from_db()
assert booking.label == ''
@pytest.mark.parametrize('flag', [True, False, None])
def test_booking_patch_api_present(app, user, flag):
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event)
assert agenda.mark_event_checked_auto is False
app.authorization = ('Basic', ('john.doe', 'password'))
# set flag
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag})
booking.refresh_from_db()
assert booking.user_was_present == flag
event.refresh_from_db()
assert event.checked is False
agenda.mark_event_checked_auto = True
agenda.save()
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag})
booking.refresh_from_db()
assert booking.user_was_present == flag
event.refresh_from_db()
assert event.checked == (flag is not None)
# reset
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': None})
booking.refresh_from_db()
assert booking.user_was_present is None
# make secondary bookings
Booking.objects.create(event=event, primary_booking=booking)
Booking.objects.create(event=event, primary_booking=booking)
# and other booking
other_booking = Booking.objects.create(event=event)
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag})
booking.refresh_from_db()
assert booking.user_was_present == flag
# all secondary bookings are updated
assert list(booking.secondary_booking_set.values_list('user_was_present', flat=True)) == [flag, flag]
other_booking.refresh_from_db()
assert other_booking.user_was_present is None # not changed
# mark the event as checked
event.checked = True
event.save()
resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag})
assert resp.json['err'] == 0
# now disable check update
agenda.disable_check_update = True
agenda.save()
resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag}, status=400)
assert resp.json['err'] == 5
assert resp.json['err_desc'] == 'event is marked as checked'
resp = app.patch_json('/api/booking/%s/' % booking.pk)
assert resp.json['err'] == 0
agenda.kind = 'meetings'
agenda.save()
resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag}, status=400)
assert resp.json['err'] == 7
assert resp.json['err_desc'] == 'can not set check fields for non events agenda'
@mock.patch('chrono.api.serializers.get_agenda_check_types')
def test_booking_patch_api_absence_reason(check_types, app, user):
check_types.return_value = []
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event, user_was_present=False)
app.authorization = ('Basic', ('john.doe', 'password'))
# reasons not defined on agenda
resp = app.patch_json(
'/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'foobar'}, status=400
)
assert resp.json['err'] == 4
assert resp.json['err_desc'] == 'invalid payload'
resp = app.patch_json(
'/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'foobar'}, status=400
)
assert resp.json['err'] == 4
assert resp.json['err_desc'] == 'invalid payload'
# set check_type
check_types.return_value = [
CheckType(slug='foo-bar', label='Foo bar', kind='absence'),
CheckType(slug='foo-baz', label='Foo baz', kind='presence'),
]
# it works with label
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'Foo bar'})
booking.refresh_from_db()
assert booking.user_check_type_slug == 'foo-bar'
assert booking.user_check_type_label == 'Foo bar'
# unknown
resp = app.patch_json(
'/api/booking/%s/' % booking.pk,
params={'user_presence_reason': 'unknown'},
status=400,
)
assert resp.json['err'] == 4
assert resp.json['err_desc'] == 'invalid payload'
# reset
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': ''})
booking.refresh_from_db()
assert booking.user_check_type_slug is None
assert booking.user_check_type_label is None
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': None})
booking.refresh_from_db()
assert booking.user_check_type_slug is None
assert booking.user_check_type_label is None
# make secondary bookings
Booking.objects.create(event=event, primary_booking=booking, user_was_present=False)
Booking.objects.create(event=event, primary_booking=booking, user_was_present=False)
# and other booking
other_booking = Booking.objects.create(event=event)
# it works also with slug
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'foo-bar'})
booking.refresh_from_db()
assert booking.user_check_type_slug == 'foo-bar'
assert booking.user_check_type_label == 'Foo bar'
# all secondary bookings are updated
assert list(booking.secondary_booking_set.values_list('user_check_type_slug', flat=True)) == [
'foo-bar',
'foo-bar',
]
other_booking.refresh_from_db()
assert other_booking.user_check_type_slug is None # not changed
assert other_booking.user_check_type_label is None # not changed
# user_was_present is True, can not set user_absence_reason
Booking.objects.update(user_was_present=True)
resp = app.patch_json(
'/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'foo-bar'}, status=400
)
assert resp.json['err'] == 6
assert resp.json['err_desc'] == 'user is marked as present, can not set absence reason'
# but it's ok if user_was_present is set to False
resp = app.patch_json(
'/api/booking/%s/' % booking.pk,
params={'user_absence_reason': 'foo-bar', 'user_was_present': False},
)
assert resp.json['err'] == 0
booking.refresh_from_db()
assert booking.user_was_present is False
assert booking.user_check_type_slug == 'foo-bar'
assert booking.user_check_type_label == 'Foo bar'
# mark the event as checked
event.checked = True
event.save()
resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'foo-bar'})
assert resp.json['err'] == 0
# now disable check update
agenda.disable_check_update = True
agenda.save()
resp = app.patch_json(
'/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'foo-bar'}, status=400
)
assert resp.json['err'] == 5
assert resp.json['err_desc'] == 'event is marked as checked'
resp = app.patch_json('/api/booking/%s/' % booking.pk)
assert resp.json['err'] == 0
agenda.kind = 'meetings'
agenda.save()
resp = app.patch_json(
'/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'foo-bar'}, status=400
)
assert resp.json['err'] == 7
assert resp.json['err_desc'] == 'can not set check fields for non events agenda'
@mock.patch('chrono.api.serializers.get_agenda_check_types')
def test_booking_patch_api_presence_reason(check_types, app, user):
check_types.return_value = []
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event, user_was_present=True)
app.authorization = ('Basic', ('john.doe', 'password'))
# reasons not defined on agenda
resp = app.patch_json(
'/api/booking/%s/' % booking.pk, params={'user_presence_reason': 'foobar'}, status=400
)
assert resp.json['err'] == 4
assert resp.json['err_desc'] == 'invalid payload'
resp = app.patch_json(
'/api/booking/%s/' % booking.pk, params={'user_presence_reason': 'foobar'}, status=400
)
assert resp.json['err'] == 4
assert resp.json['err_desc'] == 'invalid payload'
# set check_type
check_types.return_value = [
CheckType(slug='foo-bar', label='Foo bar', kind='presence'),
CheckType(slug='foo-baz', label='Foo baz', kind='absence'),
]
# it works with label
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_presence_reason': 'Foo bar'})
booking.refresh_from_db()
assert booking.user_check_type_slug == 'foo-bar'
assert booking.user_check_type_label == 'Foo bar'
# unknown
resp = app.patch_json(
'/api/booking/%s/' % booking.pk,
params={'user_presence_reason': 'unknown'},
status=400,
)
assert resp.json['err'] == 4
assert resp.json['err_desc'] == 'invalid payload'
# reset
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_presence_reason': ''})
booking.refresh_from_db()
assert booking.user_check_type_slug is None
assert booking.user_check_type_label is None
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_presence_reason': None})
booking.refresh_from_db()
assert booking.user_check_type_slug is None
assert booking.user_check_type_label is None
# make secondary bookings
Booking.objects.create(event=event, primary_booking=booking, user_was_present=True)
Booking.objects.create(event=event, primary_booking=booking, user_was_present=True)
# and other booking
other_booking = Booking.objects.create(event=event)
# it works also with slug
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_presence_reason': 'foo-bar'})
booking.refresh_from_db()
assert booking.user_check_type_slug == 'foo-bar'
assert booking.user_check_type_label == 'Foo bar'
# all secondary bookings are updated
assert list(booking.secondary_booking_set.values_list('user_check_type_slug', flat=True)) == [
'foo-bar',
'foo-bar',
]
other_booking.refresh_from_db()
assert other_booking.user_check_type_slug is None # not changed
assert other_booking.user_check_type_label is None # not changed
# user_was_present is False, can not set user_presence_reason
Booking.objects.update(user_was_present=False)
resp = app.patch_json(
'/api/booking/%s/' % booking.pk, params={'user_presence_reason': 'foo-bar'}, status=400
)
assert resp.json['err'] == 6
assert resp.json['err_desc'] == 'user is marked as absent, can not set presence reason'
# but it's ok if user_was_present is set to True
resp = app.patch_json(
'/api/booking/%s/' % booking.pk,
params={'user_presence_reason': 'foo-bar', 'user_was_present': True},
)
assert resp.json['err'] == 0
booking.refresh_from_db()
assert booking.user_was_present is True
assert booking.user_check_type_slug == 'foo-bar'
assert booking.user_check_type_label == 'Foo bar'
# mark the event as checked
event.checked = True
event.save()
resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'user_presence_reason': 'foo-bar'})
assert resp.json['err'] == 0
# now disable check update
agenda.disable_check_update = True
agenda.save()
resp = app.patch_json(
'/api/booking/%s/' % booking.pk, params={'user_presence_reason': 'foo-bar'}, status=400
)
assert resp.json['err'] == 5
assert resp.json['err_desc'] == 'event is marked as checked'
resp = app.patch_json('/api/booking/%s/' % booking.pk)
assert resp.json['err'] == 0
agenda.kind = 'meetings'
agenda.save()
resp = app.patch_json(
'/api/booking/%s/' % booking.pk, params={'user_presence_reason': 'foo-bar'}, status=400
)
assert resp.json['err'] == 7
assert resp.json['err_desc'] == 'can not set check fields for non events agenda'
def test_booking_patch_api_both_reasons(app, user):
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.patch_json(
'/api/booking/%s/' % booking.pk,
params={'user_presence_reason': 'foo-bar', 'user_absence_reason': 'foo-baz'},
status=400,
)
assert resp.json['err'] == 4
assert resp.json['err_desc'] == 'invalid payload'
def test_booking_patch_api_user_fields(app, user):
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
BookingColor.objects.create(label='the warmest color')
BookingColor.objects.create(label='the coolest color')
color = BookingColor.objects.create(label='meh')
booking = Booking.objects.create(event=event, color=color)
# make secondary bookings
Booking.objects.create(event=event, primary_booking=booking)
Booking.objects.create(event=event, primary_booking=booking)
# and other booking
other_booking = Booking.objects.create(event=event)
app.authorization = ('Basic', ('john.doe', 'password'))
to_test = [
('user_first_name', 'fooo'),
('user_first_name', ''),
('user_last_name', 'baaaar'),
('user_last_name', ''),
('user_email', 'fooo@baaaar.com'),
('user_email', ''),
('user_phone_number', '0606'),
('user_phone_number', ''),
('color', 'the warmest color'), # legacy
('use_color_for', 'the coolest color'),
]
for key, value in to_test:
params = {
key: value,
}
app.patch_json('/api/booking/%s/' % booking.pk, params=params)
booking.refresh_from_db()
if key == 'use_color_for':
key = 'color'
assert str(getattr(booking, key)) == value
# all secondary bookings are updated
for secondary_booking in booking.secondary_booking_set.all():
assert str(getattr(secondary_booking, key)) == value
other_booking.refresh_from_db()
assert not getattr(other_booking, key) # not changed
# try again with a non existing color
params = {
'color': 'unicorn crimson',
}
app.patch_json('/api/booking/%s/' % booking.pk, params=params)
booking.refresh_from_db()
assert booking.color.label == 'unicorn crimson'
for secondary_booking in booking.secondary_booking_set.all():
assert secondary_booking.color.label == 'unicorn crimson'
assert BookingColor.objects.count() == 4
params = {
'use_color_for': 'unicorn crimson again',
}
app.patch_json('/api/booking/%s/' % booking.pk, params=params)
booking.refresh_from_db()
assert booking.color.label == 'unicorn crimson again'
for secondary_booking in booking.secondary_booking_set.all():
assert secondary_booking.color.label == 'unicorn crimson again'
assert BookingColor.objects.count() == 5
# empty value
params = {
'color': '',
}
app.patch_json('/api/booking/%s/' % booking.pk, params=params)
booking.refresh_from_db()
assert booking.color is None
for secondary_booking in booking.secondary_booking_set.all():
assert secondary_booking.color is None
assert BookingColor.objects.count() == 5
# none value
params = {
'color': None,
}
app.patch_json('/api/booking/%s/' % booking.pk, params=params)
booking.refresh_from_db()
assert booking.color is None
for secondary_booking in booking.secondary_booking_set.all():
assert secondary_booking.color is None
assert BookingColor.objects.count() == 5
def test_booking_patch_api_extra_data(app, user):
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event, user_was_present=True)
app.authorization = ('Basic', ('john.doe', 'password'))
app.patch_json('/api/booking/%s/' % booking.pk, params={'foo': 'bar'})
booking.refresh_from_db()
assert booking.user_was_present is True # not changed
assert booking.extra_data == {'foo': 'bar'}
app.patch_json('/api/booking/%s/' % booking.pk, params={'foo': 'baz'})
booking.refresh_from_db()
assert booking.user_was_present is True # not changed
assert booking.extra_data == {'foo': 'baz'}
app.patch_json('/api/booking/%s/' % booking.pk, params={'foooo': 'bar'})
booking.refresh_from_db()
assert booking.user_was_present is True # not changed
assert booking.extra_data == {'foo': 'baz', 'foooo': 'bar'}
app.patch_json('/api/booking/%s/' % booking.pk, params={'foooo': 'baz', 'foo': None})
booking.refresh_from_db()
assert booking.user_was_present is True # not changed
assert booking.extra_data == {'foo': None, 'foooo': 'baz'}
# make secondary bookings
Booking.objects.create(event=event, primary_booking=booking, user_was_present=False)
Booking.objects.create(event=event, primary_booking=booking, user_was_present=False)
# and other booking
other_booking = Booking.objects.create(event=event)
app.patch_json('/api/booking/%s/' % booking.pk, params={'foooo': 'baz', 'foo': None})
assert booking.user_was_present is True # not changed
assert booking.extra_data == {'foo': None, 'foooo': 'baz'}
# all secondary bookings are upadted
assert list(booking.secondary_booking_set.values_list('extra_data', flat=True)) == [
{'foo': None, 'foooo': 'baz'},
{'foo': None, 'foooo': 'baz'},
]
assert list(booking.secondary_booking_set.values_list('user_was_present', flat=True)) == [
False,
False,
] # not changed
other_booking.refresh_from_db()
assert other_booking.extra_data is None # not changed
app.patch_json('/api/booking/%s/' % booking.pk, params={})
booking.refresh_from_db()
assert booking.user_was_present is True # not changed
assert booking.extra_data == {'foo': None, 'foooo': 'baz'} # not changed
resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'foo': ['bar', 'baz']}, status=400)
assert resp.json['err_desc'] == 'wrong type for extra_data foo value'
resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'foo': {'bar': 'baz'}}, status=400)
assert resp.json['err_desc'] == 'wrong type for extra_data foo value'
def test_booking_cancellation_api(app, user):
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event)
app.authorization = ('Basic', ('john.doe', 'password'))
app.delete('/api/booking/%s/' % booking.pk)
assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 1
def test_bookings(app, user):
agenda = Agenda.objects.create(label='Foo bar', kind='events', minimal_booking_delay=0)
event = Event.objects.create(
slug='event-slug',
start_datetime=(now() + datetime.timedelta(days=5)).replace(hour=10, minute=0),
places=5,
waiting_list_places=5,
agenda=agenda,
)
agenda2 = Agenda.objects.create(label='Foo bar2', kind='events', minimal_booking_delay=0)
# other event with the same slug but in another agenda
Event.objects.create(
slug='event-slug',
start_datetime=(now() + datetime.timedelta(days=5)).replace(hour=10, minute=0),
places=5,
agenda=agenda2,
)
# create a booking not on the waiting list
primary1 = Booking.objects.create(event=event, in_waiting_list=False, user_external_id='42')
Booking.objects.create(
event=event, in_waiting_list=False, primary_booking=primary1, user_external_id='42'
)
primary2 = Booking.objects.create(event=event, in_waiting_list=False, user_external_id='foobar')
Booking.objects.create(event=event, in_waiting_list=False, user_external_id='')
primary4 = Booking.objects.create(event=event, in_waiting_list=True, user_external_id='42')
app.authorization = ('Basic', ('john.doe', 'password'))
# unknown agenda
app.get('/api/agenda/foobar/bookings/%s/' % (event.pk), params={'user_external_id': '42'}, status=404)
# unknown event
app.get('/api/agenda/%s/bookings/0/' % (agenda.slug), params={'user_external_id': '42'}, status=404)
app.get('/api/agenda/%s/bookings/foobar/' % (agenda.slug), params={'user_external_id': '42'}, status=404)
# search for '42' external user
resp = app.get(
'/api/agenda/%s/bookings/%s/' % (agenda.slug, event.slug), params={'user_external_id': '42'}
)
assert resp.json['err'] == 0
assert resp.json['data'] == [
{'booking_id': primary1.pk, 'in_waiting_list': False},
{'booking_id': primary4.pk, 'in_waiting_list': True},
]
# primary1 is cancelled
primary1.cancel()
resp = app.get(
'/api/agenda/%s/bookings/%s/' % (agenda.slug, event.slug), params={'user_external_id': '42'}
)
assert resp.json['err'] == 0
assert resp.json['data'] == [
{'booking_id': primary4.pk, 'in_waiting_list': True},
]
# search for 'foobar' external user
resp = app.get(
'/api/agenda/%s/bookings/%s/' % (agenda.slug, event.slug), params={'user_external_id': 'foobar'}
)
assert resp.json['err'] == 0
assert resp.json['data'] == [
{'booking_id': primary2.pk, 'in_waiting_list': False},
]
# no bookings for this external user
resp = app.get(
'/api/agenda/%s/bookings/%s/' % (agenda.slug, event.slug), params={'user_external_id': '35'}
)
assert resp.json['err'] == 0
assert resp.json['data'] == []
# no user_external_id in params
resp = app.get('/api/agenda/%s/bookings/%s/' % (agenda.slug, event.slug), params={'user_external_id': ''})
assert resp.json['err'] == 1
assert resp.json['reason'] == 'missing param user_external_id' # legacy
assert resp.json['err_class'] == 'missing param user_external_id'
assert resp.json['err_desc'] == 'missing param user_external_id'
resp = app.get('/api/agenda/%s/bookings/%s/' % (agenda.slug, event.slug))
assert resp.json['err'] == 1
# wrong kind
agenda.kind = 'meetings'
agenda.save()
app.get(
'/api/agenda/%s/bookings/%s/' % (agenda.slug, event.slug),
params={'user_external_id': '42'},
status=404,
)
def test_cancel_booking(app, user):
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
primary = Booking.objects.create(event=event)
secondary = Booking.objects.create(event=event, primary_booking=primary)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/booking/%s/cancel/' % secondary.pk)
assert resp.json['err'] == 2
assert resp.json['reason'] == 'secondary booking' # legacy
assert resp.json['err_class'] == 'secondary booking'
assert resp.json['err_desc'] == 'secondary booking'
resp = app.post('/api/booking/%s/cancel/' % primary.pk)
assert resp.json['err'] == 0
primary.refresh_from_db()
secondary.refresh_from_db()
assert primary.cancellation_datetime is not None
assert secondary.cancellation_datetime is not None
# cancel an object that doesn't exist
resp = app.post('/api/booking/%s/cancel/' % 0, status=404)
# cancel an event that was already cancelled
resp = app.post('/api/booking/%s/cancel/' % primary.pk, status=200)
assert resp.json['err'] == 1
def test_cancel_booking_no_trigger(app, user):
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event, cancel_callback_url='http://example.net/jump/trigger/')
app.authorization = ('Basic', ('john.doe', 'password'))
with mock.patch('chrono.agendas.models.requests.post') as mocked_post:
app.post('/api/booking/%s/cancel/' % booking.pk)
assert not mocked_post.called
assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 1
def test_accept_booking(app, user):
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=20, waiting_list_places=5)
# create a booking on the waiting list
primary = Booking.objects.create(event=event, in_waiting_list=True)
secondary = Booking.objects.create(event=event, in_waiting_list=True, primary_booking=primary)
assert Booking.objects.filter(in_waiting_list=True).count() == 2
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/booking/%s/accept/' % secondary.id)
assert resp.json['err'] == 2
assert resp.json['reason'] == 'secondary booking' # legacy
assert resp.json['err_class'] == 'secondary booking'
assert resp.json['err_desc'] == 'secondary booking'
resp = app.post('/api/booking/%s/accept/' % primary.id)
assert resp.json['err'] == 0
assert resp.json['overbooked_places'] == 0
assert Booking.objects.filter(in_waiting_list=True).count() == 0
assert Booking.objects.filter(in_waiting_list=False).count() == 2
primary.refresh_from_db()
secondary.refresh_from_db()
assert primary.in_waiting_list is False
assert secondary.in_waiting_list is False
# accept a booking that doesn't exist
resp = app.post('/api/booking/0/accept/', status=404)
# accept a booking that was not in the waiting list
resp = app.post('/api/booking/%s/accept/' % primary.id, status=200)
assert resp.json['err'] == 3
# accept a booking that was cancelled before
primary.suspend()
primary.cancel()
resp = app.post('/api/booking/%s/accept/' % primary.id, status=200)
assert resp.json['err'] == 1
assert Booking.objects.filter(in_waiting_list=True).count() == 2
assert Booking.objects.filter(in_waiting_list=False).count() == 0
# accept a booking with overbooking
event.places = 1
event.save()
Booking.objects.update(cancellation_datetime=None)
primary.refresh_from_db()
primary.suspend()
resp = app.post('/api/booking/%s/accept/' % primary.pk)
assert resp.json['err'] == 0
assert resp.json['overbooked_places'] == 1
def test_accept_booking_non_event_agenda(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
agenda = Agenda.objects.create(kind='meetings')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=1)
booking = Booking.objects.create(event=event)
app.post('/api/booking/%s/accept/' % booking.pk, status=404)
agenda.kind = 'virtual'
agenda.save()
app.post('/api/booking/%s/accept/' % booking.pk, status=404)
def test_suspend_booking(app, user):
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=20, waiting_list_places=5)
# create a booking not on the waiting list
primary = Booking.objects.create(event=event, in_waiting_list=False)
secondary = Booking.objects.create(event=event, in_waiting_list=False, primary_booking=primary)
assert Booking.objects.filter(in_waiting_list=False).count() == 2
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/booking/%s/suspend/' % secondary.id)
assert resp.json['err'] == 2
assert resp.json['reason'] == 'secondary booking' # legacy
assert resp.json['err_class'] == 'secondary booking'
assert resp.json['err_desc'] == 'secondary booking'
resp = app.post('/api/booking/%s/suspend/' % primary.pk)
primary.refresh_from_db()
secondary.refresh_from_db()
assert primary.in_waiting_list is True
assert secondary.in_waiting_list is True
# suspend a booking that doesn't exist
resp = app.post('/api/booking/0/suspend/', status=404)
# suspend a booking that is in the waiting list
resp = app.post('/api/booking/%s/suspend/' % primary.pk, status=200)
assert resp.json['err'] == 3
# suspend a booking that was cancelled before
primary.accept()
primary.cancel()
resp = app.post('/api/booking/%s/suspend/' % primary.pk, status=200)
assert resp.json['err'] == 1
assert primary.in_waiting_list is False
def test_suspend_booking_non_event_agenda(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
agenda = Agenda.objects.create(kind='meetings')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=1)
booking = Booking.objects.create(event=event)
app.post('/api/booking/%s/suspend/' % booking.pk, status=404)
agenda.kind = 'virtual'
agenda.save()
app.post('/api/booking/%s/suspend/' % booking.pk, status=404)
def test_resize_booking_invalid_payload(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
# decrease a booking to 0
resp = app.post('/api/booking/0/resize/', params={'count': 0}, status=400)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
def test_resize_booking_not_found(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
app.post('/api/booking/0/resize/', params={'count': 42}, status=404)
def test_resize_booking_not_primary(app, user):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
event = Event.objects.create(
slug='event',
start_datetime=now(),
places=5,
waiting_list_places=5,
agenda=agenda,
)
primary = Booking.objects.create(event=event)
secondary = Booking.objects.create(event=event, primary_booking=primary)
app.authorization = ('Basic', ('john.doe', 'password'))
# resize a booking that is not primary
resp = app.post('/api/booking/%s/resize/' % secondary.pk, params={'count': 42})
assert resp.json['err'] == 2
assert resp.json['err_desc'] == 'secondary booking'
def test_resize_booking_cancelled(app, user):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
event = Event.objects.create(
slug='event',
start_datetime=now(),
places=5,
waiting_list_places=5,
agenda=agenda,
)
primary = Booking.objects.create(event=event)
primary.cancel()
# resize a booking that was cancelled before
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 42})
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'booking is cancelled'
def test_resize_booking_multi_events(app, user):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
event1 = Event.objects.create(
slug='event1',
start_datetime=now(),
places=5,
waiting_list_places=5,
agenda=agenda,
)
event2 = Event.objects.create(
slug='event2',
start_datetime=now(),
places=5,
waiting_list_places=5,
agenda=agenda,
)
primary = Booking.objects.create(event=event1, in_waiting_list=False)
Booking.objects.create(event=event2, in_waiting_list=False, primary_booking=primary)
app.authorization = ('Basic', ('john.doe', 'password'))
# resize a booking that is on multi events
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 42})
assert resp.json['err'] == 4
assert resp.json['err_desc'] == 'can not resize multi event booking'
def test_resize_booking_mixed_waiting_list(app, user):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
event = Event.objects.create(
slug='event',
start_datetime=now(),
places=5,
waiting_list_places=5,
agenda=agenda,
)
primary = Booking.objects.create(event=event, in_waiting_list=False)
Booking.objects.create(event=event, primary_booking=primary, in_waiting_list=True)
app.authorization = ('Basic', ('john.doe', 'password'))
# booking is in main list and waiting list in the same time
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 42})
assert resp.json['err'] == 5
assert resp.json['err_desc'] == 'can not resize booking: waiting list inconsistency'
def test_resize_booking(app, user):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
event = Event.objects.create(
slug='event',
start_datetime=now(),
places=5,
waiting_list_places=5,
agenda=agenda,
)
primary = Booking.objects.create(event=event, in_waiting_list=False)
# there is other bookings
Booking.objects.create(event=event, in_waiting_list=False)
app.authorization = ('Basic', ('john.doe', 'password'))
# increase
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 2})
assert resp.json['err'] == 0
assert Booking.objects.filter(in_waiting_list=False).count() == 3
assert Booking.objects.filter(primary_booking__isnull=True).count() == 2
assert Booking.objects.count() == 3
assert primary.secondary_booking_set.count() == 1
# too much
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 5})
assert resp.json['err'] == 3
assert resp.json['err_desc'] == 'sold out'
# max
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 4})
assert resp.json['err'] == 0
assert Booking.objects.filter(in_waiting_list=False).count() == 5
assert Booking.objects.filter(primary_booking__isnull=True).count() == 2
assert Booking.objects.count() == 5
assert primary.secondary_booking_set.count() == 3
# booking is overbooked - it is ok to increase
event.places = 4
event.save()
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 5})
assert resp.json['err'] == 0
assert Booking.objects.filter(in_waiting_list=False).count() == 6
assert Booking.objects.filter(primary_booking__isnull=True).count() == 2
assert Booking.objects.count() == 6
assert primary.secondary_booking_set.count() == 4
# decrease
# booking is overbooked, but it is always ok to do nothing
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 5})
assert resp.json['err'] == 0
assert Booking.objects.filter(in_waiting_list=False).count() == 6
assert Booking.objects.filter(primary_booking__isnull=True).count() == 2
assert Booking.objects.count() == 6
assert primary.secondary_booking_set.count() == 4
# or to decrease
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 4})
assert resp.json['err'] == 0
assert Booking.objects.filter(in_waiting_list=False).count() == 5
assert Booking.objects.filter(primary_booking__isnull=True).count() == 2
assert Booking.objects.count() == 5
assert primary.secondary_booking_set.count() == 3
# again
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 1})
assert resp.json['err'] == 0
assert Booking.objects.filter(in_waiting_list=False).count() == 2
assert Booking.objects.filter(primary_booking__isnull=True).count() == 2
assert Booking.objects.count() == 2
assert primary.secondary_booking_set.count() == 0
# no changes
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 1})
assert resp.json['err'] == 0
assert Booking.objects.filter(in_waiting_list=False).count() == 2
assert Booking.objects.filter(primary_booking__isnull=True).count() == 2
assert Booking.objects.count() == 2
assert primary.secondary_booking_set.count() == 0
def test_resize_booking_in_waiting_list(app, user):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
event = Event.objects.create(
slug='event',
start_datetime=now(),
places=5,
waiting_list_places=5,
agenda=agenda,
)
primary = Booking.objects.create(event=event, in_waiting_list=True)
# there is other bookings
Booking.objects.create(event=event, in_waiting_list=True)
app.authorization = ('Basic', ('john.doe', 'password'))
# increase
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 2})
assert resp.json['err'] == 0
assert Booking.objects.filter(in_waiting_list=True).count() == 3
assert Booking.objects.filter(primary_booking__isnull=True).count() == 2
assert Booking.objects.count() == 3
assert primary.secondary_booking_set.count() == 1
# too much
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 5})
assert resp.json['err'] == 3
assert resp.json['err_desc'] == 'sold out'
# max
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 4})
assert resp.json['err'] == 0
assert Booking.objects.filter(in_waiting_list=True).count() == 5
assert Booking.objects.filter(primary_booking__isnull=True).count() == 2
assert Booking.objects.count() == 5
assert primary.secondary_booking_set.count() == 3
# booking is overbooked (on waiting list, that shoud not happen)
event.waiting_list_places = 4
event.save()
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 5})
assert resp.json['err'] == 3
assert resp.json['err_desc'] == 'sold out'
# decrease
# booking is overbooked, but it is always ok to do nothing
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 4})
assert resp.json['err'] == 0
assert Booking.objects.filter(in_waiting_list=True).count() == 5
assert Booking.objects.filter(primary_booking__isnull=True).count() == 2
assert Booking.objects.count() == 5
assert primary.secondary_booking_set.count() == 3
# or to decrease
event.waiting_list_places = 3
event.save()
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 3})
assert resp.json['err'] == 0
assert Booking.objects.filter(in_waiting_list=True).count() == 4
assert Booking.objects.filter(primary_booking__isnull=True).count() == 2
assert Booking.objects.count() == 4
assert primary.secondary_booking_set.count() == 2
# again
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 1})
assert resp.json['err'] == 0
assert Booking.objects.filter(in_waiting_list=True).count() == 2
assert Booking.objects.filter(primary_booking__isnull=True).count() == 2
assert Booking.objects.count() == 2
assert primary.secondary_booking_set.count() == 0
# no changes
resp = app.post('/api/booking/%s/resize/' % primary.pk, params={'count': 1})
assert resp.json['err'] == 0
assert Booking.objects.filter(in_waiting_list=True).count() == 2
assert Booking.objects.filter(primary_booking__isnull=True).count() == 2
assert Booking.objects.count() == 2
assert primary.secondary_booking_set.count() == 0
def test_resize_booking_non_event_agenda(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
agenda = Agenda.objects.create(kind='meetings')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=1)
booking = Booking.objects.create(event=event)
app.post('/api/booking/%s/resize/' % booking.pk, params={'count': 42}, status=404)
agenda.kind = 'virtual'
agenda.save()
app.post('/api/booking/%s/resize/' % booking.pk, params={'count': 42}, status=404)
def test_anonymize_booking(app, user):
agenda = Agenda.objects.create(label='Foo bar')
event = Event.objects.create(start_datetime=now(), places=5, agenda=agenda)
Booking.objects.create(event=event, label='not to anonymize')
booking = Booking.objects.create(event=event, label='test')
Booking.objects.create(event=event, label='test secondary', primary_booking=booking)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/booking/%s/anonymize/' % booking.pk)
assert resp.json['err'] == 0
assert Booking.objects.filter(anonymization_datetime__isnull=False).count() == 2
assert Booking.objects.filter(label='').count() == 2