stats permettre plus de regroupements (#85530) #1180
|
@ -569,6 +569,7 @@ def test_statistics_forms_count_subfilters(pub, formdef):
|
|||
|
||||
# remove fields and statuses
|
||||
workflow = Workflow(name='Empty wf')
|
||||
workflow.add_status('New')
|
||||
workflow.store()
|
||||
formdef.workflow = workflow
|
||||
formdef.fields.clear()
|
||||
|
@ -578,8 +579,31 @@ def test_statistics_forms_count_subfilters(pub, formdef):
|
|||
resp = get_app(pub).get(sign_uri(url))
|
||||
assert resp.json['data'] == {
|
||||
'series': [{'data': [], 'label': 'Forms Count'}],
|
||||
'subfilters': [],
|
||||
'x_labels': [],
|
||||
'subfilters': [
|
||||
{
|
||||
'has_subfilters': True,
|
||||
'id': 'group-by',
|
||||
'label': 'Group by',
|
||||
'options': [
|
||||
{'id': 'channel', 'label': 'Channel'},
|
||||
{'id': 'simple-status', 'label': 'Simplified status'},
|
||||
{'id': 'status', 'label': 'Status'},
|
||||
],
|
||||
},
|
||||
{
|
||||
'default': '_all',
|
||||
'id': 'filter-status',
|
||||
'label': 'Status',
|
||||
'options': [
|
||||
{'id': '_all', 'label': 'All'},
|
||||
{'id': 'pending', 'label': 'Open'},
|
||||
{'id': 'done', 'label': 'Done'},
|
||||
{'id': '1', 'label': 'New'},
|
||||
],
|
||||
'required': True,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
|
@ -967,6 +991,10 @@ def test_statistics_forms_count_group_by(pub, formdef, anonymise):
|
|||
{'data': [6, None, None], 'label': 'Backoffice'},
|
||||
]
|
||||
|
||||
# group by channel without form filter
|
||||
new_resp = get_app(pub).get(sign_uri('/api/statistics/forms/count/?group-by=channel'))
|
||||
assert new_resp.json['data']['series'] == resp.json['data']['series']
|
||||
|
||||
# group by item field without time interval
|
||||
resp = get_app(pub).get(sign_uri(url + '&group-by=test-item&time_interval=none'))
|
||||
# Foo is first because it has a display value, baz is second because it has not, None is always last
|
||||
|
@ -1046,8 +1074,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):
|
||||
|
@ -1058,6 +1090,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):
|
||||
|
@ -1071,7 +1104,11 @@ def test_statistics_forms_count_group_by_form(pub):
|
|||
assert resp.json['data']['subfilters'][1] == {
|
||||
'id': 'group-by',
|
||||
'label': 'Group by',
|
||||
'options': [{'id': 'form', 'label': 'Form'}],
|
||||
'options': [
|
||||
{'id': 'channel', 'label': 'Channel'},
|
||||
{'id': 'form', 'label': 'Form'},
|
||||
],
|
||||
'has_subfilters': True,
|
||||
}
|
||||
|
||||
resp = get_app(pub).get(sign_uri('/api/statistics/forms/count/?time_interval=year'))
|
||||
|
@ -1089,6 +1126,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):
|
||||
|
@ -1685,6 +1734,7 @@ def test_statistics_multiple_forms_count_subfilters(pub, formdef):
|
|||
group_by_filter = [x for x in resp.json['data']['subfilters'] if x['id'] == 'group-by'][0]
|
||||
assert group_by_filter['options'] == [
|
||||
{'id': 'channel', 'label': 'Channel'},
|
||||
{'id': 'form', 'label': 'Form'},
|
||||
{'id': 'simple-status', 'label': 'Simplified status'},
|
||||
{'id': 'test-item', 'label': 'Test item'},
|
||||
{'id': 'checkbox', 'label': 'Checkbox'},
|
||||
|
@ -1708,3 +1758,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'}
|
||||
]
|
||||
|
|
|
@ -232,8 +232,8 @@ 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'])
|
||||
if slugs != ['_all']:
|
||||
formdef_slugs = [x for x in slugs if not x.startswith('category:')]
|
||||
|
@ -244,22 +244,17 @@ 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))
|
||||
self.set_group_by_parameters(group_by, formdefs, totals_kwargs, group_labels)
|
||||
subfilters += self.get_formdefs_subfilters(formdefs, group_by, time_interval)
|
||||
else:
|
||||
subfilters += [
|
||||
{'id': 'group-by', 'label': _('Group by'), 'options': [{'id': 'form', 'label': _('Form')}]}
|
||||
]
|
||||
if group_by == 'form':
|
||||
totals_kwargs['group_by'] = 'formdef_id'
|
||||
group_labels = {
|
||||
int(x.id): x.name for x in self.formdef_class.select(lightweight=True, order_by='name')
|
||||
}
|
||||
self.add_formdefs_subfilters(subfilters, formdefs, group_by, time_interval)
|
||||
|
||||
self.set_group_by_parameters(group_by, formdefs, totals_kwargs, group_labels)
|
||||
|
||||
channel = request.GET.get('channel', '_all')
|
||||
if channel in ('web', 'backoffice'):
|
||||
|
@ -366,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':
|
||||
|
@ -384,12 +379,27 @@ class FormsCountView(RestrictedView):
|
|||
}
|
||||
)
|
||||
|
||||
group_by_filter = {
|
||||
'id': 'group-by',
|
||||
'label': _('Group by'),
|
||||
'has_subfilters': True,
|
||||
'options': [
|
||||
{'id': 'channel', 'label': _('Channel')},
|
||||
],
|
||||
}
|
||||
|
||||
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, group_by)
|
||||
new_subfilters = self.get_form_subfilters(formdef.form_page)
|
||||
|
||||
if not subfilters:
|
||||
subfilters = new_subfilters
|
||||
|
@ -400,7 +410,7 @@ class FormsCountView(RestrictedView):
|
|||
|
||||
for filter_id, subfilter in subfilters.copy().items():
|
||||
if subfilter['options'] != new_subfilters[filter_id]['options']:
|
||||
if filter_id in ('filter-status', 'group-by'):
|
||||
if filter_id in ('filter-status'):
|
||||
# keep only common options
|
||||
subfilter['options'] = {
|
||||
k: v
|
||||
|
@ -421,11 +431,29 @@ class FormsCountView(RestrictedView):
|
|||
if needs_sorting:
|
||||
subfilter['options'].sort(key=lambda x: x['label'])
|
||||
|
||||
return subfilters
|
||||
group_by_filter = [x for x in common_subfilters if x['id'] == 'group-by'][0]
|
||||
group_by_filter['options'].append({'id': 'simple-status', 'label': _('Simplified status')})
|
||||
group_by_filter['options'].extend(
|
||||
[{'id': x['id'].removeprefix('filter-'), 'label': x['label']} for x in subfilters]
|
||||
)
|
||||
|
||||
def get_form_subfilters(self, form_page, group_by):
|
||||
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:
|
||||
common_subfilters.append(
|
||||
{
|
||||
'id': 'hide_none_label',
|
||||
'label': _('Ignore forms where "%s" is empty.') % group_by_field.label,
|
||||
'options': [{'id': 'true', 'label': _('Yes')}, {'id': 'false', 'label': _('No')}],
|
||||
'required': True,
|
||||
'default': 'false',
|
||||
}
|
||||
)
|
||||
|
||||
common_subfilters.extend(subfilters)
|
||||
|
||||
def get_form_subfilters(self, form_page):
|
||||
subfilters = []
|
||||
field_choices = []
|
||||
for field in form_page.get_formdef_fields(include_block_items_fields=True):
|
||||
if not getattr(field, 'include_in_statistics', False) or not field.contextual_varname:
|
||||
continue
|
||||
|
@ -466,36 +494,6 @@ class FormsCountView(RestrictedView):
|
|||
filter_description['default'] = field.default_filter_value
|
||||
|
||||
subfilters.append(filter_description)
|
||||
field_choices.append((field.contextual_varname, field.label))
|
||||
|
||||
if field_choices:
|
||||
additionnal_filters = [
|
||||
{
|
||||
'id': 'group-by',
|
||||
'label': _('Group by'),
|
||||
'options': {
|
||||
'channel': _('Channel'),
|
||||
'simple-status': _('Simplified status'),
|
||||
**{x[0]: x[1] for x in field_choices},
|
||||
},
|
||||
'has_subfilters': True,
|
||||
}
|
||||
]
|
||||
|
||||
if group_by not in (None, 'channel', 'simple-status', 'status'):
|
||||
group_by_field = self.get_group_by_field(form_page, group_by)
|
||||
if group_by_field:
|
||||
additionnal_filters.append(
|
||||
{
|
||||
'id': 'hide_none_label',
|
||||
'label': _('Ignore forms where "%s" is empty.') % group_by_field.label,
|
||||
'options': {'true': _('Yes'), 'false': _('No')},
|
||||
'required': True,
|
||||
'default': 'false',
|
||||
}
|
||||
)
|
||||
|
||||
subfilters = additionnal_filters + subfilters
|
||||
|
||||
subfilters = {x['id']: x for x in subfilters}
|
||||
return subfilters
|
||||
|
@ -536,6 +534,13 @@ class FormsCountView(RestrictedView):
|
|||
if not group_by:
|
||||
return
|
||||
|
||||
if group_by == 'form':
|
||||
totals_kwargs['group_by'] = 'formdef_id'
|
||||
group_labels.update(
|
||||
{int(x.id): x.name for x in self.formdef_class.select(lightweight=True, order_by='name')}
|
||||
)
|
||||
return
|
||||
|
||||
if group_by == 'channel':
|
||||
totals_kwargs['group_by'] = 'submission_channel_new'
|
||||
totals_kwargs['group_by_clause'] = (
|
||||
|
|
Loading…
Reference in New Issue