0001-statistics-merge-category-selection-into-form-option.patch
tests/api/test_statistics.py | ||
---|---|---|
6 | 6 |
from wcs import fields |
7 | 7 |
from wcs.blocks import BlockDef |
8 | 8 |
from wcs.carddef import CardDef |
9 |
from wcs.categories import Category |
|
9 |
from wcs.categories import CardDefCategory, Category
|
|
10 | 10 |
from wcs.formdef import FormDef |
11 | 11 |
from wcs.qommon.http_request import HTTPRequest |
12 | 12 |
from wcs.workflows import Workflow, WorkflowBackofficeFieldsFormDef |
... | ... | |
112 | 112 |
{'id': 'category-a', 'label': 'Category A'}, |
113 | 113 |
{'id': 'category-b', 'label': 'Category B'}, |
114 | 114 |
] |
115 |
assert category_filter['deprecated'] is True |
|
115 | 116 | |
116 | 117 | |
117 | 118 |
def test_statistics_index_forms(pub): |
... | ... | |
135 | 136 |
{'id': 'test-2', 'label': 'test 2'}, |
136 | 137 |
] |
137 | 138 | |
139 |
category_a = Category(name='Category A') |
|
140 |
category_a.store() |
|
141 |
category_b = Category(name='Category B') |
|
142 |
category_b.store() |
|
143 |
formdef2.category_id = category_a.id |
|
144 |
formdef2.store() |
|
145 | ||
146 |
formdef3 = FormDef() |
|
147 |
formdef3.name = 'test 3' |
|
148 |
formdef3.category_id = category_b.id |
|
149 |
formdef3.store() |
|
150 |
formdef3.data_class().wipe() |
|
151 | ||
152 |
resp = get_app(pub).get(sign_uri('/api/statistics/')) |
|
153 |
form_filter = [x for x in resp.json['data'][0]['filters'] if x['id'] == 'form'][0] |
|
154 |
assert form_filter['options'] == [ |
|
155 |
[None, [{'id': '_all', 'label': 'All Forms'}]], |
|
156 |
[ |
|
157 |
'Category A', |
|
158 |
[ |
|
159 |
{'id': 'category:category-a', 'label': 'All forms of category Category A'}, |
|
160 |
{'id': 'test-2', 'label': 'test 2'}, |
|
161 |
], |
|
162 |
], |
|
163 |
[ |
|
164 |
'Category B', |
|
165 |
[ |
|
166 |
{'id': 'category:category-b', 'label': 'All forms of category Category B'}, |
|
167 |
{'id': 'test-3', 'label': 'test 3'}, |
|
168 |
], |
|
169 |
], |
|
170 |
['Misc', [{'id': 'test-1', 'label': 'test 1'}]], |
|
171 |
] |
|
172 | ||
173 | ||
174 |
def test_statistics_index_cards(pub): |
|
175 |
carddef = CardDef() |
|
176 |
carddef.name = 'test 1' |
|
177 |
carddef.fields = [] |
|
178 |
carddef.store() |
|
179 |
carddef.data_class().wipe() |
|
180 | ||
181 |
carddef2 = CardDef() |
|
182 |
carddef2.name = 'test 2' |
|
183 |
carddef2.fields = [] |
|
184 |
carddef2.store() |
|
185 |
carddef2.data_class().wipe() |
|
186 | ||
187 |
resp = get_app(pub).get(sign_uri('/api/statistics/')) |
|
188 |
form_filter = [x for x in resp.json['data'][1]['filters'] if x['id'] == 'form'][0] |
|
189 |
assert form_filter['options'] == [ |
|
190 |
{'id': 'test-1', 'label': 'test 1'}, |
|
191 |
{'id': 'test-2', 'label': 'test 2'}, |
|
192 |
] |
|
193 | ||
194 |
category_a = CardDefCategory(name='Category A') |
|
195 |
category_a.store() |
|
196 |
category_b = CardDefCategory(name='Category B') |
|
197 |
category_b.store() |
|
198 |
carddef2.category_id = category_a.id |
|
199 |
carddef2.store() |
|
200 | ||
201 |
carddef3 = CardDef() |
|
202 |
carddef3.name = 'test 3' |
|
203 |
carddef3.category_id = category_b.id |
|
204 |
carddef3.store() |
|
205 |
carddef3.data_class().wipe() |
|
206 | ||
207 |
resp = get_app(pub).get(sign_uri('/api/statistics/')) |
|
208 |
form_filter = [x for x in resp.json['data'][1]['filters'] if x['id'] == 'form'][0] |
|
209 |
assert form_filter['options'] == [ |
|
210 |
['Category A', [{'id': 'test-2', 'label': 'test 2'}]], |
|
211 |
['Category B', [{'id': 'test-3', 'label': 'test 3'}]], |
|
212 |
['Misc', [{'id': 'test-1', 'label': 'test 1'}]], |
|
213 |
] |
|
214 | ||
138 | 215 | |
139 | 216 |
def test_statistics_forms_count(pub): |
140 | 217 |
category_a = Category(name='Category A') |
... | ... | |
222 | 299 |
# time_interval=day is not supported |
223 | 300 |
get_app(pub).get(sign_uri('/api/statistics/forms/count/?time_interval=day'), status=400) |
224 | 301 | |
225 |
# apply category filter |
|
226 |
resp = get_app(pub).get(sign_uri('/api/statistics/forms/count/?category=category-a'))
|
|
302 |
# apply category filter through form parameter
|
|
303 |
resp = get_app(pub).get(sign_uri('/api/statistics/forms/count/?form=category:category-a'))
|
|
227 | 304 |
assert resp.json == { |
228 | 305 |
'data': { |
229 | 306 |
'series': [{'data': [20], 'label': 'Forms Count'}], |
... | ... | |
233 | 310 |
'err': 0, |
234 | 311 |
} |
235 | 312 | |
313 |
# apply category filter (legacy) |
|
314 |
new_resp = get_app(pub).get(sign_uri('/api/statistics/forms/count/?category=category-a')) |
|
315 |
assert new_resp.json == resp.json |
|
316 | ||
236 | 317 |
# apply category id filter (legacy) |
237 | 318 |
new_resp = get_app(pub).get(sign_uri('/api/statistics/forms/count/?category=%s' % category_a.id)) |
238 | 319 |
assert new_resp.json == resp.json |
wcs/statistics/views.py | ||
---|---|---|
44 | 44 |
def get(self, request, *args, **kwargs): |
45 | 45 |
if not get_publisher().is_using_postgresql(): |
46 | 46 |
return JsonResponse({'data': [], 'err': 0}) |
47 | ||
47 | 48 |
categories = Category.select() |
48 | 49 |
categories.sort(key=lambda x: misc.simplify(x.name)) |
49 | 50 |
category_options = [{'id': '_all', 'label': C_('categories|All')}] + [ |
50 | 51 |
{'id': x.url_name, 'label': x.name} for x in categories |
51 | 52 |
] |
52 |
forms = FormDef.select(lightweight=True) |
|
53 |
forms.sort(key=lambda x: misc.simplify(x.name)) |
|
54 |
form_options = [{'id': '_all', 'label': _('All Forms')}] + [ |
|
55 |
{'id': x.url_name, 'label': x.name} for x in forms |
|
56 |
] |
|
53 | ||
57 | 54 |
cards = CardDef.select(lightweight=True) |
58 | 55 |
cards.sort(key=lambda x: misc.simplify(x.name)) |
59 | 56 |
card_options = [{'id': x.url_name, 'label': x.name} for x in cards] |
... | ... | |
95 | 92 |
'options': category_options, |
96 | 93 |
'required': True, |
97 | 94 |
'default': '_all', |
95 |
'deprecated': True, |
|
96 |
'deprecation_hint': _( |
|
97 |
'Category should now be selected using the Form field below.' |
|
98 |
), |
|
98 | 99 |
}, |
99 | 100 |
{ |
100 | 101 |
'id': 'form', |
101 | 102 |
'label': _('Form'), |
102 |
'options': form_options,
|
|
103 |
'options': self.get_form_options(FormDef),
|
|
103 | 104 |
'required': True, |
104 | 105 |
'default': '_all', |
105 | 106 |
'has_subfilters': True, |
... | ... | |
138 | 139 |
{ |
139 | 140 |
'id': 'form', |
140 | 141 |
'label': _('Card'), |
141 |
'options': card_options,
|
|
142 |
'options': self.get_form_options(CardDef, include_all_option=False),
|
|
142 | 143 |
'required': True, |
143 | 144 |
'default': '', |
144 | 145 |
'has_subfilters': True, |
... | ... | |
149 | 150 |
} |
150 | 151 |
) |
151 | 152 | |
153 |
@staticmethod |
|
154 |
def get_form_options(formdef_class, include_all_option=True): |
|
155 |
all_forms_option = [{'id': '_all', 'label': _('All Forms')}] if include_all_option else [] |
|
156 | ||
157 |
forms = formdef_class.select(lightweight=True) |
|
158 |
forms.sort(key=lambda x: misc.simplify(x.name)) |
|
159 |
forms_with_category = [x for x in forms if x.category] |
|
160 |
if not forms_with_category: |
|
161 |
return all_forms_option + [{'id': x.url_name, 'label': x.name} for x in forms] |
|
162 | ||
163 |
form_options = collections.defaultdict(list) |
|
164 |
for x in forms_with_category: |
|
165 |
if x.category.name not in form_options and include_all_option: |
|
166 |
form_options[x.category.name] = [ |
|
167 |
{ |
|
168 |
'id': 'category:' + x.category.url_name, |
|
169 |
'label': _('All forms of category %s') % x.category.name, |
|
170 |
} |
|
171 |
] |
|
172 |
form_options[x.category.name].append({'id': x.url_name, 'label': x.name}) |
|
173 |
form_options = sorted( |
|
174 |
((category, forms) for category, forms in form_options.items()), key=lambda x: misc.simplify(x[0]) |
|
175 |
) |
|
176 | ||
177 |
forms_without_category_options = [ |
|
178 |
{'id': x.url_name, 'label': x.name} for x in forms if not x.category |
|
179 |
] |
|
180 |
all_forms_option_group = [(None, all_forms_option)] if include_all_option else [] |
|
181 |
return all_forms_option_group + form_options + [(_('Misc'), forms_without_category_options)] |
|
182 | ||
152 | 183 | |
153 | 184 |
class FormsCountView(RestrictedView): |
154 | 185 |
formdef_class = FormDef |
... | ... | |
167 | 198 |
formdef_slug = request.GET.get('form', '_all' if self.has_global_count_support else '_nothing') |
168 | 199 |
group_by = request.GET.get('group-by') |
169 | 200 |
subfilters = [] |
170 |
if formdef_slug != '_all': |
|
201 |
if formdef_slug != '_all' and not formdef_slug.startswith('category:'):
|
|
171 | 202 |
try: |
172 | 203 |
formdef = self.formdef_class.get_by_urlname(formdef_slug, ignore_migration=True) |
173 | 204 |
except KeyError: |
... | ... | |
189 | 220 |
else: |
190 | 221 |
totals_kwargs['criterias'].append(StrictNotEqual('status', 'draft')) |
191 | 222 | |
223 |
if formdef_slug.startswith('category:'): |
|
224 |
category_slug = formdef_slug.split(':', 1)[1] |
|
192 | 225 |
if category_slug != '_all': |
193 | 226 |
try: |
194 | 227 |
category = Category.get_by_urlname(category_slug) |
195 |
- |