0001-api-allow-changing-recurrence-bookings-54746.patch
chrono/api/views.py | ||
---|---|---|
1594 | 1594 | |
1595 | 1595 |
events_to_book = Event.objects.filter(event_filter) |
1596 | 1596 |
events_to_book = events_to_book.filter(start_datetime__gte=start_datetime, cancelled=False) |
1597 |
if end_datetime: |
|
1598 |
events_to_book = events_to_book.filter(start_datetime__lte=end_datetime) |
|
1599 | ||
1600 |
events_to_unbook = list( |
|
1601 |
agenda.event_set.filter(booking__user_external_id=user_external_id) |
|
1602 |
.exclude(pk__in=events_to_book) |
|
1603 |
.values_list('pk', flat=True) |
|
1604 |
) |
|
1605 |
events_to_book = events_to_book.exclude(booking__user_external_id=user_external_id) |
|
1597 | 1606 | |
1598 | 1607 |
full_events = list(events_to_book.filter(full=True)) |
1599 | 1608 |
events_to_book = events_to_book.filter(full=False) |
1600 |
if end_datetime: |
|
1601 |
events_to_book = events_to_book.filter(start_datetime__lte=end_datetime) |
|
1602 | 1609 |
if not events_to_book.exists(): |
1603 | 1610 |
if full_events: |
1604 | 1611 |
raise APIError(_('all events are all full'), err_class='all events are all full') |
... | ... | |
1614 | 1621 |
extra_data = {k: v for k, v in request.data.items() if k not in payload} |
1615 | 1622 |
bookings = [make_booking(event, payload, extra_data) for event in events_to_book] |
1616 | 1623 | |
1624 |
events_to_update = Event.annotate_queryset( |
|
1625 |
agenda.event_set.filter(pk__in=events_to_unbook + [event.pk for event in events_to_book]) |
|
1626 |
) |
|
1617 | 1627 |
with transaction.atomic(): |
1628 |
deleted_count = Booking.objects.filter( |
|
1629 |
user_external_id=user_external_id, event__in=events_to_unbook |
|
1630 |
).delete()[0] |
|
1618 | 1631 |
Booking.objects.bulk_create(bookings) |
1632 | ||
1619 | 1633 |
if django.VERSION < (2, 0): |
1620 | 1634 |
from django.db.models import Case, When |
1621 | 1635 | |
1622 |
events_to_book.update(
|
|
1636 |
events_to_update.update(
|
|
1623 | 1637 |
full=Case( |
1624 | 1638 |
When( |
1625 | 1639 |
Q(booked_places_count__gte=F('places'), waiting_list_places=0) |
... | ... | |
1637 | 1651 |
), |
1638 | 1652 |
) |
1639 | 1653 |
else: |
1640 |
events_to_book.update(
|
|
1654 |
events_to_update.update(
|
|
1641 | 1655 |
full=Q(booked_places_count__gte=F('places'), waiting_list_places=0) |
1642 | 1656 |
| Q(waiting_list_places__gt=0, waiting_list_count__gte=F('waiting_list_places')), |
1643 | 1657 |
almost_full=Q(booked_places_count__gte=0.9 * F('places')), |
... | ... | |
1646 | 1660 |
response = { |
1647 | 1661 |
'err': 0, |
1648 | 1662 |
'booking_count': len(bookings), |
1663 |
'cancelled_booking_count': deleted_count, |
|
1649 | 1664 |
'full_events': [get_event_detail(request, x, agenda=agenda) for x in full_events], |
1650 | 1665 |
} |
1651 | 1666 |
return Response(response) |
tests/api/test_fillslot.py | ||
---|---|---|
2166 | 2166 |
assert resp.json['booking_count'] == 155 |
2167 | 2167 |
assert len(resp.json['full_events']) == 1 |
2168 | 2168 |
assert resp.json['full_events'][0]['slug'] == event.slug |
2169 |
resp = app.post_json(fillslots_url, params=params) |
|
2169 | 2170 | |
2170 | 2171 |
params['user_external_id'] = 'user_id_4' |
2171 | 2172 |
resp = app.post_json(fillslots_url, params=params) |
... | ... | |
2193 | 2194 |
resp = app.post_json(fillslots_url, params={'user_external_id': 'a', 'slots': 'a:1'}, status=400) |
2194 | 2195 |
assert resp.json['err'] == 1 |
2195 | 2196 |
assert resp.json['err_desc'] == 'event a is not bookable' |
2197 | ||
2198 | ||
2199 |
def test_recurring_events_api_fillslots_change_bookings(app, user, freezer): |
|
2200 |
freezer.move_to('2021-09-06 12:00') |
|
2201 |
agenda = Agenda.objects.create(label='Foo bar', kind='events') |
|
2202 |
event = Event.objects.create( |
|
2203 |
label='Event', |
|
2204 |
start_datetime=now(), |
|
2205 |
recurrence_days=[0, 1, 3, 4], # Monday, Tuesday, Thursday, Friday |
|
2206 |
places=1, |
|
2207 |
waiting_list_places=1, |
|
2208 |
agenda=agenda, |
|
2209 |
recurrence_end_date=now() + datetime.timedelta(days=364), |
|
2210 |
) |
|
2211 |
event.create_all_recurrences() |
|
2212 | ||
2213 |
app.authorization = ('Basic', ('john.doe', 'password')) |
|
2214 |
fillslots_url = '/api/agenda/%s/recurring_fillslots/' % agenda.slug |
|
2215 |
params = {'user_external_id': 'user_id'} |
|
2216 |
# Book Monday and Thursday |
|
2217 |
params['slots'] = 'event:0,event:3' |
|
2218 |
resp = app.post_json(fillslots_url, params=params) |
|
2219 |
assert resp.json['booking_count'] == 104 |
|
2220 |
assert resp.json['cancelled_booking_count'] == 0 |
|
2221 |
assert Booking.objects.count() == 104 |
|
2222 |
assert Booking.objects.filter(event__start_datetime__week_day=2).count() == 52 |
|
2223 |
assert Booking.objects.filter(event__start_datetime__week_day=5).count() == 52 |
|
2224 | ||
2225 |
# Change booking to Monday and Tuesday |
|
2226 |
params['slots'] = 'event:0,event:1' |
|
2227 |
resp = app.post_json(fillslots_url, params=params) |
|
2228 |
assert resp.json['booking_count'] == 52 |
|
2229 |
assert resp.json['cancelled_booking_count'] == 52 |
|
2230 |
assert Booking.objects.count() == 104 |
|
2231 |
assert Booking.objects.filter(event__start_datetime__week_day=2).count() == 52 |
|
2232 |
assert Booking.objects.filter(event__start_datetime__week_day=3).count() == 52 |
|
2233 | ||
2234 |
params = {'user_external_id': 'user_id_2'} |
|
2235 |
params['slots'] = 'event:0,event:3' |
|
2236 |
resp = app.post_json(fillslots_url, params=params) |
|
2237 |
assert resp.json['booking_count'] == 104 |
|
2238 |
assert resp.json['cancelled_booking_count'] == 0 |
|
2239 |
assert Booking.objects.count() == 208 |
|
2240 |
assert Booking.objects.filter(event__start_datetime__week_day=2).count() == 104 |
|
2241 |
assert Booking.objects.filter(event__start_datetime__week_day=5).count() == 52 |
|
2242 |
events = Event.annotate_queryset(Event.objects.filter(primary_event__isnull=False)) |
|
2243 |
assert events.filter(booked_places_count=1).count() == 156 |
|
2244 |
assert events.filter(waiting_list_count=1).count() == 52 |
|
2245 | ||
2246 |
params['slots'] = 'event:1,event:4' |
|
2247 |
resp = app.post_json(fillslots_url, params=params) |
|
2248 |
assert resp.json['booking_count'] == 104 |
|
2249 |
assert resp.json['cancelled_booking_count'] == 104 |
|
2250 |
assert Booking.objects.count() == 208 |
|
2251 |
assert Booking.objects.filter(event__start_datetime__week_day=3).count() == 104 |
|
2252 |
assert Booking.objects.filter(event__start_datetime__week_day=6).count() == 52 |
|
2253 |
events = Event.annotate_queryset(Event.objects.filter(primary_event__isnull=False)) |
|
2254 |
assert events.filter(booked_places_count=1).count() == 156 |
|
2255 |
assert events.filter(waiting_list_count=1).count() == 52 |
|
2196 |
- |