chrono/tests/api/test_booking.py

1501 lines
62 KiB
Python

import datetime
from unittest import mock
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, BookingColor, Category, Desk, Event, MeetingType
from chrono.utils.lingo import CheckType
pytestmark = pytest.mark.django_db
def test_booking_ics(app, some_data, meetings_agenda, user):
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
# 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
# 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')
meetings_event = Event.objects.create(agenda=meetings_agenda, start_datetime=now(), places=1)
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) == 2
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': '',
'user_was_present': None,
'user_absence_reason': None,
'user_presence_reason': None,
'use_color_for': None,
'extra_data': None,
'cancellation_datetime': None,
'creation_datetime': localtime(meetings_booking1.creation_datetime).isoformat(),
},
{
'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(),
},
{
'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(),
},
]
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(7)),
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'
@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
@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
@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
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
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