Projet

Général

Profil

0001-agendas-add-date-filter-params-on-datetimes-api-4807.patch

Emmanuel Cazenave, 02 novembre 2020 16:23

Télécharger (8,82 ko)

Voir les différences:

Subject: [PATCH] agendas: add date filter params on datetimes api (#48078)

 chrono/api/views.py | 58 +++++++++++++++++++++++++++--------
 tests/test_api.py   | 75 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 121 insertions(+), 12 deletions(-)
chrono/api/views.py
64 64
    return localtime(dt).strftime('%Y-%m-%d %H:%M:%S')
65 65

  
66 66

  
67
def get_min_datetime(agenda):
68
    if agenda.minimal_booking_delay is None:
67
def get_min_datetime(agenda, start_datetime=None):
68
    if agenda.minimal_booking_delay is None and start_datetime is None:
69 69
        return None
70
    elif agenda.minimal_booking_delay is None:
71
        return start_datetime
72

  
70 73
    min_datetime = now() + datetime.timedelta(days=agenda.minimal_booking_delay)
71
    return min_datetime.replace(hour=0, minute=0, second=0, microsecond=0)
74
    min_datetime = min_datetime.replace(hour=0, minute=0, second=0, microsecond=0)
75
    if start_datetime is None:
76
        return min_datetime
77
    return max(min_datetime, start_datetime)
72 78

  
73 79

  
74
def get_max_datetime(agenda):
75
    if agenda.maximal_booking_delay is None:
80
def get_max_datetime(agenda, end_datetime=None):
81
    if agenda.maximal_booking_delay is None and end_datetime is None:
76 82
        return None
83
    elif agenda.maximal_booking_delay is None:
84
        return end_datetime
85

  
77 86
    max_datetime = now() + datetime.timedelta(days=agenda.maximal_booking_delay)
78 87
    max_datetime = max_datetime.replace(hour=0, minute=0, second=0, microsecond=0)
79
    return max_datetime
88
    if end_datetime is None:
89
        return max_datetime
90
    return min(max_datetime, end_datetime)
80 91

  
81 92

  
82 93
TimeSlot = collections.namedtuple('TimeSlot', ['start_datetime', 'end_datetime', 'full', 'desk'])
83 94

  
84 95

  
85
def get_all_slots(base_agenda, meeting_type, resources=None, unique=False):
96
def get_all_slots(
97
    base_agenda, meeting_type, resources=None, unique=False, start_datetime=None, end_datetime=None
98
):
86 99
    '''Get all occupation state of all possible slots for the given agenda (of
87 100
       its real agendas for a virtual agenda) and the given meeting_type.
88 101

  
......
107 120
    # that the base_meeting_duration for the virtual agenda is always the same
108 121
    # as the base meeting duration of each real agenda.
109 122
    base_meeting_duration = base_agenda.get_base_meeting_duration()
110
    base_min_datetime = get_min_datetime(base_agenda)
111
    base_max_datetime = get_max_datetime(base_agenda)
123
    base_min_datetime = get_min_datetime(base_agenda, start_datetime)
124
    base_max_datetime = get_max_datetime(base_agenda, end_datetime)
112 125

  
113 126
    meeting_duration = meeting_type.duration
114 127
    meeting_duration_td = datetime.timedelta(minutes=meeting_duration)
......
121 134
    agenda_ids_by_min_max_datetimes = collections.defaultdict(set)
122 135
    agenda_id_min_max_datetime = {}
123 136
    for agenda in agendas:
124
        used_min_datetime = base_min_datetime or get_min_datetime(agenda)
125
        used_max_datetime = base_max_datetime or get_max_datetime(agenda)
137
        used_min_datetime = base_min_datetime or get_min_datetime(agenda, start_datetime)
138
        used_max_datetime = base_max_datetime or get_max_datetime(agenda, end_datetime)
126 139
        agenda_ids_by_min_max_datetimes[(used_min_datetime, used_max_datetime)].add(agenda.id)
127 140
        agenda_id_min_max_datetime[agenda.id] = (used_min_datetime, used_max_datetime)
128 141

  
......
518 531
        except APIError as e:
519 532
            return e.to_response()
520 533

  
534
        start_datetime = None
535
        if 'date_start' in request.GET:
536
            start_datetime = make_aware(
537
                datetime.datetime.combine(parse_date(request.GET['date_start']), datetime.time(0, 0))
538
            )
539

  
540
        end_datetime = None
541
        if 'date_end' in request.GET:
542
            end_datetime = make_aware(
543
                datetime.datetime.combine(parse_date(request.GET['date_end']), datetime.time(0, 0))
544
            )
545

  
521 546
        # Generate an unique slot for each possible meeting [start_datetime,
522 547
        # end_datetime] range.
523 548
        # First use get_all_slots() to get each possible meeting by desk and
......
531 556
        # The generator also remove slots starting before the current time.
532 557
        def unique_slots():
533 558
            last_slot = None
534
            all_slots = list(get_all_slots(agenda, meeting_type, resources=resources, unique=True))
559
            all_slots = list(
560
                get_all_slots(
561
                    agenda,
562
                    meeting_type,
563
                    resources=resources,
564
                    unique=True,
565
                    start_datetime=start_datetime,
566
                    end_datetime=end_datetime,
567
                )
568
            )
535 569
            for slot in sorted(all_slots, key=lambda slot: slot[:3]):
536 570
                if slot.start_datetime < now_datetime:
537 571
                    continue
tests/test_api.py
4451 4451
    resp = app.get(api_url)
4452 4452
    data = resp.json['data']
4453 4453
    assert len(data) == 4
4454

  
4455

  
4456
def test_meetings_and_virtual_datetimes_date_filter(app):
4457
    agenda_foo = Agenda.objects.create(
4458
        label=u'Agenda Foo', kind='meetings', minimal_booking_delay=1, maximal_booking_delay=7
4459
    )
4460
    meeting_type = MeetingType.objects.create(agenda=agenda_foo, label='Meeting Type', duration=30)
4461
    desk_foo = Desk.objects.create(agenda=agenda_foo, label='Desk 1')
4462
    weekday1 = (localtime(now())).weekday() + 1 % 7
4463
    weekday2 = (localtime(now())).weekday() + 2 % 7
4464
    weekday3 = (localtime(now())).weekday() + 3 % 7
4465
    weekday4 = (localtime(now())).weekday() + 4 % 7
4466
    weekday5 = (localtime(now())).weekday() + 5 % 7
4467
    weekday6 = (localtime(now())).weekday() + 6 % 7
4468
    for weekday in (weekday1, weekday2, weekday3, weekday4, weekday5, weekday6):
4469
        TimePeriod.objects.create(
4470
            weekday=weekday, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0), desk=desk_foo,
4471
        )
4472

  
4473
    virtual_agenda = Agenda.objects.create(
4474
        label=u'Agenda Virtual', kind='virtual', minimal_booking_delay=1, maximal_booking_delay=7
4475
    )
4476
    VirtualMember.objects.create(virtual_agenda=virtual_agenda, real_agenda=agenda_foo)
4477

  
4478
    # 4 slots each day * 6 days
4479
    foo_api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (agenda_foo.slug, meeting_type.slug)
4480
    resp = app.get(foo_api_url)
4481
    assert len(resp.json['data']) == 24
4482
    virtual_api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (virtual_agenda.slug, meeting_type.slug)
4483
    resp = app.get(virtual_api_url)
4484
    assert len(resp.json['data']) == 24
4485

  
4486
    # exclude weekday1 through date_start, 4 slots each day * 5 days
4487
    params = {'date_start': (localtime(now()) + datetime.timedelta(days=2)).date().isoformat()}
4488
    resp = app.get(foo_api_url, params=params)
4489
    assert len(resp.json['data']) == 20
4490
    resp = app.get(virtual_api_url, params=params)
4491
    assert len(resp.json['data']) == 20
4492

  
4493
    # minimal_booking_delay (which exclude weekday1 and wekkday2 ) takes precedence
4494
    # 4 slots each day * 4 days
4495
    agenda_foo.minimal_booking_delay = 3
4496
    agenda_foo.save()
4497
    resp = app.get(foo_api_url, params=params)
4498
    assert len(resp.json['data']) == 16
4499
    # also on virtual agenda
4500
    virtual_agenda.minimal_booking_delay = 3
4501
    virtual_agenda.save()
4502
    resp = app.get(virtual_api_url, params=params)
4503
    assert len(resp.json['data']) == 16
4504

  
4505
    # reset
4506
    agenda_foo.minimal_booking_delay = 1
4507
    virtual_agenda.minimal_booking_delay = 1
4508
    agenda_foo.save()
4509
    virtual_agenda.save()
4510

  
4511
    # exclude weekday6 through date_end, 4 slots each day * 5 days
4512
    params = {'date_end': (localtime(now()) + datetime.timedelta(days=6)).date().isoformat()}
4513
    resp = app.get(foo_api_url, params=params)
4514
    assert len(resp.json['data']) == 20
4515
    resp = app.get(virtual_api_url, params=params)
4516
    assert len(resp.json['data']) == 20
4517

  
4518
    # maximal_booking_delay (which exclude weekday5 and weekday6 ) takes precedence
4519
    # 4 slots each day * 4 days
4520
    agenda_foo.maximal_booking_delay = 5
4521
    agenda_foo.save()
4522
    resp = app.get(foo_api_url, params=params)
4523
    assert len(resp.json['data']) == 16
4524
    # also on virtual agenda
4525
    virtual_agenda.maximal_booking_delay = 5
4526
    virtual_agenda.save()
4527
    resp = app.get(virtual_api_url, params=params)
4528
    assert len(resp.json['data']) == 16
4454
-