api: add real agenda info for each slot (#78064)
gitea/chrono/pipeline/head This commit looks good
Details
gitea/chrono/pipeline/head This commit looks good
Details
This commit is contained in:
parent
0e84adb3ac
commit
a303d359d8
|
@ -801,25 +801,55 @@ class MeetingDatetimes(APIView):
|
|||
# slot from the list if there is still a bookable slot on a desk at the
|
||||
# same time.
|
||||
# The generator also remove slots starting before the current time.
|
||||
def unique_slots():
|
||||
last_slot = None
|
||||
all_slots = list(
|
||||
agenda.get_all_slots(
|
||||
meeting_type,
|
||||
resources=resources,
|
||||
unique=True,
|
||||
start_datetime=start_datetime,
|
||||
end_datetime=end_datetime,
|
||||
user_external_id=booked_user_external_id or excluded_user_external_id,
|
||||
if agenda.kind == 'meetings':
|
||||
|
||||
def unique_slots():
|
||||
last_slot = None
|
||||
all_slots = list(
|
||||
agenda.get_all_slots(
|
||||
meeting_type,
|
||||
resources=resources,
|
||||
unique=True,
|
||||
start_datetime=start_datetime,
|
||||
end_datetime=end_datetime,
|
||||
user_external_id=booked_user_external_id or excluded_user_external_id,
|
||||
)
|
||||
)
|
||||
)
|
||||
for slot in sorted(all_slots, key=lambda slot: slot[:3]):
|
||||
if slot.start_datetime < now_datetime:
|
||||
continue
|
||||
if last_slot and last_slot[:2] == slot[:2]:
|
||||
continue
|
||||
last_slot = slot
|
||||
yield slot
|
||||
for slot in sorted(all_slots, key=lambda slot: slot[:3]):
|
||||
if slot.start_datetime < now_datetime:
|
||||
continue
|
||||
if last_slot and last_slot[:2] == slot[:2]:
|
||||
continue
|
||||
last_slot = slot
|
||||
yield slot, None
|
||||
|
||||
elif agenda.kind == 'virtual':
|
||||
|
||||
def unique_slots():
|
||||
all_slots = list(
|
||||
agenda.get_all_slots(
|
||||
meeting_type,
|
||||
resources=resources,
|
||||
unique=False,
|
||||
start_datetime=start_datetime,
|
||||
end_datetime=end_datetime,
|
||||
user_external_id=booked_user_external_id or excluded_user_external_id,
|
||||
)
|
||||
)
|
||||
last_slot, slot_agendas = None, set()
|
||||
for slot in sorted(all_slots, key=lambda slot: slot[:3]):
|
||||
if slot.start_datetime < now_datetime:
|
||||
continue
|
||||
if last_slot is None:
|
||||
last_slot = slot
|
||||
elif last_slot[:2] != slot[:2]:
|
||||
yield last_slot, slot_agendas
|
||||
last_slot = slot
|
||||
slot_agendas = set()
|
||||
if not slot.full:
|
||||
slot_agendas.add(slot.desk.agenda)
|
||||
if last_slot:
|
||||
yield last_slot, slot_agendas
|
||||
|
||||
generator_of_unique_slots = unique_slots()
|
||||
|
||||
|
@ -839,7 +869,7 @@ class MeetingDatetimes(APIView):
|
|||
bookable_datetimes_number_available = 0
|
||||
first_bookable_slot = None
|
||||
data = []
|
||||
for slot in generator_of_unique_slots:
|
||||
for slot, slot_agendas in generator_of_unique_slots:
|
||||
if request.GET.get('hide_disabled') and slot.full:
|
||||
continue
|
||||
if minutes and slot.start_datetime.minute not in minutes:
|
||||
|
@ -861,6 +891,23 @@ class MeetingDatetimes(APIView):
|
|||
}
|
||||
if booked_user_external_id and slot.booked_for_external_user:
|
||||
slot_data['booked_for_external_user'] = True
|
||||
if slot_agendas is not None:
|
||||
slot_data['agendas'] = [
|
||||
{
|
||||
'id': agenda.id,
|
||||
'text': agenda.label,
|
||||
'slug': agenda.slug,
|
||||
'api': {
|
||||
'fillslot_url': request.build_absolute_uri(
|
||||
reverse(
|
||||
'api-fillslot',
|
||||
kwargs={'agenda_identifier': agenda.slug, 'event_identifier': slot_id},
|
||||
)
|
||||
)
|
||||
},
|
||||
}
|
||||
for agenda in sorted(slot_agendas, key=lambda a: a.label)
|
||||
]
|
||||
data.append(slot_data)
|
||||
|
||||
bookable_datetimes_number_total += 1
|
||||
|
|
|
@ -10,7 +10,6 @@ from chrono.agendas.models import (
|
|||
Desk,
|
||||
Event,
|
||||
MeetingType,
|
||||
Resource,
|
||||
TimePeriod,
|
||||
TimePeriodException,
|
||||
UnavailabilityCalendar,
|
||||
|
@ -18,6 +17,8 @@ from chrono.agendas.models import (
|
|||
)
|
||||
from chrono.utils.timezone import localtime, make_aware, now
|
||||
|
||||
from ...utils import build_virtual_agenda
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
|
@ -514,7 +515,7 @@ def test_virtual_agendas_meetings_datetimes_multiple_agendas(app, mock_now):
|
|||
with CaptureQueriesContext(connection) as ctx:
|
||||
resp = app.get(api_url)
|
||||
assert len(resp.json['data']) == 12
|
||||
assert len(ctx.captured_queries) == 10
|
||||
assert len(ctx.captured_queries) == 12
|
||||
|
||||
# simulate booking
|
||||
dt = datetime.datetime.strptime(resp.json['data'][2]['id'].split(':')[1], '%Y-%m-%d-%H%M')
|
||||
|
@ -643,7 +644,7 @@ def test_virtual_agendas_meetings_datetimes_exclude_slots(app):
|
|||
'/api/agenda/%s/meetings/%s/datetimes/' % (virt_agenda.slug, meeting_type.slug),
|
||||
params={'exclude_user_external_id': '42'},
|
||||
)
|
||||
assert len(ctx.captured_queries) == 11
|
||||
assert len(ctx.captured_queries) == 13
|
||||
assert resp.json['data'][0]['id'] == 'foo-bar:2021-02-26-0900'
|
||||
assert resp.json['data'][0]['disabled'] is True
|
||||
assert resp.json['data'][2]['id'] == 'foo-bar:2021-02-26-1000'
|
||||
|
@ -1188,3 +1189,63 @@ def test_datetimes_api_meetings_virtual_agenda_date_time_period(app):
|
|||
assert [x['datetime'] for x in resp.json['data']] == [
|
||||
'2022-10-24 13:00:00',
|
||||
]
|
||||
|
||||
|
||||
def test_show_available_agendas(app, user):
|
||||
agenda = build_virtual_agenda(
|
||||
agendas={
|
||||
'Agenda 1': {
|
||||
'desks': {
|
||||
'Desk 1': 'monday-sunday 08:00-12:00 14:00-17:00',
|
||||
'Desk 2': 'monday-sunday 08:00-12:00 14:00-17:00',
|
||||
},
|
||||
},
|
||||
'Agenda 2': {
|
||||
'desks': {
|
||||
'Desk 1': 'monday-sunday 08:00-12:00 14:00-17:00',
|
||||
'Desk 2': 'monday-sunday 08:00-12:00 14:00-17:00',
|
||||
},
|
||||
},
|
||||
},
|
||||
meeting_types=[30],
|
||||
)
|
||||
api_url = '/api/agenda/%s/meetings/mt-30/datetimes/' % agenda.slug
|
||||
resp = app.get(api_url)
|
||||
first_slot = resp.json['data'][0]
|
||||
assert first_slot['disabled'] is False
|
||||
assert len(first_slot['agendas']) == 2
|
||||
assert first_slot['agendas'][0]['text'] == 'Agenda 1'
|
||||
assert first_slot['agendas'][1]['text'] == 'Agenda 2'
|
||||
|
||||
## Make a booking directly on agenda 1, and check that nothing changed
|
||||
app.authorization = ('Basic', ('john.doe', 'password'))
|
||||
app.post(first_slot['agendas'][0]['api']['fillslot_url'])
|
||||
resp = app.get(api_url)
|
||||
first_slot = resp.json['data'][0]
|
||||
assert first_slot['disabled'] is False
|
||||
assert len(first_slot['agendas']) == 2
|
||||
assert first_slot['agendas'][0]['text'] == 'Agenda 1'
|
||||
assert first_slot['agendas'][1]['text'] == 'Agenda 2'
|
||||
|
||||
## Make a second booking directly on agenda 1, agenda 2 should be the only one left available
|
||||
app.post(first_slot['agendas'][0]['api']['fillslot_url'])
|
||||
resp = app.get(api_url)
|
||||
first_slot = resp.json['data'][0]
|
||||
assert first_slot['disabled'] is False
|
||||
assert len(first_slot['agendas']) == 1
|
||||
assert first_slot['agendas'][0]['text'] == 'Agenda 2'
|
||||
|
||||
## Make a booking directly on agenda 2, and check that nothing changed
|
||||
app.post(first_slot['agendas'][0]['api']['fillslot_url'])
|
||||
resp = app.get(api_url)
|
||||
first_slot = resp.json['data'][0]
|
||||
assert first_slot['disabled'] is False
|
||||
assert len(first_slot['agendas']) == 1
|
||||
assert first_slot['agendas'][0]['text'] == 'Agenda 2'
|
||||
|
||||
## Make a booking directly on agenda 2, the slots is full and no agenda available
|
||||
app.post(first_slot['agendas'][0]['api']['fillslot_url'])
|
||||
resp = app.get(api_url)
|
||||
first_slot = resp.json['data'][0]
|
||||
assert first_slot['disabled'] is True
|
||||
assert len(first_slot['agendas']) == 0
|
||||
|
|
Loading…
Reference in New Issue