Project

General

Profile

0001-statistics-merge-category-selection-into-form-option.patch

Valentin Deniaud, 11 May 2022 04:36 PM

Download (9.78 KB)

View differences:

Subject: [PATCH] statistics: merge category selection into form options
 (#62532)

 tests/api/test_statistics.py | 87 ++++++++++++++++++++++++++++++++++--
 wcs/statistics/views.py      | 49 ++++++++++++++++----
 2 files changed, 125 insertions(+), 11 deletions(-)
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
-