Projet

Général

Profil

0001-statistics-add-group-by-simplified-status-71665.patch

Valentin Deniaud, 12 décembre 2022 13:32

Télécharger (8,91 ko)

Voir les différences:

Subject: [PATCH] statistics: add group by simplified status (#71665)

 tests/api/test_statistics.py | 45 ++++++++++++++++++++++++++++++------
 wcs/statistics/views.py      | 41 ++++++++++++++++++++++++++------
 2 files changed, 72 insertions(+), 14 deletions(-)
tests/api/test_statistics.py
50 50
    workflow = Workflow(name='Workflow One')
51 51
    new_status = workflow.add_status(name='New status')
52 52
    workflow.add_status(name='End status')
53
    middle_status1 = workflow.add_status(name='Middle status 1')
54
    middle_status2 = workflow.add_status(name='Middle status 2')
53 55
    jump = new_status.add_action('jump', id='_jump')
54 56
    jump.status = '2'
55 57
    jump.timeout = 86400
58
    jump = new_status.add_action('jump', id='_jump')
59
    jump.status = '3'
60
    jump = middle_status1.add_action('jump', id='_jump')
61
    jump.status = '4'
62
    jump = middle_status2.add_action('jump', id='_jump')
63
    jump.status = '2'
56 64
    workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow)
57 65
    workflow.backoffice_fields_formdef.fields = [
58 66
        fields.BoolField(
......
432 440
        'label': 'Group by',
433 441
        'options': [
434 442
            {'id': 'channel', 'label': 'Channel'},
443
            {'id': 'simple-status', 'label': 'Simplified status'},
435 444
            {'id': 'test-item', 'label': 'Test item'},
436 445
            {'id': 'test-items', 'label': 'Test items'},
437 446
            {'id': 'checkbox', 'label': 'Checkbox'},
......
661 670
            formdata.data['1'] = False
662 671
            formdata.data['2'] = 'baz'
663 672
            formdata.data['3'] = ['baz']
664
            formdata.jump_status('2')
673
            if i == 3:
674
                formdata.jump_status('3')
675
            elif i == 9:
676
                formdata.jump_status('3')
677
                formdata.jump_status('4')
678
            else:
679
                formdata.jump_status('2')
665 680
            formdata.submission_channel = 'mail'
666 681
        else:
667 682
            formdata.receipt_time = datetime.datetime(2021, 3, 1, 2, 0).timetuple()
......
724 739
    resp = get_app(pub).get(sign_uri(url + '&group-by=status'))
725 740
    assert resp.json['data']['x_labels'] == ['2021-01', '2021-02', '2021-03']
726 741
    assert resp.json['data']['series'] == [
727
        {'data': [13, None, 4], 'label': 'New status'},
728
        {'data': [3, None, None], 'label': 'End status'},
742
        {'label': 'New status', 'data': [13, None, 4]},
743
        {'label': 'End status', 'data': [1, None, None]},
744
        {'label': 'Middle status 1', 'data': [1, None, None]},
745
        {'label': 'Middle status 2', 'data': [1, None, None]},
746
    ]
747

  
748
    # group by simplified status
749
    resp = get_app(pub).get(sign_uri(url + '&group-by=simple-status'))
750
    assert resp.json['data']['x_labels'] == ['2021-01', '2021-02', '2021-03']
751
    assert resp.json['data']['series'] == [
752
        {'label': 'New', 'data': [13, None, 4]},
753
        {'label': 'Done', 'data': [1, None, None]},
754
        {'label': 'In progress', 'data': [2, None, None]},
729 755
    ]
730 756

  
731 757
    # group by channel
......
754 780

  
755 781
    # group by status without time interval
756 782
    resp = get_app(pub).get(sign_uri(url + '&group-by=status&time_interval=none'))
757
    assert resp.json['data']['x_labels'] == ['New status', 'End status']
758
    assert resp.json['data']['series'] == [{'data': [17, 3], 'label': 'Forms Count'}]
783
    assert resp.json['data']['x_labels'] == ['New status', 'End status', 'Middle status 1', 'Middle status 2']
784
    assert resp.json['data']['series'] == [{'data': [17, 1, 1, 1], 'label': 'Forms Count'}]
785

  
786
    # group by simplfified status without time interval
787
    resp = get_app(pub).get(sign_uri(url + '&group-by=simple-status&time_interval=none'))
788
    assert resp.json['data']['x_labels'] == ['New', 'Done', 'In progress']
789
    assert resp.json['data']['series'] == [{'label': 'Forms Count', 'data': [17, 1, 2]}]
759 790

  
760 791
    # check statuses order
761 792
    formdef.workflow.possible_status = list(reversed(formdef.workflow.possible_status))
762 793
    formdef.workflow.store()
763 794
    resp = get_app(pub).get(sign_uri(url + '&group-by=status&time_interval=none'))
764
    assert resp.json['data']['x_labels'] == ['End status', 'New status']
765
    assert resp.json['data']['series'] == [{'data': [3, 17], 'label': 'Forms Count'}]
795
    assert resp.json['data']['x_labels'] == ['Middle status 2', 'Middle status 1', 'End status', 'New status']
796
    assert resp.json['data']['series'] == [{'data': [1, 1, 1, 17], 'label': 'Forms Count'}]
766 797

  
767 798
    # group by on block field is not supported
768 799
    resp = get_app(pub).get(sign_uri(url + '&group-by=blockdata_bool'))
wcs/statistics/views.py
376 376
                {
377 377
                    'id': 'group-by',
378 378
                    'label': _('Group by'),
379
                    'options': [{'id': 'channel', 'label': _('Channel')}]
379
                    'options': [
380
                        {'id': 'channel', 'label': _('Channel')},
381
                        {'id': 'simple-status', 'label': _('Simplified status')},
382
                    ]
380 383
                    + [{'id': x[0], 'label': x[1]} for x in field_choices],
381 384
                },
382 385
            )
......
391 394
            if not hasattr(fields[0], 'block_field'):  # block fields are not supported
392 395
                return fields[0]
393 396

  
394
    def get_group_labels(self, group_by_field, formdef, form_page):
397
    def get_group_labels(self, group_by_field, formdef, form_page, group_by):
395 398
        group_labels = {}
396
        if group_by_field.type == 'status':
399
        if group_by == 'status':
397 400
            group_labels = {'wf-%s' % status.id: status.name for status in formdef.workflow.possible_status}
401
        elif group_by == 'simple-status':
402
            group_labels['wf-%s' % formdef.workflow.possible_status[0].id] = _('New')
403
            for status in formdef.workflow.possible_status[1:]:
404
                if status.is_endpoint():
405
                    group_labels['wf-%s' % status.id] = _('Done')
406
                else:
407
                    group_labels['wf-%s' % status.id] = _('In progress')
398 408
        elif group_by_field.type == 'bool':
399 409
            group_labels = {True: _('Yes'), False: _('No')}
400 410
        elif group_by_field.type in ('item', 'items'):
......
418 428
            group_labels[None] = _('Web')
419 429
            group_labels[''] = _('Web')
420 430
            return
431
        elif group_by == 'simple-status':
432
            group_by_field = self.get_group_by_field(form_page, 'status')
433
        else:
434
            group_by_field = self.get_group_by_field(form_page, group_by)
421 435

  
422
        group_by_field = self.get_group_by_field(form_page, group_by)
423 436
        if not group_by_field:
424 437
            return
425 438

  
......
428 441
        else:
429 442
            totals_kwargs['group_by'] = sql.get_field_id(group_by_field)
430 443

  
431
        group_labels.update(self.get_group_labels(group_by_field, formdef, form_page))
444
        group_labels.update(self.get_group_labels(group_by_field, formdef, form_page, group_by))
432 445

  
433 446
    def get_grouped_time_data(self, totals, group_labels):
434 447
        totals_by_time = collections.OrderedDict(
......
490 503
                return len(group_label_indexes)
491 504
            return group_label_indexes[group]
492 505

  
493
        groups.sort(key=get_group_order)
494
        return {group_labels.get(group, group): totals_by_group[group] for group in groups}
506
        totals_by_label = {}
507
        for group in sorted(groups, key=get_group_order):
508
            label = group_labels.get(group, group)
509
            if label in totals_by_label:
510
                if isinstance(totals_by_label[label], list):
511
                    for i, (x, y) in enumerate(zip(totals_by_group[group], totals_by_label[label])):
512
                        totals_by_label[label][i] = (x or 0) + (y or 0) if x or y else None
513
                        totals_by_label[label][i] = ((x or 0) + (y or 0)) or None
514
                else:
515
                    totals_by_label[label] = (
516
                        (totals_by_label[label] or 0) + (totals_by_group[group] or 0)
517
                    ) or None
518
            else:
519
                totals_by_label[label] = totals_by_group[group]
520

  
521
        return totals_by_label
495 522

  
496 523

  
497 524
class CardsCountView(FormsCountView):
498
-