1740 lines
72 KiB
Python
1740 lines
72 KiB
Python
import codecs
|
|
import datetime
|
|
from unittest import mock
|
|
|
|
import pytest
|
|
import requests
|
|
from django.core.management import call_command
|
|
from django.db import connection
|
|
from django.test.utils import CaptureQueriesContext
|
|
from django.utils.timezone import localtime, make_aware, now
|
|
from webtest import Upload
|
|
|
|
from chrono.agendas.models import AbsenceReason, AbsenceReasonGroup, Agenda, Booking, Desk, Event
|
|
|
|
from .test_all import login
|
|
|
|
pytestmark = pytest.mark.django_db
|
|
|
|
|
|
def test_add_event(app, admin_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.maximal_booking_delay = 0
|
|
agenda.save()
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
assert "This agenda doesn't have any event yet." in resp.text
|
|
year = now().year + 1
|
|
resp = resp.click('New Event')
|
|
resp.form['start_datetime_0'] = '%s-02-15' % year
|
|
resp.form['start_datetime_1'] = '17:00'
|
|
resp.form['places'] = 10
|
|
resp = resp.form.submit()
|
|
resp = resp.follow()
|
|
event = Event.objects.get(places=10)
|
|
assert event.publication_datetime is None
|
|
assert "This agenda doesn't have any event yet." not in resp.text
|
|
assert '/manage/agendas/%s/events/%s/' % (agenda.id, event.id) in resp.text
|
|
assert ('Feb. 15, %s, 5 p.m.' % year) in resp.text
|
|
|
|
resp_datetimes = app.get('/api/agenda/%s/datetimes/' % agenda.id)
|
|
assert resp_datetimes.json['data'][0]['text'] == 'Feb. 15, %s, 5 p.m.' % year
|
|
assert resp_datetimes.json['data'][0]['datetime'] == '%s-02-15 17:00:00' % year
|
|
|
|
# add with errors in datetime parts
|
|
for parts in (
|
|
('', ''),
|
|
('invalid', ''),
|
|
('', 'invalid'),
|
|
('2019-02-24', 'invalid'),
|
|
('invalid', '17:00'),
|
|
):
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
resp = resp.click('New Event')
|
|
resp.form['start_datetime_0'] = parts[0]
|
|
resp.form['start_datetime_1'] = parts[1]
|
|
resp.form['places'] = 10
|
|
resp = resp.form.submit()
|
|
assert (
|
|
resp.text.count('Enter a valid date')
|
|
or resp.text.count('Enter a valid time') == 1
|
|
or resp.text.count('This field is required.') >= 1
|
|
)
|
|
|
|
|
|
def test_add_event_on_missing_agenda(app, admin_user):
|
|
app = login(app)
|
|
app.get('/manage/agendas/%s/add-event' % '0', status=404)
|
|
|
|
|
|
def test_add_event_as_manager(app, manager_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.view_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
app = login(app, username='manager', password='manager')
|
|
resp = app.get('/manage/agendas/%s/' % agenda.id, status=302)
|
|
app.get('/manage/agendas/%s/add-event' % agenda.id, status=403)
|
|
|
|
agenda.edit_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
assert '<h2>Settings' in resp.text
|
|
resp = resp.click('New Event')
|
|
resp.form['start_datetime_0'] = '2016-02-15'
|
|
resp.form['start_datetime_1'] = '17:00'
|
|
resp.form['places'] = 10
|
|
resp = resp.form.submit()
|
|
resp = resp.follow()
|
|
event = Event.objects.get(places=10)
|
|
assert "This agenda doesn't have any event yet." not in resp.text
|
|
assert '/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id) in resp.text
|
|
assert 'Feb. 15, 2016, 5 p.m.' in resp.text
|
|
assert event.duration is None
|
|
assert event.end_datetime is None
|
|
|
|
resp = resp.click('New Event')
|
|
resp.form['start_datetime_0'] = '2016-02-15'
|
|
resp.form['start_datetime_1'] = '17:00'
|
|
resp.form['duration'] = 45
|
|
resp.form['places'] = 12
|
|
resp = resp.form.submit()
|
|
resp = resp.follow()
|
|
event = Event.objects.get(places=12)
|
|
assert event.duration == 45
|
|
assert event.end_datetime == event.start_datetime + datetime.timedelta(minutes=45)
|
|
|
|
|
|
def test_edit_event(settings, app, admin_user):
|
|
settings.LANGUAGE_CODE = 'fr-fr' # check date initial value format
|
|
agenda = Agenda.objects.create(label='Foo bar')
|
|
event = Event.objects.create(
|
|
label='Foo',
|
|
start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)),
|
|
places=20,
|
|
agenda=agenda,
|
|
)
|
|
event2 = Event.objects.create(
|
|
label='Other',
|
|
start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)),
|
|
places=20,
|
|
agenda=agenda,
|
|
)
|
|
assert event.duration is None
|
|
assert event.end_datetime is None
|
|
other_agenda = Agenda.objects.create(label='Foo bar')
|
|
other_event = Event.objects.create(
|
|
label='Foo',
|
|
start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)),
|
|
places=20,
|
|
agenda=other_agenda,
|
|
)
|
|
assert event.slug == other_event.slug
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.pk, event.pk))
|
|
assert resp.form['start_datetime_0'].value == '2016-02-15'
|
|
assert resp.form['start_datetime_1'].value == '17:00'
|
|
assert resp.form['publication_datetime_0'].value == ''
|
|
assert resp.form['publication_datetime_1'].value == ''
|
|
assert resp.form['duration'].value == ''
|
|
assert resp.form['description'].value == ''
|
|
resp.form['start_datetime_0'] = '2016-02-16'
|
|
resp.form['start_datetime_1'] = '17:00'
|
|
resp.form['publication_datetime_0'] = '2020-05-11'
|
|
resp.form['publication_datetime_1'] = '12:00'
|
|
resp.form['duration'].value = 45
|
|
resp.form['places'] = 20
|
|
resp.form['description'] = 'A description'
|
|
resp = resp.form.submit()
|
|
settings.LANGUAGE_CODE = 'en'
|
|
resp = resp.follow()
|
|
assert '/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id) in resp.text
|
|
assert 'Feb. 16, 2016, 5 p.m.' in resp.text
|
|
event.refresh_from_db()
|
|
assert event.places == 20
|
|
assert str(event.publication_datetime) == '2020-05-11 10:00:00+00:00'
|
|
assert str(event.publication_datetime.tzinfo) == 'UTC'
|
|
assert event.duration == 45
|
|
assert event.end_datetime == event.start_datetime + datetime.timedelta(minutes=45)
|
|
assert event.description == 'A description'
|
|
assert event.slug == other_event.slug
|
|
|
|
# check slug edition
|
|
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.pk, event.pk))
|
|
resp.form['slug'] = event2.slug
|
|
resp = resp.form.submit()
|
|
assert resp.context['form'].errors['slug'] == ['Another event exists with the same identifier.']
|
|
|
|
|
|
def test_event_digit_slug(app, admin_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.maximal_booking_delay = 0
|
|
agenda.save()
|
|
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
|
|
app = login(app)
|
|
|
|
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp.form['slug'] = 42
|
|
resp = resp.form.submit()
|
|
assert 'value cannot be a number' in resp.text
|
|
|
|
|
|
def test_edit_missing_event(app, admin_user):
|
|
app = login(app)
|
|
app.get('/manage/agendas/999/', status=404)
|
|
|
|
|
|
def test_edit_event_as_manager(app, manager_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.view_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
event = Event.objects.create(
|
|
start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)),
|
|
places=20,
|
|
agenda=agenda,
|
|
publication_datetime=make_aware(datetime.datetime(2020, 5, 11)),
|
|
)
|
|
app = login(app, username='manager', password='manager')
|
|
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id), status=403)
|
|
|
|
agenda.edit_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
resp = resp.click('Feb. 15, 2016, 5 p.m.')
|
|
assert resp.form['start_datetime_0'].value == '2016-02-15'
|
|
assert resp.form['start_datetime_1'].value == '17:00'
|
|
assert resp.form['publication_datetime_0'].value == '2020-05-11'
|
|
assert resp.form['publication_datetime_1'].value == '00:00'
|
|
resp.form['start_datetime_0'] = '2016-02-16'
|
|
resp.form['start_datetime_1'] = '17:00'
|
|
resp.form['publication_datetime_0'] = ''
|
|
resp.form['publication_datetime_1'] = ''
|
|
resp.form['places'] = 20
|
|
resp = resp.form.submit()
|
|
resp = resp.follow()
|
|
assert '/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id) in resp.text
|
|
assert 'Feb. 16, 2016, 5 p.m.' in resp.text
|
|
event.refresh_from_db()
|
|
assert event.publication_datetime is None
|
|
|
|
|
|
def test_edit_recurring_event(settings, app, admin_user, freezer):
|
|
freezer.move_to('2021-01-12 12:10')
|
|
agenda = Agenda.objects.create(
|
|
label='Foo bar', kind='events', minimal_booking_delay=15, maximal_booking_delay=30
|
|
)
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
event = Event.objects.create(start_datetime=now(), places=10, agenda=agenda)
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp.form['frequency'] = 'recurring'
|
|
resp.form['recurrence_days'] = [localtime().weekday()]
|
|
resp = resp.form.submit()
|
|
|
|
# detail page doesn't exist
|
|
resp = app.get('/manage/agendas/%s/events/%s/' % (agenda.id, event.id), status=404)
|
|
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
assert 'On Tuesday at 1:10 p.m.' in resp.text
|
|
# event is bookable regardless of minimal_booking_delay, since it has bookable recurrences
|
|
assert len(resp.pyquery.find('.bookable')) == 1
|
|
|
|
# maximal_booking_delay is accounted for, because no recurrences are bookable
|
|
freezer.move_to('2020-11-12')
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
assert len(resp.pyquery.find('.not-bookable')) == 1
|
|
|
|
# editing recurring event updates event recurrences
|
|
event.refresh_from_db()
|
|
event_recurrence = event.get_or_create_event_recurrence(event.start_datetime)
|
|
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp.form['places'] = 20
|
|
resp = resp.form.submit().follow()
|
|
event_recurrence.refresh_from_db()
|
|
assert event_recurrence.places == 20
|
|
|
|
# but some fields should not be updated
|
|
assert event_recurrence.slug != event.slug
|
|
assert not event_recurrence.recurrence_days
|
|
|
|
# changing recurrence attribute removes event recurrences
|
|
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp.form['frequency'] = 'unique'
|
|
resp = resp.form.submit().follow()
|
|
assert not Event.objects.filter(primary_event=event).exists()
|
|
|
|
# same goes with changing slug
|
|
event.recurrence = 'weekly'
|
|
event.save()
|
|
event_recurrence = event.get_or_create_event_recurrence(event.start_datetime)
|
|
assert Event.objects.filter(primary_event=event).exists()
|
|
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp.form['slug'] = 'hop'
|
|
resp = resp.form.submit().follow()
|
|
assert not Event.objects.filter(primary_event=event).exists()
|
|
|
|
# changing recurring attribute or slug is forbidden if there are bookings for future recurrences
|
|
event_recurrence = event.get_or_create_event_recurrence(event.start_datetime + datetime.timedelta(days=7))
|
|
Booking.objects.create(event=event_recurrence)
|
|
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
assert 'disabled' in resp.form['frequency'].attrs
|
|
assert all('disabled' in resp.form.get('recurrence_days', index=i).attrs for i in range(7))
|
|
assert 'disabled' in resp.form['recurrence_week_interval'].attrs
|
|
assert 'disabled' in resp.form['slug'].attrs
|
|
assert 'disabled' in resp.form['start_datetime_0'].attrs
|
|
assert 'disabled' in resp.form['start_datetime_1'].attrs
|
|
|
|
# changing it anyway doesn't work
|
|
resp.form['slug'] = 'changed'
|
|
resp = resp.form.submit()
|
|
assert not Event.objects.filter(slug='changed').exists()
|
|
|
|
# deletion of event recurrence is not allowed
|
|
resp = app.get('/manage/agendas/%s/events/%s/' % (agenda.id, event_recurrence.id))
|
|
assert 'Delete' not in resp.text
|
|
|
|
resp = resp.click('Options')
|
|
assert 'Delete' not in resp.text
|
|
assert {
|
|
'slug',
|
|
'frequency',
|
|
'recurrence_days',
|
|
'recurence_weekly_interval',
|
|
'recurrence_end_date',
|
|
'publication_datetime_0',
|
|
'publication_datetime_1',
|
|
}.isdisjoint(resp.form.fields)
|
|
|
|
|
|
def test_edit_recurring_event_with_end_date(settings, app, admin_user, freezer):
|
|
freezer.move_to('2021-01-12 12:10')
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
|
event = Event.objects.create(
|
|
start_datetime=now(), places=10, recurrence_days=list(range(7)), agenda=agenda
|
|
)
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp.form['recurrence_end_date'] = (localtime() + datetime.timedelta(days=5)).strftime('%Y-%m-%d')
|
|
resp = resp.form.submit()
|
|
|
|
# recurrences are created automatically
|
|
event = Event.objects.get(recurrence_days__isnull=False)
|
|
assert Event.objects.filter(primary_event=event).count() == 5
|
|
assert Event.objects.filter(primary_event=event, start_datetime=now()).exists()
|
|
|
|
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp.form['start_datetime_1'] = (localtime() + datetime.timedelta(hours=1)).strftime('%H:%M')
|
|
resp = resp.form.submit()
|
|
assert Event.objects.filter(primary_event=event).count() == 5
|
|
assert Event.objects.filter(
|
|
primary_event=event, start_datetime=now() + datetime.timedelta(hours=1)
|
|
).exists()
|
|
# old recurrences were deleted
|
|
assert not Event.objects.filter(primary_event=event, start_datetime=now()).exists()
|
|
|
|
# if start datetime of a recurrence is edited, it stays that way
|
|
recurrence = event.recurrences.first()
|
|
recurrence.start_datetime += datetime.timedelta(hours=1)
|
|
recurrence.save()
|
|
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp = resp.form.submit()
|
|
assert Event.objects.filter(primary_event=event).count() == 5
|
|
assert Event.objects.filter(primary_event=event, start_datetime=recurrence.start_datetime).count() == 1
|
|
# ensure recurrence_end_date has not been propagated
|
|
assert not Event.objects.filter(primary_event=event, recurrence_end_date__isnull=False).exists()
|
|
|
|
# editing recurrence_end_date is permitted as long as bookings are not impacted
|
|
event_recurrence = Event.objects.get(primary_event=event, start_datetime__day=15)
|
|
Booking.objects.create(event=event_recurrence)
|
|
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp.form['recurrence_end_date'] = (localtime() + datetime.timedelta(days=6)).strftime('%Y-%m-%d')
|
|
resp = resp.form.submit()
|
|
assert Event.objects.filter(primary_event=event).count() == 6
|
|
|
|
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp.form['recurrence_end_date'] = (localtime() + datetime.timedelta(days=4)).strftime('%Y-%m-%d')
|
|
resp = resp.form.submit()
|
|
assert Event.objects.filter(primary_event=event).count() == 4
|
|
|
|
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp.form['recurrence_end_date'] = (localtime() + datetime.timedelta(days=2)).strftime('%Y-%m-%d')
|
|
resp = resp.form.submit()
|
|
assert Event.objects.filter(primary_event=event).count() == 4
|
|
assert 'Bookings exist after this date' in resp.text
|
|
|
|
|
|
def test_booked_places(app, admin_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.save()
|
|
event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=10, agenda=agenda)
|
|
event.save()
|
|
Booking(event=event).save()
|
|
Booking(event=event).save()
|
|
app = login(app)
|
|
|
|
day = event.start_datetime
|
|
resp = app.get('/manage/agendas/%s/%d/%d/' % (agenda.id, day.year, day.month), status=200)
|
|
assert '8 remaining places' in resp.text
|
|
assert '(2/10 bookings)' in resp.text
|
|
|
|
|
|
def test_event_classes(app, admin_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.save()
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=10, agenda=agenda)
|
|
event.save()
|
|
for _ in range(2):
|
|
Booking(event=event).save()
|
|
app = login(app)
|
|
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
assert 'full' not in resp.text
|
|
assert 'overbooking' not in resp.text
|
|
resp = app.get('/manage/agendas/%s/events/%s/' % (agenda.pk, event.pk))
|
|
assert '<span class="tag">Full</span>' not in resp
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert '<span class="tag">Full</span>' not in resp
|
|
|
|
for _ in range(8):
|
|
Booking(event=event).save()
|
|
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
assert 'full' in resp.text
|
|
assert 'overbooking' not in resp.text
|
|
resp = app.get('/manage/agendas/%s/events/%s/' % (agenda.pk, event.pk))
|
|
assert '<span class="tag">Full</span>' in resp
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert '<span class="tag">Full</span>' in resp
|
|
|
|
Booking(event=event).save()
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
assert 'full' in resp.text
|
|
assert 'overbooking' in resp.text
|
|
|
|
|
|
def test_event_detail_backoffice_url_translation(app, admin_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.save()
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=10, agenda=agenda)
|
|
event.save()
|
|
Booking.objects.create(event=event, backoffice_url='publik://default/foo/')
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/events/%s/' % (agenda.pk, event.pk))
|
|
assert 'http://example.org/foo/' in resp.text
|
|
|
|
|
|
def test_delete_event(app, admin_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.save()
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=10, agenda=agenda)
|
|
event.save()
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
resp = resp.click(href='/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp = resp.click('Delete')
|
|
resp = resp.form.submit()
|
|
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
|
|
assert Event.objects.count() == 0
|
|
|
|
|
|
def test_delete_busy_event(app, admin_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.save()
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
event = Event(start_datetime=now() + datetime.timedelta(days=10), places=10, agenda=agenda)
|
|
event.save()
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
resp = resp.click(href='/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp = resp.click('Delete')
|
|
assert 'Are you sure you want to delete this event?' in resp.text
|
|
|
|
booking = Booking(event=event)
|
|
booking.save()
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
resp = resp.click(href='/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp = resp.click('Delete')
|
|
assert 'This cannot be removed' in resp.text
|
|
|
|
booking.cancellation_datetime = now()
|
|
booking.save()
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
resp = resp.click(href='/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp = resp.click('Delete')
|
|
assert 'Are you sure you want to delete this event?' in resp.text
|
|
|
|
# suddenly the booking is no longer cancelled, but the admin clicks on the
|
|
# delete button.
|
|
booking.cancellation_datetime = None
|
|
booking.save()
|
|
resp = resp.form.submit(status=403)
|
|
|
|
|
|
def test_delete_recurring_event(app, admin_user, freezer):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
start_datetime = now() + datetime.timedelta(days=10)
|
|
event = Event.objects.create(
|
|
start_datetime=start_datetime, places=10, agenda=agenda, recurrence_days=[start_datetime.weekday()]
|
|
)
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
resp = resp.click(href='/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp = resp.click('Delete')
|
|
assert 'Are you sure you want to delete this event?' in resp.text
|
|
|
|
event_recurrence = event.get_or_create_event_recurrence(event.start_datetime)
|
|
booking = Booking.objects.create(event=event_recurrence)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
resp = resp.click(href='/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp = resp.click('Delete')
|
|
assert 'This cannot be removed' in resp.text
|
|
|
|
booking.cancellation_datetime = now()
|
|
booking.save()
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
resp = resp.click(href='/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp = resp.click('Delete')
|
|
assert 'Are you sure you want to delete this event?' in resp.text
|
|
|
|
booking.cancellation_datetime = None
|
|
booking.save()
|
|
freezer.move_to(now() + datetime.timedelta(days=11))
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
resp = resp.click(href='/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp = resp.click('Delete')
|
|
assert 'Are you sure you want to delete this event?' in resp.text
|
|
|
|
|
|
def test_delete_event_as_manager(app, manager_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.edit_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=10, agenda=agenda)
|
|
event.save()
|
|
|
|
app = login(app, username='manager', password='manager')
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
resp = resp.click(href='/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
|
|
resp = resp.click('Delete')
|
|
resp = resp.form.submit()
|
|
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
|
|
assert Event.objects.count() == 0
|
|
|
|
|
|
def test_export_events(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo bar')
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/export-events' % agenda.id)
|
|
csv_export = resp.text
|
|
assert (
|
|
csv_export
|
|
== 'date,time,number of places,number of places in waiting list,label,identifier,description,pricing,URL,publication date/time,duration\r\n'
|
|
)
|
|
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id)
|
|
resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,00:30,10', 'text/csv')
|
|
resp.form.submit(status=302)
|
|
|
|
resp = app.get('/manage/agendas/%s/export-events' % agenda.id)
|
|
csv_export = resp.text
|
|
assert (
|
|
csv_export
|
|
== 'date,time,number of places,number of places in waiting list,label,identifier,description,pricing,URL,publication date/time,duration\r\n'
|
|
'2016-09-16,00:30,10,0,,foo-bar-event,,,,,\r\n'
|
|
)
|
|
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id)
|
|
resp.form['events_csv_file'] = Upload(
|
|
't.csv',
|
|
b'2016-09-16,23:30,10,5,label,slug,"description\nfoobar",pricing,url,2016-10-16 00:00,90',
|
|
'text/csv',
|
|
)
|
|
resp.form.submit(status=302)
|
|
resp = app.get('/manage/agendas/%s/export-events' % agenda.id)
|
|
csv_export = resp.text
|
|
assert (
|
|
csv_export
|
|
== 'date,time,number of places,number of places in waiting list,label,identifier,description,pricing,URL,publication date/time,duration\r\n'
|
|
'2016-09-16,00:30,10,0,,foo-bar-event,,,,,\r\n'
|
|
'2016-09-16,23:30,10,5,label,slug,"description\nfoobar",pricing,url,2016-10-16 00:00,90\r\n'
|
|
)
|
|
|
|
|
|
def test_export_events_wrong_kind(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
|
|
|
|
app = login(app)
|
|
app.get('/manage/agendas/%s/export-events' % agenda.id, status=404)
|
|
agenda.kind = 'virtual'
|
|
agenda.save()
|
|
app.get('/manage/agendas/%s/export-events' % agenda.id, status=404)
|
|
|
|
|
|
def test_import_events(app, admin_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.save()
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
|
resp = resp.click('Import Events')
|
|
sample_csv_resp = resp.click('Download sample file')
|
|
assert sample_csv_resp.content_type == 'text/csv'
|
|
assert sample_csv_resp.text.startswith('date,time')
|
|
|
|
resp.form['events_csv_file'] = Upload('t.csv', sample_csv_resp.content, 'text/csv')
|
|
resp = resp.form.submit(status=302)
|
|
assert Event.objects.count() == 1
|
|
Event.objects.all().delete()
|
|
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload('t.csv', b'xx', 'text/csv')
|
|
resp = resp.form.submit(status=200)
|
|
assert 'Invalid file format.' in resp.text
|
|
|
|
resp.form['events_csv_file'] = Upload('t.csv', b'xxxx\0\0xxxx', 'text/csv')
|
|
resp = resp.form.submit(status=200)
|
|
assert 'Invalid file format.' in resp.text
|
|
|
|
resp.form['events_csv_file'] = Upload('t.csv', b'2016-14-16,18:00', 'text/csv')
|
|
resp = resp.form.submit(status=200)
|
|
assert 'Invalid file format.' in resp.text
|
|
|
|
resp.form['events_csv_file'] = Upload('t.csv', b'2016-14-16,18:00,10', 'text/csv')
|
|
resp = resp.form.submit(status=200)
|
|
assert 'Invalid file format. (date/time format' in resp.text
|
|
|
|
resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,blah', 'text/csv')
|
|
resp = resp.form.submit(status=200)
|
|
assert 'Invalid file format. (number of places,' in resp.text
|
|
|
|
resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,10,blah', 'text/csv')
|
|
resp = resp.form.submit(status=200)
|
|
assert 'Invalid file format. (number of places in waiting list,' in resp.text
|
|
|
|
resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,10,5,' + b'x' * 151, 'text/csv')
|
|
resp = resp.form.submit(status=200)
|
|
assert 'Ensure this value has at most 150' in resp.text
|
|
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,10', 'text/csv')
|
|
resp = resp.form.submit(status=302)
|
|
assert Event.objects.count() == 1
|
|
assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
|
|
assert Event.objects.all()[0].places == 10
|
|
Event.objects.all().delete()
|
|
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,10,5', 'text/csv')
|
|
resp = resp.form.submit(status=302)
|
|
assert Event.objects.count() == 1
|
|
assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
|
|
assert Event.objects.all()[0].places == 10
|
|
assert Event.objects.all()[0].waiting_list_places == 5
|
|
Event.objects.all().delete()
|
|
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload('t.csv', '2016-09-16,18:00,10,5,éléphant'.encode(), 'text/csv')
|
|
resp = resp.form.submit(status=302)
|
|
assert Event.objects.count() == 1
|
|
assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
|
|
assert Event.objects.all()[0].places == 10
|
|
assert Event.objects.all()[0].waiting_list_places == 5
|
|
assert Event.objects.all()[0].label == 'éléphant'
|
|
Event.objects.all().delete()
|
|
|
|
# BOM
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload(
|
|
't.csv', codecs.BOM_UTF8 + '2016-09-16,18:00,10,5,éléphant'.encode(), 'text/csv'
|
|
)
|
|
resp = resp.form.submit(status=302)
|
|
assert Event.objects.count() == 1
|
|
assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
|
|
assert Event.objects.all()[0].places == 10
|
|
assert Event.objects.all()[0].waiting_list_places == 5
|
|
assert Event.objects.all()[0].label == 'éléphant'
|
|
Event.objects.all().delete()
|
|
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload(
|
|
't.csv', '2016-09-16,18:00,10,5,éléphant'.encode('iso-8859-15'), 'text/csv'
|
|
)
|
|
resp = resp.form.submit(status=302)
|
|
assert Event.objects.count() == 1
|
|
assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
|
|
assert Event.objects.all()[0].places == 10
|
|
assert Event.objects.all()[0].waiting_list_places == 5
|
|
assert Event.objects.all()[0].label == 'éléphant'
|
|
Event.objects.all().delete()
|
|
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload(
|
|
't.csv', '2016-09-16,18:00,10,5,éléphant'.encode('eucjp'), 'text/csv'
|
|
)
|
|
resp = resp.form.submit(status=302)
|
|
assert Event.objects.count() == 1
|
|
assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
|
|
assert Event.objects.all()[0].places == 10
|
|
assert Event.objects.all()[0].waiting_list_places == 5
|
|
assert Event.objects.all()[0].label == '\x8f«±l\x8f«±phant' # eucjp interpreted as iso-8859-15
|
|
Event.objects.all().delete()
|
|
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload(
|
|
't.csv',
|
|
b'date,time,etc.\n' b'2016-09-16,18:00,10,5,bla bla bla\n' b'\n' b'2016-09-19,18:00,10',
|
|
'text/csv',
|
|
)
|
|
resp = resp.form.submit(status=302)
|
|
assert Event.objects.count() == 2
|
|
Event.objects.all().delete()
|
|
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload(
|
|
't.csv',
|
|
'"date"\t"time"\t"etc."\n'
|
|
'"2016-09-16"\t"18:00"\t"10"\t"5"\t"éléphant"\n'
|
|
'"2016-09-19"\t"18:00"\t"10"'.encode('iso-8859-15'),
|
|
'text/csv',
|
|
)
|
|
resp = resp.form.submit(status=302)
|
|
assert Event.objects.count() == 2
|
|
Event.objects.all().delete()
|
|
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,10,5,label,slug', 'text/csv')
|
|
resp = resp.form.submit(status=302)
|
|
assert Event.objects.count() == 1
|
|
event = Event.objects.latest('pk')
|
|
assert event.start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
|
|
assert event.places == 10
|
|
assert event.waiting_list_places == 5
|
|
assert event.label == 'label'
|
|
assert event.slug == 'slug'
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,10,5,label,slug', 'text/csv')
|
|
resp = resp.form.submit(status=302)
|
|
assert Event.objects.count() == 1
|
|
event = Event.objects.latest('pk')
|
|
assert event.slug == 'slug'
|
|
|
|
# additional optional attributes
|
|
Event.objects.all().delete()
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,10,5,label,slug,,,,,', 'text/csv')
|
|
resp = resp.form.submit(status=302)
|
|
assert Event.objects.count() == 1
|
|
event = Event.objects.get()
|
|
assert event.description == ''
|
|
assert event.pricing == ''
|
|
assert event.url == ''
|
|
assert event.publication_datetime is None
|
|
assert event.duration is None
|
|
Event.objects.all().delete()
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload(
|
|
't.csv',
|
|
b'2016-09-16,18:00,10,5,label,slug,"description\nfoobar",pricing,url,2016-10-16,90',
|
|
'text/csv',
|
|
)
|
|
resp = resp.form.submit(status=302)
|
|
assert Event.objects.count() == 1
|
|
event = Event.objects.get()
|
|
assert event.description == 'description\nfoobar'
|
|
assert event.pricing == 'pricing'
|
|
assert event.url == 'url'
|
|
assert str(event.publication_datetime) == '2016-10-15 22:00:00+00:00'
|
|
assert str(event.publication_datetime.tzinfo) == 'UTC'
|
|
assert event.duration == 90
|
|
Event.objects.all().delete()
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload(
|
|
't.csv',
|
|
b'2016-09-16,18:00,10,5,label,slug,"description\nfoobar",pricing,url,2016-10-16 10:00,90',
|
|
'text/csv',
|
|
)
|
|
resp = resp.form.submit(status=302)
|
|
assert Event.objects.count() == 1
|
|
event = Event.objects.get()
|
|
assert event.description == 'description\nfoobar'
|
|
assert event.pricing == 'pricing'
|
|
assert event.url == 'url'
|
|
assert str(event.publication_datetime) == '2016-10-16 08:00:00+00:00'
|
|
assert str(event.publication_datetime.tzinfo) == 'UTC'
|
|
assert event.duration == 90
|
|
|
|
# publication date/time bad format
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload(
|
|
't.csv', b'2016-09-16,18:00,10,5,label,slug,description,pricing,url,foobar', 'text/csv'
|
|
)
|
|
resp = resp.form.submit(status=200)
|
|
assert 'Invalid file format. (date/time format' in resp.text
|
|
|
|
# duration bad format
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload(
|
|
't.csv', b'2016-09-16,18:00,10,5,label,slug,description,pricing,url,2016-09-16,foobar', 'text/csv'
|
|
)
|
|
resp = resp.form.submit(status=200)
|
|
assert 'Invalid file format. (duration' in resp.text
|
|
|
|
# import events with empty slugs
|
|
Event.objects.all().delete()
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload(
|
|
't.csv',
|
|
b'2016-09-16,18:00,10,5,labela,labelb,,pricing,\n'
|
|
b'2016-09-17,18:00,10,5,labela,labelb-1,,pricing,\n'
|
|
b'2016-09-18,18:00,10,5,labela,labelb-2,,pricing,\n'
|
|
b'2016-09-18,18:00,10,5,labelb,,,pricing,\n'
|
|
b'2016-09-18,18:00,10,5,labelb,,,pricing,\n',
|
|
'text/csv',
|
|
)
|
|
with CaptureQueriesContext(connection) as ctx:
|
|
resp = resp.form.submit(status=302)
|
|
assert len(ctx.captured_queries) == 22
|
|
assert Event.objects.count() == 5
|
|
assert set(Event.objects.values_list('slug', flat=True)) == {
|
|
'labelb',
|
|
'labelb-1',
|
|
'labelb-2',
|
|
'labelb-3',
|
|
'labelb-4',
|
|
}
|
|
|
|
# forbidden numerical slug
|
|
Event.objects.all().delete()
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,10,5,label,1234', 'text/csv')
|
|
resp = resp.form.submit(status=200)
|
|
assert 'value cannot be a number' in resp.text
|
|
assert 'Identifier:' in resp.text # verbose_name is shown, not field name ('slug:')
|
|
|
|
|
|
def test_import_events_existing_event(app, admin_user, freezer):
|
|
agenda = Agenda.objects.create(label='Foo bar')
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload(
|
|
't.csv',
|
|
b'2016-09-16,18:00,10,5,label,slug\n2016-09-16,18:00,10,5,label,slug\n',
|
|
'text/csv',
|
|
)
|
|
resp.form.submit(status=302)
|
|
assert agenda.event_set.count() == 1
|
|
event = Event.objects.latest('pk')
|
|
|
|
def check_import(date, time, with_alert):
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload(
|
|
't.csv',
|
|
b'%s,%s,10,5,label,slug\n' % (date.encode(), time.encode()),
|
|
'text/csv',
|
|
)
|
|
resp = resp.form.submit(status=302).follow()
|
|
assert agenda.event_set.count() == 1
|
|
event.refresh_from_db()
|
|
if with_alert:
|
|
assert (
|
|
'<li class="warning">Event "label" start date has changed. Do not forget to notify the registrants.</li>'
|
|
in resp.text
|
|
)
|
|
else:
|
|
assert (
|
|
'<li class="warning">Event "label" start date has changed. Do not forget to notify the registrants.</li>'
|
|
not in resp.text
|
|
)
|
|
assert event.start_datetime == make_aware(
|
|
datetime.datetime(*(int(v) for v in date.split('-')), *(int(v) for v in time.split(':')))
|
|
)
|
|
|
|
# change date or time
|
|
# event in the past, no alert, with or without booking
|
|
Booking.objects.create(
|
|
event=event, cancellation_datetime=make_aware(datetime.datetime(2017, 5, 20, 10, 30))
|
|
)
|
|
check_import('2016-09-15', '18:00', False) # change date
|
|
check_import('2016-09-15', '17:00', False) # change time
|
|
# available booking
|
|
Booking.objects.create(event=event)
|
|
check_import('2016-09-14', '17:00', False) # change date
|
|
check_import('2016-09-14', '16:00', False) # change time
|
|
|
|
# date in the future
|
|
freezer.move_to('2016-09-01')
|
|
# warn if available booking only
|
|
check_import('2016-09-13', '16:00', True) # change date
|
|
check_import('2016-09-13', '15:00', True) # change time
|
|
# no available booking
|
|
Booking.objects.all().delete()
|
|
Booking.objects.create(
|
|
event=event, cancellation_datetime=make_aware(datetime.datetime(2017, 5, 20, 10, 30))
|
|
)
|
|
check_import('2016-09-12', '15:00', False) # change date
|
|
check_import('2016-09-12', '14:00', False) # change time
|
|
|
|
# check there is a message per changed event
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload(
|
|
't.csv',
|
|
b'2016-09-16,18:00,10,5,label,slug\n2016-09-16,19:00,10,5,label,other_slug\n',
|
|
'text/csv',
|
|
)
|
|
resp.form.submit(status=302)
|
|
assert agenda.event_set.count() == 2
|
|
event2 = Event.objects.latest('pk')
|
|
Booking.objects.create(event=event)
|
|
Booking.objects.create(event=event2)
|
|
|
|
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
|
resp.form['events_csv_file'] = Upload(
|
|
't.csv',
|
|
b'2016-09-17,18:00,10,5,label,slug\n2016-09-17,19:00,10,5,,other_slug\n2016-09-17,20:00,10,5,,other_slug\n',
|
|
'text/csv',
|
|
)
|
|
resp = resp.form.submit(status=302).follow()
|
|
assert agenda.event_set.count() == 2
|
|
assert (
|
|
resp.text.count(
|
|
'Event "label" start date has changed. Do not forget to notify the registrants.'
|
|
)
|
|
== 1
|
|
)
|
|
assert (
|
|
resp.text.count(
|
|
'Event "other_slug" start date has changed. Do not forget to notify the registrants.'
|
|
)
|
|
== 1
|
|
)
|
|
|
|
|
|
def test_import_events_wrong_kind(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
|
|
|
|
app = login(app)
|
|
app.get('/manage/agendas/%s/import-events' % agenda.id, status=404)
|
|
agenda.kind = 'virtual'
|
|
agenda.save()
|
|
app.get('/manage/agendas/%s/import-events' % agenda.id, status=404)
|
|
|
|
|
|
def test_event_cancellation(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
event = Event.objects.create(
|
|
label='xyz', start_datetime=now() + datetime.timedelta(days=1), places=10, agenda=agenda
|
|
)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%d/events/%d/' % (agenda.pk, event.pk))
|
|
assert 'Bookings (0/10)' in resp.text
|
|
|
|
resp = resp.click('Cancel', href='/cancel')
|
|
assert 'related bookings' not in resp.text
|
|
|
|
Booking.objects.create(event=event)
|
|
Booking.objects.create(event=event)
|
|
|
|
resp = app.get('/manage/agendas/%d/events/%d/' % (agenda.pk, event.pk))
|
|
assert 'Bookings (2/10)' in resp.text
|
|
|
|
resp = resp.click('Cancel', href='manage/agendas/%d/events/%d/cancel' % (agenda.pk, event.pk))
|
|
assert '2 related bookings will also be cancelled.' in resp.text
|
|
|
|
resp = resp.form.submit().follow()
|
|
assert 'Cancelled' in resp.text
|
|
assert 'Bookings (0/10)' in resp.text
|
|
assert Booking.objects.filter(event=event, cancellation_datetime__isnull=False).count() == 2
|
|
resp = app.get('/manage/agendas/%d/events/%d/' % (agenda.pk, event.pk))
|
|
assert '/manage/agendas/%d/events/%d/cancel' % (agenda.pk, event.pk) not in resp.text
|
|
|
|
|
|
def test_event_cancellation_error_report(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
event = Event.objects.create(
|
|
label='xyz', start_datetime=now() + datetime.timedelta(days=1), places=10, agenda=agenda
|
|
)
|
|
day = event.start_datetime
|
|
|
|
def mocked_requests_connection_error(*args, **kwargs):
|
|
raise requests.exceptions.ConnectionError('unreachable')
|
|
|
|
for _ in range(5):
|
|
Booking.objects.create(event=event, cancel_callback_url='http://example.org/jump/trigger/')
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/%d/%d/' % (agenda.id, day.year, day.month))
|
|
resp = resp.click('Cancellation error reports')
|
|
assert 'No error report' in resp.text
|
|
|
|
resp = app.get('/manage/agendas/%d/events/%d/cancel' % (agenda.pk, event.pk))
|
|
resp = resp.form.submit().follow()
|
|
assert 'Cancellation in progress' in resp.text
|
|
|
|
with mock.patch('chrono.utils.requests_wrapper.RequestsSession.send') as mock_send:
|
|
mock_response = mock.Mock(status_code=200)
|
|
mock_send.return_value = mock_response
|
|
mock_send.side_effect = mocked_requests_connection_error
|
|
call_command('cancel_events')
|
|
|
|
event.refresh_from_db()
|
|
assert not event.cancelled and not event.cancellation_scheduled
|
|
assert not Booking.objects.filter(cancellation_datetime__isnull=False).exists()
|
|
|
|
resp = app.get('/manage/agendas/%s/%d/%d/' % (agenda.id, day.year, day.month))
|
|
assert 'Errors occured during cancellation of event "xyz".' in resp.text
|
|
|
|
# warning doesn't go away
|
|
resp = app.get('/manage/agendas/%s/%d/%d/' % (agenda.id, day.year, day.month))
|
|
assert 'Errors occured during cancellation of event "xyz".' in resp.text
|
|
|
|
resp = resp.click('Details')
|
|
assert resp.text.count('unreachable') == 5
|
|
|
|
resp = app.get('/manage/agendas/%s/%d/%d/' % (agenda.id, day.year, day.month))
|
|
assert 'Errors occured during cancellation of event "xyz".' not in resp.text
|
|
|
|
resp = resp.click('Cancellation error reports')
|
|
assert '(5 failures)' in resp.text
|
|
|
|
resp = resp.click(str(event))
|
|
resp = resp.click('Force cancellation')
|
|
resp = resp.form.submit().follow()
|
|
event.refresh_from_db()
|
|
assert event.cancelled and not event.cancellation_scheduled
|
|
assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 5
|
|
|
|
|
|
def test_event_cancellation_error_report_backofice_url_translation(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
event = Event.objects.create(
|
|
label='xyz', start_datetime=now() + datetime.timedelta(days=1), places=10, agenda=agenda
|
|
)
|
|
day = event.start_datetime
|
|
|
|
def mocked_requests_connection_error(*args, **kwargs):
|
|
raise requests.exceptions.ConnectionError('unreachable')
|
|
|
|
for _ in range(5):
|
|
Booking.objects.create(
|
|
event=event,
|
|
cancel_callback_url='http://example.org/jump/trigger/',
|
|
backoffice_url='publik://default/',
|
|
)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/%d/%d/' % (agenda.id, day.year, day.month))
|
|
resp = resp.click('Cancellation error reports')
|
|
assert 'No error report' in resp.text
|
|
|
|
resp = app.get('/manage/agendas/%d/events/%d/cancel' % (agenda.pk, event.pk))
|
|
resp = resp.form.submit().follow()
|
|
assert 'Cancellation in progress' in resp.text
|
|
|
|
with mock.patch('chrono.utils.requests_wrapper.RequestsSession.send') as mock_send:
|
|
mock_response = mock.Mock(status_code=200)
|
|
mock_send.return_value = mock_response
|
|
mock_send.side_effect = mocked_requests_connection_error
|
|
call_command('cancel_events')
|
|
|
|
event.refresh_from_db()
|
|
assert not event.cancelled and not event.cancellation_scheduled
|
|
assert not Booking.objects.filter(cancellation_datetime__isnull=False).exists()
|
|
|
|
resp = app.get('/manage/agendas/%s/%d/%d/' % (agenda.id, day.year, day.month))
|
|
assert 'Errors occured during cancellation of event "xyz".' in resp.text
|
|
|
|
resp = resp.click('Cancellation error reports')
|
|
assert '(5 failures)' in resp.text
|
|
|
|
resp = resp.click(str(event))
|
|
assert 'http://example.org/' in resp.text
|
|
|
|
|
|
def test_event_cancellation_forbidden(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
event = Event.objects.create(
|
|
label='xyz', start_datetime=now() + datetime.timedelta(days=1), places=10, agenda=agenda
|
|
)
|
|
Booking.objects.create(event=event)
|
|
booking = Booking.objects.create(event=event, backoffice_url='http://example.org/backoffice/xx/')
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%d/events/%d/cancel' % (agenda.pk, event.pk))
|
|
assert 'event has bookings with no callback url configured' in resp.text
|
|
assert 'Proceed with cancellation' not in resp.text
|
|
|
|
booking.cancel()
|
|
resp = app.get('/manage/agendas/%d/events/%d/cancel' % (agenda.pk, event.pk))
|
|
assert 'event has bookings with no callback url configured' not in resp.text
|
|
assert 'Proceed with cancellation' in resp.text
|
|
|
|
|
|
def test_event_booking_form_url(settings, app, admin_user):
|
|
settings.TEMPLATE_VARS = {'eservices_url': 'http://demarches/'}
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
event = Event.objects.create(
|
|
label='xyz', start_datetime=now() + datetime.timedelta(days=1), places=10, agenda=agenda
|
|
)
|
|
day = event.start_datetime
|
|
|
|
login(app)
|
|
|
|
assert event.get_booking_form_url() is None
|
|
resp = app.get('/manage/agendas/%d/%d/%d/' % (agenda.pk, day.year, day.month))
|
|
assert 'Booking form' not in resp.text
|
|
resp = app.get('/manage/agendas/%d/events/open/' % agenda.pk)
|
|
assert 'Booking form' not in resp.text
|
|
resp = app.get('/manage/agendas/%d/events/%d/' % (agenda.pk, event.pk))
|
|
assert 'Booking form' not in resp.text
|
|
|
|
agenda.booking_form_url = '{{ eservices_url }}backoffice/submission/inscription-aux-activites/'
|
|
agenda.save()
|
|
assert (
|
|
event.get_booking_form_url()
|
|
== 'http://demarches/backoffice/submission/inscription-aux-activites/?agenda=%s&event=%s'
|
|
% (agenda.slug, event.slug)
|
|
)
|
|
resp = app.get('/manage/agendas/%d/%d/%d/' % (agenda.pk, day.year, day.month))
|
|
assert (
|
|
'<a class="link-action-text" href="http://demarches/backoffice/submission/inscription-aux-activites/?agenda=%s&event=%s&ReturnURL=%s">Booking form</a>'
|
|
% (
|
|
agenda.slug,
|
|
event.slug,
|
|
'http://testserver/manage/agendas/%d/%d/%d/' % (agenda.pk, day.year, day.month),
|
|
)
|
|
in resp.text
|
|
)
|
|
resp = app.get('/manage/agendas/%d/events/open/' % agenda.pk)
|
|
assert (
|
|
'<a class="link-action-text" href="http://demarches/backoffice/submission/inscription-aux-activites/?agenda=%s&event=%s&ReturnURL=%s">Booking form</a>'
|
|
% (agenda.slug, event.slug, 'http://testserver/manage/agendas/%d/events/open/' % agenda.pk)
|
|
in resp.text
|
|
)
|
|
resp = app.get('/manage/agendas/%d/events/%d/' % (agenda.pk, event.pk))
|
|
assert (
|
|
'<a href="http://demarches/backoffice/submission/inscription-aux-activites/?agenda=%s&event=%s&ReturnURL=%s">Booking form</a>'
|
|
% (agenda.slug, event.slug, 'http://testserver/manage/agendas/%d/events/%d/' % (agenda.pk, event.pk))
|
|
in resp.text
|
|
)
|
|
|
|
|
|
def test_booking_cancellation_events_agenda(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
event = Event(label='xyz', start_datetime=now() + datetime.timedelta(days=1), places=10, agenda=agenda)
|
|
event.save()
|
|
booking = Booking.objects.create(event=event)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/events/%s/' % (agenda.id, event.id))
|
|
assert 'Bookings (1/10)' in resp.text
|
|
|
|
resp = resp.click('Cancel', href='bookings/')
|
|
resp = resp.form.submit()
|
|
assert resp.location.endswith('/manage/agendas/%s/events/%s/' % (agenda.id, event.id))
|
|
|
|
booking.refresh_from_db()
|
|
assert booking.cancellation_datetime
|
|
|
|
resp = resp.follow()
|
|
assert 'Bookings (0/10)' in resp.text
|
|
|
|
# again
|
|
app.get('/manage/agendas/%s/bookings/%s/cancel' % (agenda.pk, booking.pk), status=404)
|
|
|
|
# test secondary booking
|
|
primary = Booking.objects.create(event=event)
|
|
secondary = Booking.objects.create(event=event, primary_booking=primary)
|
|
resp = app.get('/manage/agendas/%s/events/%s/' % (agenda.pk, event.pk))
|
|
assert 'Bookings (2/10)' in resp.text
|
|
assert '/manage/agendas/%s/bookings/%s/cancel' % (agenda.pk, primary.pk) in resp.text
|
|
assert '/manage/agendas/%s/bookings/%s/cancel' % (agenda.pk, secondary.pk) not in resp.text
|
|
app.get('/manage/agendas/%s/bookings/%s/cancel' % (agenda.pk, secondary.pk), status=404)
|
|
app.get('/manage/agendas/%s/bookings/%s/cancel' % (agenda.pk, primary.pk)).form.submit()
|
|
primary.refresh_from_db()
|
|
secondary.refresh_from_db()
|
|
assert primary.cancellation_datetime
|
|
assert secondary.cancellation_datetime
|
|
|
|
|
|
def test_event_check(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
agenda2 = Agenda.objects.create(label='Events', kind='events')
|
|
Desk.objects.create(agenda=agenda2, slug='_exceptions_holder')
|
|
event = Event.objects.create(
|
|
label='xyz',
|
|
start_datetime=now() + datetime.timedelta(days=1),
|
|
places=10,
|
|
waiting_list_places=5,
|
|
agenda=agenda,
|
|
)
|
|
booking1 = Booking.objects.create(event=event, user_first_name='User', user_last_name='42')
|
|
Booking.objects.create(event=event, user_first_name='User', user_last_name='01')
|
|
Booking.objects.create(event=event, user_first_name='User', user_last_name='17')
|
|
Booking.objects.create(event=event, user_first_name='User', user_last_name='35')
|
|
Booking.objects.create(event=event, user_first_name='User', user_last_name='05')
|
|
booking6 = Booking.objects.create(event=event, user_first_name='User', user_last_name='Cancelled')
|
|
booking6.cancel()
|
|
booking7 = Booking.objects.create(
|
|
event=event, user_first_name='User', user_last_name='Waiting', in_waiting_list=True
|
|
)
|
|
booking8 = Booking.objects.create(
|
|
event=event, user_first_name='User', user_last_name='Secondary', primary_booking=booking1
|
|
)
|
|
login(app)
|
|
|
|
# event not in past
|
|
resp = app.get('/manage/agendas/%s/events/%s/' % (agenda.pk, event.pk))
|
|
assert '/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk) not in resp
|
|
app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk), status=404)
|
|
|
|
event.start_datetime = localtime(now()).replace(hour=22, minute=0) # it's ok all the day
|
|
event.save()
|
|
resp = app.get('/manage/agendas/%s/events/%s/' % (agenda.pk, event.pk))
|
|
assert '/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk) in resp
|
|
|
|
# unknown agenda
|
|
app.get('/manage/agendas/%s/events/%s/check' % (0, event.pk), status=404)
|
|
# wrong agenda
|
|
app.get('/manage/agendas/%s/events/%s/check' % (agenda2.pk, event.pk), status=404)
|
|
|
|
resp = resp.click('Check')
|
|
assert 'Bookings (6/10)' in resp
|
|
assert 'Waiting List (1/5)' in resp
|
|
assert (
|
|
resp.text.index('Bookings (6/10)')
|
|
< resp.text.index('User 01')
|
|
< resp.text.index('User 05')
|
|
< resp.text.index('User 17')
|
|
< resp.text.index('User 35')
|
|
< resp.text.index('User 42')
|
|
< resp.text.index('Waiting List (1/5)')
|
|
< resp.text.index('User Waiting')
|
|
) # user ordering is not optimal ...
|
|
assert 'User Cancelled' not in resp
|
|
|
|
agenda.booking_user_block_template = '{{ booking.user_name }} Foo Bar'
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert 'User 01 Foo Bar' in resp
|
|
assert 'User Waiting Foo Bar' in resp
|
|
|
|
# cancelled booking
|
|
token = resp.context['csrf_token']
|
|
app.post(
|
|
'/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking6.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
status=404,
|
|
)
|
|
app.post(
|
|
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking6.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
status=404,
|
|
)
|
|
|
|
# booking in waiting list
|
|
app.post(
|
|
'/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking7.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
status=404,
|
|
)
|
|
app.post(
|
|
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking7.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
status=404,
|
|
)
|
|
|
|
# secondary booking
|
|
app.post(
|
|
'/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking8.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
status=404,
|
|
)
|
|
app.post(
|
|
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking8.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
status=404,
|
|
)
|
|
|
|
# unknown agenda
|
|
app.post(
|
|
'/manage/agendas/%s/bookings/%s/presence' % (0, booking1.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
status=404,
|
|
)
|
|
app.post(
|
|
'/manage/agendas/%s/bookings/%s/absence' % (0, booking1.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
status=404,
|
|
)
|
|
# wrong agenda
|
|
app.post(
|
|
'/manage/agendas/%s/bookings/%s/presence' % (agenda2.pk, booking1.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
status=404,
|
|
)
|
|
app.post(
|
|
'/manage/agendas/%s/bookings/%s/absence' % (agenda2.pk, booking1.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
status=404,
|
|
)
|
|
|
|
# cancelled event
|
|
event.cancel()
|
|
resp = app.get('/manage/agendas/%s/events/%s/' % (agenda.pk, event.pk))
|
|
assert '/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk) not in resp
|
|
app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk), status=404)
|
|
event.cancellation_datetime = None
|
|
|
|
|
|
def test_event_checked(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events', booking_check_filters='foo,bar')
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
event = Event.objects.create(
|
|
label='xyz',
|
|
start_datetime=now() - datetime.timedelta(days=1),
|
|
places=10,
|
|
agenda=agenda,
|
|
)
|
|
login(app)
|
|
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert 'Mark the event as checked' not in resp
|
|
|
|
Booking.objects.create(event=event, user_first_name='User')
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert '<span class="tag">Checked</span>' not in resp
|
|
assert 'Mark the event as checked' in resp
|
|
assert event.checked is False
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
assert 'checked tag' not in resp
|
|
resp = app.get('/manage/agendas/%s/events/%s/' % (agenda.pk, event.pk))
|
|
assert '<span class="tag">Checked</span>' not in resp
|
|
|
|
token = resp.context['csrf_token']
|
|
resp = app.post(
|
|
'/manage/agendas/%s/events/%s/checked' % (agenda.pk, event.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
)
|
|
assert resp.location.endswith('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
event.refresh_from_db()
|
|
assert event.checked is True
|
|
resp = resp.follow()
|
|
assert '<span class="tag">Checked</span>' in resp
|
|
assert 'Mark the event as checked' not in resp
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
assert 'checked tag' in resp
|
|
resp = app.get('/manage/agendas/%s/events/%s/' % (agenda.pk, event.pk))
|
|
assert '<span class="tag">Checked</span>' in resp
|
|
|
|
|
|
def test_event_check_filters(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events', booking_check_filters='foo,bar')
|
|
event = Event.objects.create(
|
|
label='xyz',
|
|
start_datetime=now() - datetime.timedelta(days=1),
|
|
places=10,
|
|
agenda=agenda,
|
|
)
|
|
Booking.objects.create(event=event, user_first_name='User', user_last_name='none')
|
|
Booking.objects.create(event=event, user_first_name='User', user_last_name='empty', extra_data={})
|
|
Booking.objects.create(
|
|
event=event, user_first_name='User', user_last_name='foo-val1 bar-none', extra_data={'foo': 'val1'}
|
|
)
|
|
Booking.objects.create(
|
|
event=event,
|
|
user_first_name='User',
|
|
user_last_name='foo-val2 bar-val1',
|
|
extra_data={'foo': 'val2', 'bar': 'val1'},
|
|
)
|
|
Booking.objects.create(
|
|
event=event,
|
|
user_first_name='User',
|
|
user_last_name='foo-val1 bar-val2',
|
|
extra_data={'foo': 'val1', 'bar': 'val2'},
|
|
)
|
|
Booking.objects.create(
|
|
event=event, user_first_name='User', user_last_name='foo-none bar-val2', extra_data={'bar': 'val2'}
|
|
)
|
|
login(app)
|
|
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert 'User none' in resp
|
|
assert 'User empty' in resp
|
|
assert 'User foo-val1' in resp
|
|
assert 'User foo-val2 bar-val1' in resp
|
|
assert 'User foo-val1 bar-val2' in resp
|
|
assert 'User foo-none bar-val2' in resp
|
|
|
|
resp = app.get(
|
|
'/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk), params={'unknown': 'unknown'}
|
|
)
|
|
assert 'User none' in resp
|
|
assert 'User empty' in resp
|
|
assert 'User foo-val1 bar-none' in resp
|
|
assert 'User foo-val2 bar-val1' in resp
|
|
assert 'User foo-val1 bar-val2' in resp
|
|
assert 'User foo-none bar-val2' in resp
|
|
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk), params={'foo': 'unknown'})
|
|
assert 'User none' in resp
|
|
assert 'User empty' in resp
|
|
assert 'User foo-val1 bar-none' in resp
|
|
assert 'User foo-val2 bar-val1' in resp
|
|
assert 'User foo-val1 bar-val2' in resp
|
|
assert 'User foo-none bar-val2' in resp
|
|
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk), params={'foo': 'val1'})
|
|
assert 'User none' not in resp
|
|
assert 'User empty' not in resp
|
|
assert 'User foo-val1 bar-none' in resp
|
|
assert 'User foo-val2 bar-val1' not in resp
|
|
assert 'User foo-val1 bar-val2' in resp
|
|
assert 'User foo-none bar-val2' not in resp
|
|
|
|
resp = app.get(
|
|
'/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk), params={'foo': 'val1', 'bar': 'val2'}
|
|
)
|
|
assert 'User none' not in resp
|
|
assert 'User empty' not in resp
|
|
assert 'User foo-val1 bar-none' not in resp
|
|
assert 'User foo-val2 bar-val1' not in resp
|
|
assert 'User foo-val1 bar-val2' in resp
|
|
assert 'User foo-none bar-val2' not in resp
|
|
|
|
resp = app.get(
|
|
'/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk), params={'foo': 'val2', 'bar': 'val2'}
|
|
)
|
|
assert 'User none' not in resp
|
|
assert 'User empty' not in resp
|
|
assert 'User foo-val1 bar-none' not in resp
|
|
assert 'User foo-val2 bar-val1' not in resp
|
|
assert 'User foo-val1 bar-val2' not in resp
|
|
assert 'User foo-none bar-val2' not in resp
|
|
|
|
|
|
def test_event_check_booking(app, admin_user):
|
|
group = AbsenceReasonGroup.objects.create(label='Foo bar')
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
event = Event.objects.create(
|
|
label='xyz',
|
|
start_datetime=now() - datetime.timedelta(days=1),
|
|
places=10,
|
|
waiting_list_places=5,
|
|
agenda=agenda,
|
|
)
|
|
booking = Booking.objects.create(event=event, user_first_name='User', user_last_name='42')
|
|
secondary_booking = Booking.objects.create(
|
|
event=event, user_first_name='User', user_last_name='42', primary_booking=booking
|
|
)
|
|
assert agenda.mark_event_checked_auto is False
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert resp.pyquery.find('td.booking-status')[0].text.strip() == '-'
|
|
assert len(resp.pyquery.find('td.booking-actions button[disabled]')) == 0
|
|
assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) in resp
|
|
assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) in resp
|
|
|
|
# set as present
|
|
token = resp.context['csrf_token']
|
|
resp = app.post(
|
|
'/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
).follow()
|
|
assert resp.pyquery.find('td.booking-status')[0].text.strip() == 'Present'
|
|
assert len(resp.pyquery.find('td.booking-actions button[disabled]')) == 1
|
|
assert resp.pyquery.find('td.booking-actions button[disabled]')[0].text == 'Presence'
|
|
booking.refresh_from_db()
|
|
assert booking.user_was_present is True
|
|
assert booking.user_absence_reason == ''
|
|
secondary_booking.refresh_from_db()
|
|
assert secondary_booking.user_was_present is True
|
|
assert secondary_booking.user_absence_reason == ''
|
|
event.refresh_from_db()
|
|
assert event.checked is False
|
|
|
|
agenda.mark_event_checked_auto = True
|
|
agenda.save()
|
|
|
|
# set as absent without reason
|
|
resp = app.post(
|
|
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
).follow()
|
|
assert resp.pyquery.find('td.booking-status')[0].text.strip() == 'Absent'
|
|
assert len(resp.pyquery.find('td.booking-actions button[disabled]')) == 1
|
|
assert resp.pyquery.find('td.booking-actions button[disabled]')[0].text == 'Absence'
|
|
booking.refresh_from_db()
|
|
assert booking.user_was_present is False
|
|
assert booking.user_absence_reason == ''
|
|
secondary_booking.refresh_from_db()
|
|
assert secondary_booking.user_was_present is False
|
|
assert secondary_booking.user_absence_reason == ''
|
|
event.refresh_from_db()
|
|
assert event.checked is True
|
|
|
|
agenda.absence_reasons_group = group
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert len(resp.pyquery.find('td.booking-actions select')) == 0
|
|
|
|
AbsenceReason.objects.create(label='Foo reason', group=group)
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert len(resp.pyquery.find('td.booking-actions select')) == 1
|
|
|
|
# set as absent with reason
|
|
resp = app.post(
|
|
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk),
|
|
params={'csrfmiddlewaretoken': token, 'reason': 'Foo reason'},
|
|
).follow()
|
|
assert 'Foo reason' in resp
|
|
booking.refresh_from_db()
|
|
assert booking.user_was_present is False
|
|
assert booking.user_absence_reason == 'Foo reason'
|
|
secondary_booking.refresh_from_db()
|
|
assert secondary_booking.user_was_present is False
|
|
assert secondary_booking.user_absence_reason == 'Foo reason'
|
|
|
|
# set as present
|
|
app.post(
|
|
'/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
)
|
|
booking.refresh_from_db()
|
|
assert booking.user_was_present is True
|
|
assert booking.user_absence_reason == ''
|
|
secondary_booking.refresh_from_db()
|
|
assert secondary_booking.user_was_present is True
|
|
assert secondary_booking.user_absence_reason == ''
|
|
|
|
# mark the event as checked
|
|
event.checked = True
|
|
event.save()
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) in resp
|
|
assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) in resp
|
|
resp = app.post(
|
|
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
status=302,
|
|
)
|
|
app.post(
|
|
'/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
status=302,
|
|
)
|
|
|
|
# now disable check update
|
|
agenda.disable_check_update = True
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert '/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk) not in resp
|
|
assert '/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk) not in resp
|
|
resp = app.post(
|
|
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
status=404,
|
|
)
|
|
app.post(
|
|
'/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
status=404,
|
|
)
|
|
|
|
|
|
def test_event_check_booking_ajax(app, admin_user):
|
|
group = AbsenceReasonGroup.objects.create(label='Foo bar')
|
|
AbsenceReason.objects.create(label='Foo reason', group=group)
|
|
agenda = Agenda.objects.create(label='Events', kind='events', absence_reasons_group=group)
|
|
event = Event.objects.create(
|
|
label='xyz',
|
|
start_datetime=now() - datetime.timedelta(days=1),
|
|
places=10,
|
|
waiting_list_places=5,
|
|
agenda=agenda,
|
|
)
|
|
booking = Booking.objects.create(event=event, user_first_name='User', user_last_name='42')
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
token = resp.context['csrf_token']
|
|
|
|
# set as present
|
|
resp = app.post(
|
|
'/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
extra_environ={'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'},
|
|
)
|
|
assert '<tr>' not in resp # because this is a fragment
|
|
assert resp.pyquery.find('td.booking-status')[0].text.strip() == 'Present'
|
|
assert len(resp.pyquery.find('td.booking-actions button[disabled]')) == 1
|
|
assert resp.pyquery.find('td.booking-actions button[disabled]')[0].text == 'Presence'
|
|
|
|
# set as absent
|
|
resp = app.post(
|
|
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk),
|
|
params={'csrfmiddlewaretoken': token, 'reason': 'Foo reason'},
|
|
extra_environ={'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'},
|
|
)
|
|
assert '<tr>' not in resp # because this is a fragment
|
|
assert len(resp.pyquery.find('td.booking-actions button[disabled]')) == 1
|
|
assert resp.pyquery.find('td.booking-actions button[disabled]')[0].text.startswith('Absence')
|
|
assert '<option value="Foo reason" selected>Foo reason</option>' in resp
|
|
|
|
|
|
def test_event_check_all_bookings(app, admin_user):
|
|
group = AbsenceReasonGroup.objects.create(label='Foo bar')
|
|
AbsenceReason.objects.create(label='Foo reason', group=group)
|
|
agenda = Agenda.objects.create(label='Events', kind='events', absence_reasons_group=group)
|
|
event = Event.objects.create(
|
|
label='xyz',
|
|
start_datetime=now() - datetime.timedelta(days=1),
|
|
places=10,
|
|
waiting_list_places=5,
|
|
agenda=agenda,
|
|
)
|
|
booking1 = Booking.objects.create(event=event, user_first_name='User', user_last_name='42')
|
|
assert agenda.mark_event_checked_auto is False
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
token = resp.context['csrf_token']
|
|
assert 'Mark all bookings without status' in resp
|
|
assert '/manage/agendas/%s/events/%s/presence' % (agenda.pk, event.pk) in resp
|
|
assert '/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk) in resp
|
|
|
|
resp = app.post(
|
|
'/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk), params={'csrfmiddlewaretoken': token}
|
|
)
|
|
booking1.refresh_from_db()
|
|
assert booking1.user_was_present is False
|
|
assert booking1.user_absence_reason == ''
|
|
event.refresh_from_db()
|
|
assert event.checked is False
|
|
|
|
agenda.mark_event_checked_auto = True
|
|
agenda.save()
|
|
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert 'Mark all bookings without status' not in resp
|
|
assert '/manage/agendas/%s/events/%s/presence' % (agenda.pk, event.pk) not in resp
|
|
assert '/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk) not in resp
|
|
|
|
booking2 = Booking.objects.create(event=event, user_first_name='User', user_last_name='35')
|
|
secondary_booking = Booking.objects.create(
|
|
event=event, user_first_name='User', user_last_name='35', primary_booking=booking2
|
|
)
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert 'Mark all bookings without status' in resp
|
|
assert '/manage/agendas/%s/events/%s/presence' % (agenda.pk, event.pk) in resp
|
|
assert '/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk) in resp
|
|
|
|
app.post(
|
|
'/manage/agendas/%s/events/%s/presence' % (agenda.pk, event.pk), params={'csrfmiddlewaretoken': token}
|
|
)
|
|
booking1.refresh_from_db()
|
|
assert booking1.user_was_present is False
|
|
assert booking1.user_absence_reason == ''
|
|
booking2.refresh_from_db()
|
|
assert booking2.user_was_present is True
|
|
assert booking2.user_absence_reason == ''
|
|
secondary_booking.refresh_from_db()
|
|
assert secondary_booking.user_was_present is True
|
|
assert secondary_booking.user_absence_reason == ''
|
|
event.refresh_from_db()
|
|
assert event.checked is True
|
|
|
|
# event is checked
|
|
booking3 = Booking.objects.create(event=event, user_first_name='User', user_last_name='51')
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert 'Mark all bookings without status' in resp
|
|
app.post(
|
|
'/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk),
|
|
params={'csrfmiddlewaretoken': token, 'reason': 'Foo reason'},
|
|
)
|
|
booking1.refresh_from_db()
|
|
assert booking1.user_was_present is False
|
|
assert booking1.user_absence_reason == ''
|
|
booking2.refresh_from_db()
|
|
assert booking2.user_was_present is True
|
|
assert booking2.user_absence_reason == ''
|
|
booking3.refresh_from_db()
|
|
assert booking3.user_was_present is False
|
|
assert booking3.user_absence_reason == 'Foo reason'
|
|
|
|
# now disable check update
|
|
agenda.disable_check_update = True
|
|
agenda.save()
|
|
Booking.objects.create(event=event, user_first_name='User', user_last_name='52')
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert 'Mark all bookings without status' not in resp
|
|
app.post(
|
|
'/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk),
|
|
params={'csrfmiddlewaretoken': token, 'reason': 'Foo reason'},
|
|
status=404,
|
|
)
|
|
resp = app.post(
|
|
'/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk),
|
|
params={'csrfmiddlewaretoken': token},
|
|
status=404,
|
|
)
|
|
|
|
|
|
def test_event_check_primary_booking(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
event = Event.objects.create(
|
|
label='xyz',
|
|
start_datetime=now() - datetime.timedelta(days=1),
|
|
places=10,
|
|
waiting_list_places=5,
|
|
agenda=agenda,
|
|
)
|
|
booking = Booking.objects.create(event=event, user_first_name='User', user_last_name='42')
|
|
Booking.objects.create(event=event, user_first_name='John', user_last_name='Doe')
|
|
booking_3 = Booking.objects.create(
|
|
event=event, user_first_name='Jane', user_last_name='Doe', in_waiting_list=True
|
|
)
|
|
# create secondary bookings
|
|
Booking.objects.create(event=event, user_first_name='User', user_last_name='42', primary_booking=booking)
|
|
Booking.objects.create(event=event, user_first_name='User', user_last_name='42', primary_booking=booking)
|
|
Booking.objects.create(
|
|
event=event,
|
|
user_first_name='Jane',
|
|
user_last_name='Doe',
|
|
primary_booking=booking_3,
|
|
in_waiting_list=True,
|
|
)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
|
assert 'Bookings (4/10)' in resp.text
|
|
user_bookings = resp.pyquery.find('td.booking-username.main-list')
|
|
assert len(user_bookings) == 2
|
|
assert user_bookings[0].text == 'User 42 (3 places)'
|
|
assert user_bookings[1].text == 'John Doe'
|
|
|
|
assert 'Waiting List (2/5)' in resp.text
|
|
user_bookings = resp.pyquery.find('td.booking-username.waiting')
|
|
assert len(user_bookings) == 1
|
|
assert user_bookings[0].text == 'Jane Doe (2 places)'
|