statistics: allow group by form when filtering on many forms (#85530)

This commit is contained in:
Valentin Deniaud 2024-02-22 11:14:55 +01:00
parent 8f5d6ab0b9
commit f39f15f2b6
2 changed files with 55 additions and 24 deletions

View File

@ -1070,8 +1070,12 @@ def test_statistics_forms_count_group_by_same_varname(pub, formdef):
def test_statistics_forms_count_group_by_form(pub):
category_a = Category(name='Category A')
category_a.store()
formdef = FormDef()
formdef.name = 'A'
formdef.category_id = category_a.id
formdef.store()
for i in range(10):
@ -1082,6 +1086,7 @@ def test_statistics_forms_count_group_by_form(pub):
formdef = FormDef()
formdef.name = 'B'
formdef.category_id = category_a.id
formdef.store()
for i in range(5):
@ -1096,6 +1101,7 @@ def test_statistics_forms_count_group_by_form(pub):
'id': 'group-by',
'label': 'Group by',
'options': [{'id': 'form', 'label': 'Form'}],
'has_subfilters': True,
}
resp = get_app(pub).get(sign_uri('/api/statistics/forms/count/?time_interval=year'))
@ -1113,6 +1119,18 @@ def test_statistics_forms_count_group_by_form(pub):
assert resp.json['data']['x_labels'] == ['A', 'B']
assert resp.json['data']['series'] == [{'data': [10, 5], 'label': 'Forms Count'}]
resp = get_app(pub).get(
sign_uri('/api/statistics/forms/count/?time_interval=none&group-by=form&form=category:category-a')
)
assert resp.json['data']['x_labels'] == ['A', 'B']
assert resp.json['data']['series'] == [{'data': [10, 5], 'label': 'Forms Count'}]
resp = get_app(pub).get(
sign_uri('/api/statistics/forms/count/?time_interval=none&group-by=form&form=a&form=b')
)
assert resp.json['data']['x_labels'] == ['A', 'B']
assert resp.json['data']['series'] == [{'data': [10, 5], 'label': 'Forms Count'}]
def test_statistics_forms_count_months_to_show(pub, formdef):
for i in range(24):
@ -1708,6 +1726,7 @@ def test_statistics_multiple_forms_count_subfilters(pub, formdef):
# group-by subfilter shows all common fields
group_by_filter = [x for x in resp.json['data']['subfilters'] if x['id'] == 'group-by'][0]
assert group_by_filter['options'] == [
{'id': 'form', 'label': 'Form'},
{'id': 'channel', 'label': 'Channel'},
{'id': 'simple-status', 'label': 'Simplified status'},
{'id': 'test-item', 'label': 'Test item'},
@ -1732,3 +1751,10 @@ def test_statistics_multiple_forms_count_subfilters(pub, formdef):
category_resp = get_app(pub).get(sign_uri('/api/statistics/forms/count/?form=category:category-a'))
assert category_resp.json == resp.json
# cannot group by form if single form is selected
form_resp = get_app(pub).get(sign_uri('/api/statistics/forms/count/?form=test'))
form_group_by_filter = [x for x in form_resp.json['data']['subfilters'] if x['id'] == 'group-by'][0]
assert [x for x in group_by_filter['options'] if x not in form_group_by_filter['options']] == [
{'id': 'form', 'label': 'Form'}
]

View File

@ -232,7 +232,6 @@ class FormsCountView(RestrictedView):
}
group_by = request.GET.get('group-by')
group_labels = {}
subfilters = self.get_common_subfilters(time_interval)
formdefs = []
slugs = request.GET.getlist('form', ['_all'] if self.has_global_count_support else ['_nothing'])
@ -245,16 +244,15 @@ class FormsCountView(RestrictedView):
if not formdefs:
raise TraversalError()
subfilters = self.get_common_subfilters(time_interval, formdefs)
if formdefs:
for formdef in formdefs:
formdef.form_page = self.formpage_class(formdef=formdef, update_breadcrumbs=False)
self.set_formdef_parameters(totals_kwargs, formdefs)
totals_kwargs['criterias'].extend(self.get_filters_criterias(formdefs))
subfilters += self.get_formdefs_subfilters(formdefs, group_by, time_interval)
else:
subfilters += [
{'id': 'group-by', 'label': _('Group by'), 'options': [{'id': 'form', 'label': _('Form')}]}
]
self.add_formdefs_subfilters(subfilters, formdefs, group_by, time_interval)
self.set_group_by_parameters(group_by, formdefs, totals_kwargs, group_labels)
@ -363,7 +361,7 @@ class FormsCountView(RestrictedView):
return criterias
def get_common_subfilters(self, time_interval):
def get_common_subfilters(self, time_interval, formdefs):
subfilters = []
if time_interval == 'month':
@ -381,9 +379,22 @@ class FormsCountView(RestrictedView):
}
)
group_by_filter = {
'id': 'group-by',
'label': _('Group by'),
'has_subfilters': True,
'options': [],
}
if len(formdefs) != 1:
# allow grouping by form only if no form is selected or many are selected
group_by_filter['options'].append({'id': 'form', 'label': _('Form')})
subfilters.append(group_by_filter)
return subfilters
def get_formdefs_subfilters(self, formdefs, group_by, time_interval):
def add_formdefs_subfilters(self, common_subfilters, formdefs, group_by, time_interval):
subfilters = None
for formdef in formdefs:
new_subfilters = self.get_form_subfilters(formdef.form_page)
@ -418,23 +429,19 @@ class FormsCountView(RestrictedView):
if needs_sorting:
subfilter['options'].sort(key=lambda x: x['label'])
additionnal_filters = [
{
'id': 'group-by',
'label': _('Group by'),
'options': [
{'id': 'channel', 'label': _('Channel')},
{'id': 'simple-status', 'label': _('Simplified status')},
]
+ [{'id': x['id'].removeprefix('filter-'), 'label': x['label']} for x in subfilters],
'has_subfilters': True,
}
]
group_by_filter = [x for x in common_subfilters if x['id'] == 'group-by'][0]
group_by_filter['options'].extend(
[
{'id': 'channel', 'label': _('Channel')},
{'id': 'simple-status', 'label': _('Simplified status')},
]
+ [{'id': x['id'].removeprefix('filter-'), 'label': x['label']} for x in subfilters]
)
if group_by not in (None, 'channel', 'simple-status', 'status'):
group_by_field = self.get_group_by_field(formdefs[0].form_page, group_by)
if group_by_field:
additionnal_filters.append(
common_subfilters.append(
{
'id': 'hide_none_label',
'label': _('Ignore forms where "%s" is empty.') % group_by_field.label,
@ -444,9 +451,7 @@ class FormsCountView(RestrictedView):
}
)
subfilters = additionnal_filters + subfilters
return subfilters
common_subfilters.extend(subfilters)
def get_form_subfilters(self, form_page):
subfilters = []