1849 lines
75 KiB
Python
1849 lines
75 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,
|
|
BookingCheck,
|
|
BookingColor,
|
|
Category,
|
|
Desk,
|
|
Event,
|
|
MeetingType,
|
|
Subscription,
|
|
)
|
|
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
|
|
|
|
|
|
@pytest.mark.freeze_time('2023-09-18 14:00')
|
|
def test_bookings_ics(app, user):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
|
event = Event.objects.create(
|
|
label='Event A', agenda=agenda, start_datetime=now() + datetime.timedelta(days=3), places=10
|
|
)
|
|
Booking.objects.create(event=event, user_external_id='enfant-1234')
|
|
|
|
agenda = Agenda.objects.create(label='Foo bar 2', kind='events')
|
|
event = Event.objects.create(
|
|
label='Event B', agenda=agenda, start_datetime=now() + datetime.timedelta(days=4), places=10
|
|
)
|
|
Booking.objects.create(event=event, user_external_id='enfant-1234')
|
|
|
|
resp = app.get('/api/bookings/ics/')
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'missing param user_external_id'
|
|
|
|
resp = app.get('/api/bookings/ics/', params={'user_external_id': 'enfant-1234'})
|
|
assert 'BEGIN:VCALENDAR' in resp.text
|
|
assert resp.text.count('UID') == 2
|
|
assert 'DTSTART:20230921' in resp.text
|
|
assert 'DTSTART:20230922' in resp.text
|
|
|
|
resp = app.get('/api/bookings/ics/', params={'user_external_id': 'enfant-1234', 'agenda': 'foo-bar'})
|
|
assert resp.text.count('UID') == 1
|
|
assert 'DTSTART:20230921' in resp.text
|
|
assert 'DTSTART:20230922' not in resp.text
|
|
|
|
resp = app.get('/api/bookings/ics/', params={'user_external_id': 'enfant-1234', 'agenda': 'xxx'})
|
|
assert 'BEGIN:VCALENDAR' in resp.text
|
|
assert resp.text.count('UID') == 0
|
|
|
|
|
|
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_booking1.mark_user_presence()
|
|
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) == 6
|
|
|
|
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': True,
|
|
'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_count_param(app, user):
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
agenda = Agenda.objects.create(label='test', kind='events')
|
|
event = Event.objects.create(
|
|
label='EVT test', agenda=agenda, start_datetime=now() + datetime.timedelta(days=3), places=42
|
|
)
|
|
|
|
params = {'user_external_id': '42', 'count': 13}
|
|
resp = app.post(f'/api/agenda/{agenda.pk}/fillslot/{event.pk}/', params=params)
|
|
resp = app.get(f'/api/booking/{resp.json["booking_id"]}/')
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['places_count'] == 13
|
|
|
|
params['count'] = 1
|
|
resp = app.post(f'/api/agenda/{agenda.pk}/fillslot/{event.pk}/', params=params)
|
|
resp = app.get(f'/api/booking/{resp.json["booking_id"]}/')
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['places_count'] == 1
|
|
|
|
del params['count']
|
|
resp = app.post(f'/api/agenda/{agenda.pk}/fillslot/{event.pk}/', params=params)
|
|
resp = app.get(f'/api/booking/{resp.json["booking_id"]}/')
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['places_count'] == 1
|
|
|
|
|
|
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')
|
|
booking2.mark_user_presence()
|
|
booking3 = Booking.objects.create(event=event, user_external_id='42')
|
|
booking3.mark_user_absence()
|
|
|
|
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 = Booking.objects.create(event=event, user_external_id='42')
|
|
booking.mark_user_absence()
|
|
booking2 = Booking.objects.create(event=event, user_external_id='42')
|
|
booking2.mark_user_absence(check_type_slug='foo-bar', check_type_label='Foo bar')
|
|
booking3 = Booking.objects.create(event=event, user_external_id='42')
|
|
booking3.mark_user_presence(check_type_slug='foo-bar-2', 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']] == []
|
|
BookingCheck.objects.update(presence=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 = Booking.objects.create(event=event, user_external_id='42')
|
|
booking.mark_user_presence()
|
|
booking2 = Booking.objects.create(event=event, user_external_id='42')
|
|
booking2.mark_user_presence(check_type_slug='foo-bar', check_type_label='Foo bar')
|
|
booking3 = Booking.objects.create(event=event, user_external_id='42')
|
|
booking3.mark_user_absence(check_type_slug='foo-bar-2', 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']] == []
|
|
BookingCheck.objects.update(presence=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)
|
|
if flag is True:
|
|
booking.mark_user_presence(check_type_slug='foo-bar')
|
|
elif flag is False:
|
|
booking.mark_user_absence(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_get_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
|
|
app.get('/api/booking/0/', status=404)
|
|
|
|
# cancelled
|
|
booking.cancel()
|
|
resp = app.get('/api/booking/%s/' % booking.pk)
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['cancellation_datetime']
|
|
|
|
# not a primary booking
|
|
secondary = Booking.objects.create(event=event, primary_booking=booking)
|
|
resp = app.get('/api/booking/%s/' % secondary.pk)
|
|
assert resp.json['err'] == 2
|
|
assert resp.json['err_desc'] == 'secondary booking'
|
|
|
|
# in waiting list
|
|
booking = Booking.objects.create(event=event, in_waiting_list=True)
|
|
resp = app.get('/api/booking/%s/' % booking.pk)
|
|
assert resp.json['err'] == 0
|
|
|
|
|
|
def test_booking_api_patch_error(app, user):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
|
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
|
|
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
# unknown
|
|
app.patch('/api/booking/0/', status=404)
|
|
|
|
# cancelled
|
|
booking = Booking.objects.create(event=event)
|
|
booking.cancel()
|
|
resp = app.patch('/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)
|
|
resp = app.patch('/api/booking/%s/' % secondary.pk)
|
|
assert resp.json['err'] == 2
|
|
assert resp.json['err_desc'] == 'secondary booking'
|
|
|
|
# in waiting list
|
|
booking = Booking.objects.create(event=event, in_waiting_list=True)
|
|
|
|
resp = app.patch_json('/api/booking/%s/' % booking.pk, {'label': 'foobar', 'foo': 'bar'})
|
|
assert resp.json['err'] == 0
|
|
|
|
resp = app.patch_json('/api/booking/%s/' % booking.pk, {'user_was_present': True})
|
|
assert resp.json['err'] == 3
|
|
assert resp.json['err_desc'] == 'booking is in waiting list'
|
|
|
|
|
|
def test_booking_api_delete_error(app, user):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
|
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
|
|
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
# unknown
|
|
app.delete('/api/booking/0/', status=404)
|
|
|
|
# cancelled
|
|
booking = Booking.objects.create(event=event)
|
|
booking.cancel()
|
|
resp = app.delete('/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)
|
|
resp = app.delete('/api/booking/%s/' % secondary.pk)
|
|
assert resp.json['err'] == 2
|
|
assert resp.json['err_desc'] == 'secondary booking'
|
|
|
|
# in waiting list
|
|
booking = Booking.objects.create(event=event, in_waiting_list=True)
|
|
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()
|
|
if flag is not None:
|
|
assert booking.user_check.presence == flag
|
|
else:
|
|
assert not booking.user_check
|
|
|
|
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()
|
|
if flag is not None:
|
|
assert booking.user_check.presence == flag
|
|
else:
|
|
assert not booking.user_check
|
|
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 not booking.user_check
|
|
|
|
# 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()
|
|
if flag is not None:
|
|
assert booking.user_check.presence == flag
|
|
else:
|
|
assert not booking.user_check
|
|
# secondary bookings are left untouched
|
|
assert list(booking.secondary_booking_set.values_list('user_checks', flat=True)) == [None, None]
|
|
other_booking.refresh_from_db()
|
|
assert not other_booking.user_check # 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)
|
|
booking.mark_user_absence()
|
|
|
|
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)
|
|
Booking.objects.create(event=event, primary_booking=booking)
|
|
# 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'
|
|
# secondary bookings are left unchanged
|
|
assert list(booking.secondary_booking_set.values_list('user_checks', flat=True)) == [None, None]
|
|
other_booking.refresh_from_db()
|
|
assert not other_booking.user_check # not changed
|
|
|
|
# presence is True, can not set user_absence_reason
|
|
BookingCheck.objects.update(presence=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 presence 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_check.presence 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)
|
|
booking.mark_user_presence()
|
|
|
|
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)
|
|
Booking.objects.create(event=event, primary_booking=booking)
|
|
# 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'
|
|
# secondary bookings are left unchanged
|
|
assert list(booking.secondary_booking_set.values_list('user_checks', flat=True)) == [None, None]
|
|
other_booking.refresh_from_db()
|
|
assert not other_booking.user_check # not changed
|
|
|
|
# presence is False, can not set user_presence_reason
|
|
BookingCheck.objects.update(presence=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 presence 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_check.presence 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)
|
|
booking.mark_user_presence()
|
|
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.patch_json('/api/booking/%s/' % booking.pk, params={'foo': 'bar'})
|
|
booking.refresh_from_db()
|
|
assert booking.user_check.presence 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_check.presence 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_check.presence 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_check.presence is True # not changed
|
|
assert booking.extra_data == {'foo': None, 'foooo': 'baz'}
|
|
|
|
# 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={'foooo': 'baz', 'foo': None})
|
|
assert booking.user_check.presence 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'},
|
|
]
|
|
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_check.presence 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
|
|
|
|
|
|
def test_partial_bookings_check(app, user):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events', partial_bookings=True)
|
|
start_datetime = make_aware(datetime.datetime(2023, 5, 2, 8, 0))
|
|
event = Event.objects.create(
|
|
label='Event', start_datetime=start_datetime, end_time=datetime.time(18, 00), places=10, agenda=agenda
|
|
)
|
|
booking = Booking.objects.create(
|
|
user_external_id='user_id',
|
|
user_first_name='Jane',
|
|
user_last_name='Doe',
|
|
start_time=datetime.time(9, 00),
|
|
end_time=datetime.time(17, 00),
|
|
event=event,
|
|
)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
params = {
|
|
'user_external_id': 'user_id',
|
|
'timestamp': '2023-05-02 10:30',
|
|
}
|
|
resp = app.post('/api/agenda/%s/partial-bookings-check/' % agenda.slug, params=params)
|
|
assert resp.json['err'] == 0
|
|
|
|
check = BookingCheck.objects.get()
|
|
assert check.booking == booking
|
|
assert check.presence is True
|
|
assert check.start_time == datetime.time(10, 30)
|
|
assert check.end_time is None
|
|
|
|
params['timestamp'] = '2023-05-02 15:00'
|
|
resp = app.post('/api/agenda/%s/partial-bookings-check/' % agenda.slug, params=params)
|
|
assert resp.json['err'] == 0
|
|
|
|
check = BookingCheck.objects.get()
|
|
assert check.booking == booking
|
|
assert check.presence is True
|
|
assert check.start_time == datetime.time(10, 30)
|
|
assert check.end_time == datetime.time(15, 00)
|
|
|
|
# third check is forbidden
|
|
params['timestamp'] = '2023-05-02 16:00'
|
|
resp = app.post('/api/agenda/%s/partial-bookings-check/' % agenda.slug, params=params)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'no booking to check'
|
|
|
|
# check outside of opening hours is forbidden
|
|
params['timestamp'] = '2023-05-02 19:00'
|
|
resp = app.post('/api/agenda/%s/partial-bookings-check/' % agenda.slug, params=params)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'check time outside of opening hours'
|
|
|
|
# no booking for user
|
|
params['user_external_id'] = 'xxx'
|
|
params['timestamp'] = '2023-05-02 15:00'
|
|
resp = app.post('/api/agenda/%s/partial-bookings-check/' % agenda.slug, params=params, status=404)
|
|
|
|
# no event during check time
|
|
params['user_external_id'] = 'user_id'
|
|
params['timestamp'] = '2023-06-02 15:00'
|
|
resp = app.post('/api/agenda/%s/partial-bookings-check/' % agenda.slug, params=params, status=404)
|
|
|
|
# event check is locked
|
|
event.check_locked = True
|
|
event.save()
|
|
params['timestamp'] = '2023-05-02 15:00'
|
|
resp = app.post('/api/agenda/%s/partial-bookings-check/' % agenda.slug, params=params, status=404)
|
|
|
|
|
|
def test_partial_bookings_check_ignore_absence(app, user):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events', partial_bookings=True)
|
|
start_datetime = make_aware(datetime.datetime(2023, 5, 2, 8, 0))
|
|
event = Event.objects.create(
|
|
label='Event', start_datetime=start_datetime, end_time=datetime.time(18, 00), places=10, agenda=agenda
|
|
)
|
|
booking = Booking.objects.create(
|
|
user_external_id='user_id',
|
|
user_first_name='Jane',
|
|
user_last_name='Doe',
|
|
start_time=datetime.time(9, 00),
|
|
end_time=datetime.time(17, 00),
|
|
event=event,
|
|
)
|
|
booking.mark_user_absence(start_time=datetime.time(9, 00), end_time=datetime.time(12, 00))
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
params = {
|
|
'user_external_id': 'user_id',
|
|
'timestamp': '2023-05-02 12:30',
|
|
}
|
|
resp = app.post('/api/agenda/%s/partial-bookings-check/' % agenda.slug, params=params)
|
|
|
|
check = BookingCheck.objects.filter(presence=True).get()
|
|
assert check.booking == booking
|
|
assert check.start_time == datetime.time(12, 30)
|
|
assert check.end_time is None
|
|
|
|
params['timestamp'] = '2023-05-02 15:00'
|
|
resp = app.post('/api/agenda/%s/partial-bookings-check/' % agenda.slug, params=params)
|
|
assert resp.json['err'] == 0
|
|
|
|
check = BookingCheck.objects.filter(presence=True).get()
|
|
assert check.booking == booking
|
|
assert check.start_time == datetime.time(12, 30)
|
|
assert check.end_time == datetime.time(15, 00)
|
|
|
|
|
|
def test_partial_bookings_check_multiple_bookings(app, user):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events', partial_bookings=True)
|
|
start_datetime = make_aware(datetime.datetime(2023, 5, 2, 8, 0))
|
|
event = Event.objects.create(
|
|
label='Event', start_datetime=start_datetime, end_time=datetime.time(18, 00), places=10, agenda=agenda
|
|
)
|
|
first_booking = Booking.objects.create(
|
|
user_external_id='user_id',
|
|
user_first_name='Jane',
|
|
user_last_name='Doe',
|
|
start_time=datetime.time(9, 00),
|
|
end_time=datetime.time(12, 00),
|
|
event=event,
|
|
)
|
|
second_booking = Booking.objects.create(
|
|
user_external_id='user_id',
|
|
user_first_name='Jane',
|
|
user_last_name='Doe',
|
|
start_time=datetime.time(14, 00),
|
|
end_time=datetime.time(18, 00),
|
|
event=event,
|
|
)
|
|
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
for i in range(4):
|
|
params = {
|
|
'user_external_id': 'user_id',
|
|
'timestamp': '2023-05-02 1%s:30' % i,
|
|
}
|
|
resp = app.post('/api/agenda/%s/partial-bookings-check/' % agenda.slug, params=params)
|
|
assert resp.json['err'] == 0
|
|
|
|
assert first_booking.user_check.start_time == datetime.time(10, 30)
|
|
assert first_booking.user_check.end_time == datetime.time(11, 30)
|
|
assert second_booking.user_check.start_time == datetime.time(12, 30)
|
|
assert second_booking.user_check.end_time == datetime.time(13, 30)
|
|
|
|
|
|
def test_partial_bookings_check_subscription(app, user):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events', partial_bookings=True)
|
|
start_datetime = make_aware(datetime.datetime(2023, 5, 2, 8, 0))
|
|
event = Event.objects.create(
|
|
label='Event', start_datetime=start_datetime, end_time=datetime.time(18, 00), places=10, agenda=agenda
|
|
)
|
|
Subscription.objects.create(
|
|
user_external_id='user_id',
|
|
user_first_name='Jane',
|
|
user_last_name='Doe',
|
|
date_start=event.start_datetime,
|
|
date_end=event.start_datetime + datetime.timedelta(days=2),
|
|
agenda=agenda,
|
|
)
|
|
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
params = {
|
|
'user_external_id': 'user_id',
|
|
'timestamp': '2023-05-02 10:30',
|
|
}
|
|
resp = app.post('/api/agenda/%s/partial-bookings-check/' % agenda.slug, params=params)
|
|
assert resp.json['err'] == 0
|
|
|
|
params['timestamp'] = '2023-05-02 15:00'
|
|
resp = app.post('/api/agenda/%s/partial-bookings-check/' % agenda.slug, params=params)
|
|
assert resp.json['err'] == 0
|
|
|
|
check = BookingCheck.objects.get()
|
|
assert check.booking.user_external_id == 'user_id'
|
|
assert check.presence is True
|
|
assert check.start_time == datetime.time(10, 30)
|
|
assert check.end_time == datetime.time(15, 00)
|