Projet

Général

Profil

0001-api-allow-changing-recurrence-bookings-54746.patch

Valentin Deniaud, 15 juillet 2021 16:42

Télécharger (7 ko)

Voir les différences:

Subject: [PATCH] api: allow changing recurrence bookings (#54746)

 chrono/api/views.py        | 23 ++++++++++++---
 tests/api/test_fillslot.py | 60 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+), 4 deletions(-)
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
-