api: merge category selection into agenda options (#71187) #8
|
@ -293,7 +293,7 @@ class StatisticsFiltersSerializer(serializers.Serializer):
|
||||||
start = serializers.DateTimeField(required=False, input_formats=['iso-8601', '%Y-%m-%d'])
|
start = serializers.DateTimeField(required=False, input_formats=['iso-8601', '%Y-%m-%d'])
|
||||||
end = serializers.DateTimeField(required=False, input_formats=['iso-8601', '%Y-%m-%d'])
|
end = serializers.DateTimeField(required=False, input_formats=['iso-8601', '%Y-%m-%d'])
|
||||||
category = serializers.SlugField(required=False, allow_blank=False, max_length=256)
|
category = serializers.SlugField(required=False, allow_blank=False, max_length=256)
|
||||||
agenda = serializers.SlugField(required=False, allow_blank=False, max_length=256)
|
agenda = serializers.CharField(required=False, allow_blank=False, max_length=256)
|
||||||
fpeters marked this conversation as resolved
|
|||||||
group_by = serializers.ListField(
|
group_by = serializers.ListField(
|
||||||
required=False, child=serializers.SlugField(allow_blank=False, max_length=256)
|
required=False, child=serializers.SlugField(allow_blank=False, max_length=256)
|
||||||
)
|
)
|
||||||
|
|
|
@ -3051,10 +3051,6 @@ class StatisticsList(APIView):
|
||||||
category_options = [{'id': '_all', 'label': pgettext('categories', 'All')}] + [
|
category_options = [{'id': '_all', 'label': pgettext('categories', 'All')}] + [
|
||||||
{'id': x.slug, 'label': x.label} for x in categories
|
{'id': x.slug, 'label': x.label} for x in categories
|
||||||
]
|
]
|
||||||
agendas = Agenda.objects.all()
|
|
||||||
agenda_options = [{'id': '_all', 'label': pgettext('agendas', 'All')}] + [
|
|
||||||
{'id': x.slug, 'label': x.label} for x in agendas
|
|
||||||
]
|
|
||||||
return Response(
|
return Response(
|
||||||
{
|
{
|
||||||
'data': [
|
'data': [
|
||||||
|
@ -3078,11 +3074,15 @@ class StatisticsList(APIView):
|
||||||
'required': True,
|
'required': True,
|
||||||
'default': '_all',
|
'default': '_all',
|
||||||
'has_subfilters': True,
|
'has_subfilters': True,
|
||||||
|
'deprecated': True,
|
||||||
|
'deprecation_hint': _(
|
||||||
|
'Category should now be selected using the Agenda field below.'
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'id': 'agenda',
|
'id': 'agenda',
|
||||||
'label': _('Agenda'),
|
'label': _('Agenda'),
|
||||||
'options': agenda_options,
|
'options': self.get_agenda_options(),
|
||||||
'required': True,
|
'required': True,
|
||||||
'default': '_all',
|
'default': '_all',
|
||||||
'has_subfilters': True,
|
'has_subfilters': True,
|
||||||
|
@ -3093,6 +3093,34 @@ class StatisticsList(APIView):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_agenda_options():
|
||||||
|
all_agendas_option = [{'id': '_all', 'label': pgettext('agendas', 'All')}]
|
||||||
|
|
||||||
|
agendas = Agenda.objects.all().order_by('category__name')
|
||||||
|
agendas_with_category = [x for x in agendas if x.category]
|
||||||
|
if not agendas_with_category:
|
||||||
|
return all_agendas_option + [{'id': x.slug, 'label': x.label} for x in agendas]
|
||||||
|
|
||||||
|
agenda_options = {None: all_agendas_option}
|
||||||
|
for agenda in agendas_with_category:
|
||||||
|
if agenda.category.label not in agenda_options:
|
||||||
|
agenda_options[agenda.category.label] = [
|
||||||
|
{
|
||||||
|
'id': 'category:' + agenda.category.slug,
|
||||||
|
'label': _('All agendas of category %s') % agenda.category.label,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
agenda_options[agenda.category.label].append({'id': agenda.slug, 'label': agenda.label})
|
||||||
|
|
||||||
|
agendas_without_category_options = [
|
||||||
|
{'id': x.slug, 'label': x.label} for x in agendas if not x.category
|
||||||
|
]
|
||||||
|
if agendas_without_category_options:
|
||||||
|
agenda_options[_('Misc')] = agendas_without_category_options
|
||||||
|
|
||||||
|
return list(agenda_options.items())
|
||||||
|
|
||||||
|
|
||||||
statistics_list = StatisticsList.as_view()
|
statistics_list = StatisticsList.as_view()
|
||||||
|
|
||||||
|
@ -3114,13 +3142,17 @@ class BookingsStatistics(APIView):
|
||||||
if 'end' in data:
|
if 'end' in data:
|
||||||
bookings = bookings.filter(event__start_datetime__lte=data['end'])
|
bookings = bookings.filter(event__start_datetime__lte=data['end'])
|
||||||
|
|
||||||
if 'category' in data and data['category'] != '_all':
|
agenda_slug = data.get('agenda', '_all')
|
||||||
bookings = bookings.filter(event__agenda__category__slug=data['category'])
|
category_slug = data.get('category', '_all')
|
||||||
subfilters = self.get_subfilters(agendas=Agenda.objects.filter(category__slug=data['category']))
|
if agenda_slug.startswith('category:'):
|
||||||
|
category_slug = agenda_slug.split(':', 1)[1]
|
||||||
|
|
||||||
if 'agenda' in data and data['agenda'] != '_all':
|
if category_slug != '_all':
|
||||||
bookings = bookings.filter(event__agenda__slug=data['agenda'])
|
bookings = bookings.filter(event__agenda__category__slug=category_slug)
|
||||||
subfilters = self.get_subfilters(agendas=Agenda.objects.filter(slug=data['agenda']))
|
subfilters = self.get_subfilters(agendas=Agenda.objects.filter(category__slug=category_slug))
|
||||||
|
elif agenda_slug != '_all':
|
||||||
|
bookings = bookings.filter(event__agenda__slug=agenda_slug)
|
||||||
|
subfilters = self.get_subfilters(agendas=Agenda.objects.filter(slug=agenda_slug))
|
||||||
|
|
||||||
bookings = bookings.annotate(day=TruncDay('event__start_datetime'))
|
bookings = bookings.annotate(day=TruncDay('event__start_datetime'))
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,10 @@ pytestmark = pytest.mark.django_db
|
||||||
|
|
||||||
|
|
||||||
def test_statistics_list(app, user):
|
def test_statistics_list(app, user):
|
||||||
Agenda.objects.create(label='Foo bar')
|
agenda = Agenda.objects.create(label='Foo bar')
|
||||||
Agenda.objects.create(label='Bar foo')
|
agenda2 = Agenda.objects.create(label='Bar foo')
|
||||||
Category.objects.create(label='Category A')
|
category = Category.objects.create(label='Category A')
|
||||||
Category.objects.create(label='Category B')
|
category2 = Category.objects.create(label='Category B')
|
||||||
|
|
||||||
# unauthorized
|
# unauthorized
|
||||||
app.get('/api/statistics/', status=401)
|
app.get('/api/statistics/', status=401)
|
||||||
|
@ -20,7 +20,51 @@ def test_statistics_list(app, user):
|
||||||
category_filter = [x for x in resp.json['data'][0]['filters'] if x['id'] == 'category'][0]
|
category_filter = [x for x in resp.json['data'][0]['filters'] if x['id'] == 'category'][0]
|
||||||
assert len(category_filter['options']) == 3
|
assert len(category_filter['options']) == 3
|
||||||
agenda_filter = [x for x in resp.json['data'][0]['filters'] if x['id'] == 'agenda'][0]
|
agenda_filter = [x for x in resp.json['data'][0]['filters'] if x['id'] == 'agenda'][0]
|
||||||
assert len(agenda_filter['options']) == 3
|
assert agenda_filter['options'] == [
|
||||||
|
{'id': '_all', 'label': 'All'},
|
||||||
|
{'id': 'bar-foo', 'label': 'Bar foo'},
|
||||||
|
{'id': 'foo-bar', 'label': 'Foo bar'},
|
||||||
|
]
|
||||||
|
|
||||||
|
agenda.category = category
|
||||||
|
agenda.save()
|
||||||
|
|
||||||
|
resp = app.get('/api/statistics/')
|
||||||
|
agenda_filter = [x for x in resp.json['data'][0]['filters'] if x['id'] == 'agenda'][0]
|
||||||
|
assert agenda_filter['options'] == [
|
||||||
|
[None, [{'id': '_all', 'label': 'All'}]],
|
||||||
|
[
|
||||||
|
'Category A',
|
||||||
|
[
|
||||||
|
{'id': 'category:category-a', 'label': 'All agendas of category Category A'},
|
||||||
|
{'id': 'foo-bar', 'label': 'Foo bar'},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
['Misc', [{'id': 'bar-foo', 'label': 'Bar foo'}]],
|
||||||
|
]
|
||||||
|
|
||||||
|
agenda2.category = category2
|
||||||
|
agenda2.save()
|
||||||
|
|
||||||
|
resp = app.get('/api/statistics/')
|
||||||
|
agenda_filter = [x for x in resp.json['data'][0]['filters'] if x['id'] == 'agenda'][0]
|
||||||
|
assert agenda_filter['options'] == [
|
||||||
|
[None, [{'id': '_all', 'label': 'All'}]],
|
||||||
|
[
|
||||||
|
'Category A',
|
||||||
|
[
|
||||||
|
{'id': 'category:category-a', 'label': 'All agendas of category Category A'},
|
||||||
|
{'id': 'foo-bar', 'label': 'Foo bar'},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Category B',
|
||||||
|
[
|
||||||
|
{'id': 'category:category-b', 'label': 'All agendas of category Category B'},
|
||||||
|
{'id': 'bar-foo', 'label': 'Bar foo'},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_statistics_bookings(app, user, freezer):
|
def test_statistics_bookings(app, user, freezer):
|
||||||
|
@ -58,6 +102,11 @@ def test_statistics_bookings(app, user, freezer):
|
||||||
Booking.objects.create(event=event3)
|
Booking.objects.create(event=event3)
|
||||||
|
|
||||||
# category filter
|
# category filter
|
||||||
|
resp = app.get(url + '?agenda=category:category-a')
|
||||||
|
assert resp.json['data']['x_labels'] == ['2020-10-25']
|
||||||
|
assert resp.json['data']['series'] == [{'label': 'Bookings Count', 'data': [1]}]
|
||||||
|
|
||||||
|
# legacy, category filter
|
||||||
resp = app.get(url + '?category=category-a')
|
resp = app.get(url + '?category=category-a')
|
||||||
assert resp.json['data']['x_labels'] == ['2020-10-25']
|
assert resp.json['data']['x_labels'] == ['2020-10-25']
|
||||||
assert resp.json['data']['series'] == [{'label': 'Bookings Count', 'data': [1]}]
|
assert resp.json['data']['series'] == [{'label': 'Bookings Count', 'data': [1]}]
|
||||||
|
|
Loading…
Reference in New Issue
Le changement ici c'est pour accepter le : dans un category:whatever, correct ?
(commentaire à 90% fait pour tester les commentaires gitea).
Oui, grosse flemme de mettre une regex mais je me plierai à ce que demandera la relecture.