api: revert endpoint (#83098)
This commit is contained in:
parent
678ac6c1de
commit
63a575f303
|
@ -38,6 +38,11 @@ urlpatterns = [
|
|||
views.agendas_events_fillslots,
|
||||
name='api-agendas-events-fillslots',
|
||||
),
|
||||
path(
|
||||
'agendas/events/fillslots/<uuid:request_uuid>/revert/',
|
||||
views.agendas_events_fillslots_revert,
|
||||
name='api-agendas-events-fillslots-revert',
|
||||
),
|
||||
path(
|
||||
'agendas/events/check-status/',
|
||||
views.agendas_events_check_status,
|
||||
|
|
|
@ -2131,6 +2131,74 @@ class MultipleAgendasEventsFillslots(EventsFillslots):
|
|||
agendas_events_fillslots = MultipleAgendasEventsFillslots.as_view()
|
||||
|
||||
|
||||
class MultipleAgendasEventsFillslotsRevert(APIView):
|
||||
permission_classes = (permissions.IsAuthenticated,)
|
||||
|
||||
def post(self, request, request_uuid):
|
||||
bookings = Booking.objects.filter(request_uuid=request_uuid)
|
||||
bookings_to_cancel = []
|
||||
bookings_to_book = []
|
||||
bookings_to_delete = []
|
||||
for booking in bookings:
|
||||
if booking.previous_state == 'unbooked':
|
||||
bookings_to_delete.append(booking)
|
||||
if booking.previous_state == 'booked':
|
||||
bookings_to_book.append(booking)
|
||||
if booking.previous_state == 'cancelled':
|
||||
bookings_to_cancel.append(booking)
|
||||
|
||||
events = Event.objects.filter(
|
||||
pk__in=[b.event_id for b in bookings_to_cancel + bookings_to_book + bookings_to_delete]
|
||||
).prefetch_related('agenda')
|
||||
events_by_id = {x.id: x for x in events}
|
||||
with transaction.atomic():
|
||||
cancellation_datetime = now()
|
||||
cancelled_events = [
|
||||
get_short_event_detail(
|
||||
request,
|
||||
events_by_id[x.event_id],
|
||||
multiple_agendas=True,
|
||||
)
|
||||
for x in bookings_to_cancel
|
||||
]
|
||||
cancelled_count = Booking.objects.filter(pk__in=[b.pk for b in bookings_to_cancel]).update(
|
||||
cancellation_datetime=cancellation_datetime
|
||||
)
|
||||
booked_events = [
|
||||
get_short_event_detail(
|
||||
request,
|
||||
events_by_id[x.event_id],
|
||||
multiple_agendas=True,
|
||||
)
|
||||
for x in bookings_to_book
|
||||
]
|
||||
booked_count = Booking.objects.filter(pk__in=[b.pk for b in bookings_to_book]).update(
|
||||
cancellation_datetime=None
|
||||
)
|
||||
deleted_events = [
|
||||
get_short_event_detail(
|
||||
request,
|
||||
events_by_id[x.event_id],
|
||||
multiple_agendas=True,
|
||||
)
|
||||
for x in bookings_to_delete
|
||||
]
|
||||
deleted_count = Booking.objects.filter(pk__in=[b.pk for b in bookings_to_delete]).delete()[0]
|
||||
response = {
|
||||
'err': 0,
|
||||
'cancelled_booking_count': cancelled_count,
|
||||
'cancelled_events': cancelled_events,
|
||||
'booked_booking_count': booked_count,
|
||||
'booked_events': booked_events,
|
||||
'deleted_booking_count': deleted_count,
|
||||
'deleted_events': deleted_events,
|
||||
}
|
||||
return Response(response)
|
||||
|
||||
|
||||
agendas_events_fillslots_revert = MultipleAgendasEventsFillslotsRevert.as_view()
|
||||
|
||||
|
||||
class MultipleAgendasEvents(APIView):
|
||||
permission_classes = (permissions.IsAuthenticated,)
|
||||
serializer_class = serializers.SlotsSerializer
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import datetime
|
||||
import uuid
|
||||
|
||||
import pytest
|
||||
from django.db import connection
|
||||
|
@ -829,3 +830,311 @@ def test_api_events_fillslots_multiple_agendas_partial_bookings(app, user):
|
|||
resp.json['errors']['non_field_errors'][0]
|
||||
== 'must include start_time and end_time for partial bookings agenda'
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.freeze_time('2021-02-23 14:00')
|
||||
def test_api_events_fillslots_multiple_agendas_revert(app, user):
|
||||
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
||||
event = Event.objects.create(
|
||||
label='Event',
|
||||
start_datetime=now() + datetime.timedelta(days=5),
|
||||
duration=120,
|
||||
places=1,
|
||||
agenda=agenda,
|
||||
)
|
||||
|
||||
app.authorization = ('Basic', ('john.doe', 'password'))
|
||||
request_uuid = uuid.uuid4()
|
||||
|
||||
# no corresponding booking
|
||||
revert_url = '/api/agendas/events/fillslots/%s/revert/' % request_uuid
|
||||
resp = app.post(revert_url)
|
||||
assert resp.json == {
|
||||
'err': 0,
|
||||
'cancelled_booking_count': 0,
|
||||
'cancelled_events': [],
|
||||
'deleted_booking_count': 0,
|
||||
'deleted_events': [],
|
||||
'booked_booking_count': 0,
|
||||
'booked_events': [],
|
||||
}
|
||||
|
||||
booking1 = Booking.objects.create(event=event, request_uuid=uuid.uuid4())
|
||||
resp = app.post(revert_url)
|
||||
assert resp.json == {
|
||||
'err': 0,
|
||||
'cancelled_booking_count': 0,
|
||||
'cancelled_events': [],
|
||||
'deleted_booking_count': 0,
|
||||
'deleted_events': [],
|
||||
'booked_booking_count': 0,
|
||||
'booked_events': [],
|
||||
}
|
||||
booking1.refresh_from_db()
|
||||
assert booking1.cancellation_datetime is None
|
||||
|
||||
booking2 = Booking.objects.create(event=event, request_uuid=request_uuid)
|
||||
resp = app.post(revert_url)
|
||||
assert resp.json == {
|
||||
'err': 0,
|
||||
'cancelled_booking_count': 0,
|
||||
'cancelled_events': [],
|
||||
'deleted_booking_count': 0,
|
||||
'deleted_events': [],
|
||||
'booked_booking_count': 0,
|
||||
'booked_events': [],
|
||||
}
|
||||
booking1.refresh_from_db()
|
||||
assert booking1.cancellation_datetime is None
|
||||
booking2.refresh_from_db()
|
||||
assert booking2.cancellation_datetime is None
|
||||
|
||||
# booking was previously cancelled
|
||||
booking = Booking.objects.create(event=event, request_uuid=request_uuid, previous_state='cancelled')
|
||||
resp = app.post(revert_url)
|
||||
assert resp.json == {
|
||||
'err': 0,
|
||||
'cancelled_booking_count': 1,
|
||||
'cancelled_events': [
|
||||
{
|
||||
'agenda_label': 'Foo bar',
|
||||
'check_locked': False,
|
||||
'checked': False,
|
||||
'date': '2021-02-28',
|
||||
'datetime': '2021-02-28 15:00:00',
|
||||
'description': None,
|
||||
'duration': 120,
|
||||
'end_datetime': '2021-02-28 17:00:00',
|
||||
'id': 'foo-bar@event',
|
||||
'invoiced': False,
|
||||
'label': 'Event',
|
||||
'pricing': None,
|
||||
'slug': 'event',
|
||||
'text': 'Event',
|
||||
'url': None,
|
||||
}
|
||||
],
|
||||
'deleted_booking_count': 0,
|
||||
'deleted_events': [],
|
||||
'booked_booking_count': 0,
|
||||
'booked_events': [],
|
||||
}
|
||||
booking1.refresh_from_db()
|
||||
assert booking1.cancellation_datetime is None
|
||||
booking2.refresh_from_db()
|
||||
assert booking2.cancellation_datetime is None
|
||||
booking.refresh_from_db()
|
||||
assert booking.cancellation_datetime is not None
|
||||
|
||||
# again, but with a cancelled booking
|
||||
resp = app.post(revert_url)
|
||||
assert resp.json == {
|
||||
'err': 0,
|
||||
'cancelled_booking_count': 1,
|
||||
'cancelled_events': [
|
||||
{
|
||||
'agenda_label': 'Foo bar',
|
||||
'check_locked': False,
|
||||
'checked': False,
|
||||
'date': '2021-02-28',
|
||||
'datetime': '2021-02-28 15:00:00',
|
||||
'description': None,
|
||||
'duration': 120,
|
||||
'end_datetime': '2021-02-28 17:00:00',
|
||||
'id': 'foo-bar@event',
|
||||
'invoiced': False,
|
||||
'label': 'Event',
|
||||
'pricing': None,
|
||||
'slug': 'event',
|
||||
'text': 'Event',
|
||||
'url': None,
|
||||
}
|
||||
],
|
||||
'deleted_booking_count': 0,
|
||||
'deleted_events': [],
|
||||
'booked_booking_count': 0,
|
||||
'booked_events': [],
|
||||
}
|
||||
booking1.refresh_from_db()
|
||||
assert booking1.cancellation_datetime is None
|
||||
booking2.refresh_from_db()
|
||||
assert booking2.cancellation_datetime is None
|
||||
booking.refresh_from_db()
|
||||
assert booking.cancellation_datetime is not None
|
||||
|
||||
# booking was previously not cancelled
|
||||
booking.previous_state = 'booked'
|
||||
booking.save()
|
||||
resp = app.post(revert_url)
|
||||
assert resp.json == {
|
||||
'err': 0,
|
||||
'cancelled_booking_count': 0,
|
||||
'cancelled_events': [],
|
||||
'deleted_booking_count': 0,
|
||||
'deleted_events': [],
|
||||
'booked_booking_count': 1,
|
||||
'booked_events': [
|
||||
{
|
||||
'agenda_label': 'Foo bar',
|
||||
'check_locked': False,
|
||||
'checked': False,
|
||||
'date': '2021-02-28',
|
||||
'datetime': '2021-02-28 15:00:00',
|
||||
'description': None,
|
||||
'duration': 120,
|
||||
'end_datetime': '2021-02-28 17:00:00',
|
||||
'id': 'foo-bar@event',
|
||||
'invoiced': False,
|
||||
'label': 'Event',
|
||||
'pricing': None,
|
||||
'slug': 'event',
|
||||
'text': 'Event',
|
||||
'url': None,
|
||||
}
|
||||
],
|
||||
}
|
||||
booking1.refresh_from_db()
|
||||
assert booking1.cancellation_datetime is None
|
||||
booking2.refresh_from_db()
|
||||
assert booking2.cancellation_datetime is None
|
||||
booking.refresh_from_db()
|
||||
assert booking.cancellation_datetime is None
|
||||
|
||||
# again, but with a not cancelled booking
|
||||
resp = app.post(revert_url)
|
||||
assert resp.json == {
|
||||
'err': 0,
|
||||
'cancelled_booking_count': 0,
|
||||
'cancelled_events': [],
|
||||
'deleted_booking_count': 0,
|
||||
'deleted_events': [],
|
||||
'booked_booking_count': 1,
|
||||
'booked_events': [
|
||||
{
|
||||
'agenda_label': 'Foo bar',
|
||||
'check_locked': False,
|
||||
'checked': False,
|
||||
'date': '2021-02-28',
|
||||
'datetime': '2021-02-28 15:00:00',
|
||||
'description': None,
|
||||
'duration': 120,
|
||||
'end_datetime': '2021-02-28 17:00:00',
|
||||
'id': 'foo-bar@event',
|
||||
'invoiced': False,
|
||||
'label': 'Event',
|
||||
'pricing': None,
|
||||
'slug': 'event',
|
||||
'text': 'Event',
|
||||
'url': None,
|
||||
}
|
||||
],
|
||||
}
|
||||
booking1.refresh_from_db()
|
||||
assert booking1.cancellation_datetime is None
|
||||
booking2.refresh_from_db()
|
||||
assert booking2.cancellation_datetime is None
|
||||
booking.refresh_from_db()
|
||||
assert booking.cancellation_datetime is None
|
||||
|
||||
# booking was previously unbooked
|
||||
booking.previous_state = 'unbooked'
|
||||
booking.save()
|
||||
resp = app.post(revert_url)
|
||||
assert resp.json == {
|
||||
'err': 0,
|
||||
'cancelled_booking_count': 0,
|
||||
'cancelled_events': [],
|
||||
'deleted_booking_count': 1,
|
||||
'deleted_events': [
|
||||
{
|
||||
'agenda_label': 'Foo bar',
|
||||
'check_locked': False,
|
||||
'checked': False,
|
||||
'date': '2021-02-28',
|
||||
'datetime': '2021-02-28 15:00:00',
|
||||
'description': None,
|
||||
'duration': 120,
|
||||
'end_datetime': '2021-02-28 17:00:00',
|
||||
'id': 'foo-bar@event',
|
||||
'invoiced': False,
|
||||
'label': 'Event',
|
||||
'pricing': None,
|
||||
'slug': 'event',
|
||||
'text': 'Event',
|
||||
'url': None,
|
||||
}
|
||||
],
|
||||
'booked_booking_count': 0,
|
||||
'booked_events': [],
|
||||
}
|
||||
booking1.refresh_from_db()
|
||||
assert booking1.cancellation_datetime is None
|
||||
booking2.refresh_from_db()
|
||||
assert booking2.cancellation_datetime is None
|
||||
assert Booking.objects.filter(pk=booking.pk).exists() is False
|
||||
|
||||
# again, but with a cancelled booking
|
||||
booking = Booking.objects.create(
|
||||
event=event, request_uuid=request_uuid, previous_state='unbooked', cancellation_datetime=now()
|
||||
)
|
||||
resp = app.post(revert_url)
|
||||
assert resp.json == {
|
||||
'err': 0,
|
||||
'cancelled_booking_count': 0,
|
||||
'cancelled_events': [],
|
||||
'deleted_booking_count': 1,
|
||||
'deleted_events': [
|
||||
{
|
||||
'agenda_label': 'Foo bar',
|
||||
'check_locked': False,
|
||||
'checked': False,
|
||||
'date': '2021-02-28',
|
||||
'datetime': '2021-02-28 15:00:00',
|
||||
'description': None,
|
||||
'duration': 120,
|
||||
'end_datetime': '2021-02-28 17:00:00',
|
||||
'id': 'foo-bar@event',
|
||||
'invoiced': False,
|
||||
'label': 'Event',
|
||||
'pricing': None,
|
||||
'slug': 'event',
|
||||
'text': 'Event',
|
||||
'url': None,
|
||||
}
|
||||
],
|
||||
'booked_booking_count': 0,
|
||||
'booked_events': [],
|
||||
}
|
||||
booking1.refresh_from_db()
|
||||
assert booking1.cancellation_datetime is None
|
||||
booking2.refresh_from_db()
|
||||
assert booking2.cancellation_datetime is None
|
||||
assert Booking.objects.filter(pk=booking.pk).exists() is False
|
||||
|
||||
# check num queries
|
||||
Booking.objects.create(
|
||||
event=event, request_uuid=request_uuid, previous_state='cancelled', cancellation_datetime=now()
|
||||
)
|
||||
event = Event.objects.create(
|
||||
label='Event',
|
||||
start_datetime=now() + datetime.timedelta(days=5),
|
||||
duration=120,
|
||||
places=1,
|
||||
agenda=agenda,
|
||||
)
|
||||
Booking.objects.create(
|
||||
event=event, request_uuid=request_uuid, previous_state='booked', cancellation_datetime=now()
|
||||
)
|
||||
event = Event.objects.create(
|
||||
label='Event',
|
||||
start_datetime=now() + datetime.timedelta(days=5),
|
||||
duration=120,
|
||||
places=1,
|
||||
agenda=agenda,
|
||||
)
|
||||
Booking.objects.create(
|
||||
event=event, request_uuid=request_uuid, previous_state='unbooked', cancellation_datetime=now()
|
||||
)
|
||||
with CaptureQueriesContext(connection) as ctx:
|
||||
resp = app.post(revert_url)
|
||||
assert len(ctx.captured_queries) == 13
|
||||
|
|
Loading…
Reference in New Issue