19 |
19 |
import itertools
|
20 |
20 |
import uuid
|
21 |
21 |
|
22 |
|
from django.db import transaction
|
|
22 |
from django.db import IntegrityError, transaction
|
23 |
23 |
from django.db.models import Prefetch, Q
|
24 |
24 |
from django.http import Http404, HttpResponse
|
25 |
25 |
from django.shortcuts import get_object_or_404
|
... | ... | |
918 |
918 |
def post(self, request, agenda_identifier=None, event_identifier=None, format=None):
|
919 |
919 |
return self.fillslot(request=request, agenda_identifier=agenda_identifier, format=format)
|
920 |
920 |
|
921 |
|
def fillslot(self, request, agenda_identifier=None, slots=[], format=None):
|
|
921 |
def fillslot(self, request, agenda_identifier=None, slots=[], format=None, retry=False):
|
922 |
922 |
multiple_booking = bool(not slots)
|
923 |
923 |
try:
|
924 |
924 |
agenda = Agenda.objects.get(slug=agenda_identifier)
|
... | ... | |
1138 |
1138 |
# booking requires real Event objects (not lazy Timeslots);
|
1139 |
1139 |
# create them now, with data from the slots and the desk we found.
|
1140 |
1140 |
events = []
|
1141 |
|
for start_datetime in datetimes:
|
1142 |
|
event = Event.objects.create(
|
1143 |
|
agenda=available_desk.agenda,
|
1144 |
|
slug=str(uuid.uuid4()), # set slug to avoid queries during slug generation
|
1145 |
|
meeting_type=meeting_type,
|
1146 |
|
start_datetime=start_datetime,
|
1147 |
|
full=False,
|
1148 |
|
places=1,
|
1149 |
|
desk=available_desk,
|
1150 |
|
)
|
1151 |
|
if resources:
|
1152 |
|
event.resources.add(*resources)
|
1153 |
|
events.append(event)
|
|
1141 |
try:
|
|
1142 |
with transaction.atomic():
|
|
1143 |
for start_datetime in datetimes:
|
|
1144 |
event = Event.objects.create(
|
|
1145 |
agenda=available_desk.agenda,
|
|
1146 |
slug=str(uuid.uuid4()), # set slug to avoid queries during slug generation
|
|
1147 |
meeting_type=meeting_type,
|
|
1148 |
start_datetime=start_datetime,
|
|
1149 |
full=False,
|
|
1150 |
places=1,
|
|
1151 |
desk=available_desk,
|
|
1152 |
)
|
|
1153 |
if resources:
|
|
1154 |
event.resources.add(*resources)
|
|
1155 |
events.append(event)
|
|
1156 |
except IntegrityError:
|
|
1157 |
# "optimistic concurrency control", between our availability
|
|
1158 |
# check with get_all_slots() and now, new event can have been
|
|
1159 |
# created and conflict with the events we want to create, and
|
|
1160 |
# so we get an IntegrityError exception. In this case we
|
|
1161 |
# restart the fillslot() from the begginning to redo the
|
|
1162 |
# availability check and return a proper error to the client.
|
|
1163 |
#
|
|
1164 |
# To prevent looping, we still raise the IntegrityError during
|
|
1165 |
# the second run of fillslot().
|
|
1166 |
if retry:
|
|
1167 |
raise
|
|
1168 |
return self.fillslot(request, agenda_identifier=agenda_identifier, slots=slots, retry=True)
|
1154 |
1169 |
else:
|
1155 |
1170 |
# convert event recurrence identifiers to real event slugs
|
1156 |
1171 |
for i, slot in enumerate(slots.copy()):
|
1157 |
|
-
|