api: return virtual agenda booking count in statistics (#79355)
gitea/chrono/pipeline/head This commit looks good Details

This commit is contained in:
Valentin Deniaud 2023-07-04 16:40:26 +02:00
parent 95618bd475
commit 3d576b48ee
2 changed files with 94 additions and 4 deletions

View File

@ -3234,7 +3234,9 @@ class BookingsStatistics(APIView):
if not agendas:
raise APIErrorBadRequest(_('No agendas found.'))
bookings = bookings.filter(event__agenda__in=agendas)
bookings = bookings.filter(
Q(event__agenda__in=agendas) | Q(event__agenda__virtual_agendas__in=agendas)
)
subfilters = self.get_subfilters(agendas=agendas)
bookings = bookings.annotate(day=TruncDay('event__start_datetime'))
@ -3306,7 +3308,9 @@ class BookingsStatistics(APIView):
def get_subfilters(self, agendas):
extra_data_keys = (
Booking.objects.filter(event__agenda__in=agendas)
Booking.objects.filter(
Q(event__agenda__in=agendas) | Q(event__agenda__virtual_agendas__in=agendas)
)
.annotate(extra_data_keys=Func('extra_data', function='jsonb_object_keys'))
.distinct('extra_data_keys')
.order_by('extra_data_keys')

View File

@ -1,6 +1,8 @@
import datetime
import pytest
from chrono.agendas.models import Agenda, Booking, Category, Event
from chrono.agendas.models import Agenda, Booking, Category, Desk, Event, MeetingType, VirtualMember
from chrono.utils.timezone import now
pytestmark = pytest.mark.django_db
@ -9,6 +11,7 @@ pytestmark = pytest.mark.django_db
def test_statistics_list(app, user):
agenda = Agenda.objects.create(label='Foo bar')
agenda2 = Agenda.objects.create(label='Bar foo')
Agenda.objects.create(label='Virtual', kind='virtual')
category = Category.objects.create(label='Category A')
category2 = Category.objects.create(label='Category B')
@ -22,6 +25,7 @@ def test_statistics_list(app, user):
{'id': '_all', 'label': 'All'},
{'id': 'bar-foo', 'label': 'Bar foo'},
{'id': 'foo-bar', 'label': 'Foo bar'},
{'id': 'virtual', 'label': 'Virtual'},
]
agenda.category = category
@ -38,7 +42,7 @@ def test_statistics_list(app, user):
{'id': 'foo-bar', 'label': 'Foo bar'},
],
],
['Misc', [{'id': 'bar-foo', 'label': 'Bar foo'}]],
['Misc', [{'id': 'bar-foo', 'label': 'Bar foo'}, {'id': 'virtual', 'label': 'Virtual'}]],
]
agenda2.category = category2
@ -62,6 +66,7 @@ def test_statistics_list(app, user):
{'id': 'bar-foo', 'label': 'Bar foo'},
],
],
['Misc', [{'id': 'virtual', 'label': 'Virtual'}]],
]
@ -216,3 +221,84 @@ def test_statistics_bookings_subfilters_list(app, user):
resp = app.get(url + '?agenda=category:xxx', status=400)
assert resp.json['err_desc'] == 'No agendas found.'
@pytest.mark.freeze_time('2020-10-01 14:00')
def test_statistics_bookings_virtual(app, user):
agenda_foo = Agenda.objects.create(label='Agenda Foo', kind='meetings')
mt = MeetingType.objects.create(agenda=agenda_foo, label='Meeting Type', duration=30)
desk = Desk.objects.create(agenda=agenda_foo, label='Desk 1')
# 3 bookings on 01/10
for i in range(3):
start_datetime = now() + datetime.timedelta(hours=i)
event = Event.objects.create(
agenda=agenda_foo, meeting_type=mt, places=1, start_datetime=start_datetime, desk=desk
)
Booking.objects.create(event=event)
# 1 booking on 02/10
start_datetime = now() + datetime.timedelta(days=1)
event = Event.objects.create(
agenda=agenda_foo, meeting_type=mt, places=1, start_datetime=start_datetime, desk=desk
)
real_booking = Booking.objects.create(event=event)
agenda_bar = Agenda.objects.create(label='Agenda Bar', kind='meetings')
mt = MeetingType.objects.create(agenda=agenda_bar, label='Meeting Type', duration=30)
desk = Desk.objects.create(agenda=agenda_bar, label='Desk 1')
# 1 booking on 02/10
start_datetime = now() + datetime.timedelta(days=1, hours=1)
event = Event.objects.create(
agenda=agenda_bar, meeting_type=mt, places=1, start_datetime=start_datetime, desk=desk
)
Booking.objects.create(event=event)
# 2 bookings on 03/10
for i in range(2):
start_datetime = now() + datetime.timedelta(days=2, hours=i)
event = Event.objects.create(
agenda=agenda_bar, meeting_type=mt, places=1, start_datetime=start_datetime, desk=desk
)
Booking.objects.create(event=event)
virtual_agenda = Agenda.objects.create(slug='virtual_agenda', kind='virtual')
VirtualMember.objects.create(virtual_agenda=virtual_agenda, real_agenda=agenda_foo)
VirtualMember.objects.create(virtual_agenda=virtual_agenda, real_agenda=agenda_bar)
# normal booking on 01/10
agenda = Agenda.objects.create(label='Foo bar', kind='events')
event = Event.objects.create(start_datetime=now(), places=5, agenda=agenda)
Booking.objects.create(event=event)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/statistics/')
url = [x for x in resp.json['data'] if x['id'] == 'bookings_count'][0]['url']
resp = app.get(url + '?time_interval=day')
assert resp.json['data']['x_labels'] == ['2020-10-01', '2020-10-02', '2020-10-03']
assert resp.json['data']['series'][0]['data'] == [4, 2, 2]
resp = app.get(url + '?time_interval=day&agenda=virtual_agenda')
assert resp.json['data']['x_labels'] == ['2020-10-01', '2020-10-02', '2020-10-03']
assert resp.json['data']['series'][0]['data'] == [3, 2, 2]
# filter on category containing both real and virtual
category = Category.objects.create(label='Category A')
virtual_agenda.category = category
virtual_agenda.save()
agenda_foo.category = category
agenda_foo.save()
resp = app.get(url + '?time_interval=day&agenda=category:category-a')
assert resp.json['data']['x_labels'] == ['2020-10-01', '2020-10-02', '2020-10-03']
assert resp.json['data']['series'][0]['data'] == [3, 2, 2]
# check subfilters from real agendas are found
real_booking.extra_data = {'menu': 'vegetables'}
real_booking.save()
resp = app.get(url + '?agenda=virtual_agenda')
assert len(resp.json['data']['subfilters'][0]['options']) == 1
assert resp.json['data']['subfilters'][0]['options'][0] == {'id': 'menu', 'label': 'Menu'}