api: add support for statistics on cards (#62029)
This commit is contained in:
parent
74673b9e25
commit
bde49d22b7
|
@ -5,6 +5,7 @@ import pytest
|
|||
|
||||
from wcs import fields
|
||||
from wcs.blocks import BlockDef
|
||||
from wcs.carddef import CardDef
|
||||
from wcs.categories import Category
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.qommon.http_request import HTTPRequest
|
||||
|
@ -129,7 +130,7 @@ def test_statistics_index_forms(pub):
|
|||
resp = get_app(pub).get(sign_uri('/api/statistics/'))
|
||||
form_filter = [x for x in resp.json['data'][0]['filters'] if x['id'] == 'form'][0]
|
||||
assert form_filter['options'] == [
|
||||
{'id': '_all', 'label': 'All'},
|
||||
{'id': '_all', 'label': 'All Forms'},
|
||||
{'id': 'test-1', 'label': 'test 1'},
|
||||
{'id': 'test-2', 'label': 'test 2'},
|
||||
]
|
||||
|
@ -569,3 +570,25 @@ def test_statistics_forms_count_group_by(pub, formdef, anonymise):
|
|||
# invalid field
|
||||
resp = get_app(pub).get(sign_uri(url + '&group-by=xxx'))
|
||||
assert resp.json['data']['series'] == [{'data': [16, 0, 4], 'label': 'Forms Count'}]
|
||||
|
||||
|
||||
def test_statistics_cards_count(pub):
|
||||
carddef = CardDef()
|
||||
carddef.name = 'test 1'
|
||||
carddef.fields = []
|
||||
carddef.store()
|
||||
carddef.data_class().wipe()
|
||||
|
||||
for _i in range(20):
|
||||
carddata = carddef.data_class()()
|
||||
carddata.just_created()
|
||||
carddata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
|
||||
carddata.store()
|
||||
|
||||
# apply (required) card filter
|
||||
resp = get_app(pub).get(sign_uri('/api/statistics/cards/count/?form=%s' % carddef.url_name))
|
||||
assert resp.json['data']['series'] == [{'data': [20], 'label': 'Cards Count'}]
|
||||
assert resp.json['data']['x_labels'] == ['2021-01']
|
||||
|
||||
resp = get_app(pub).get(sign_uri('/api/statistics/cards/count/?card=%s' % 'invalid'), status=400)
|
||||
assert resp.text == 'invalid form'
|
||||
|
|
11
wcs/sql.py
11
wcs/sql.py
|
@ -3801,13 +3801,18 @@ def get_period_query(
|
|||
clause = [NotNull('receipt_time')]
|
||||
table_name = 'wcs_all_forms'
|
||||
if criterias:
|
||||
from wcs.formdef import FormDef
|
||||
|
||||
formdef_class = FormDef
|
||||
for criteria in criterias:
|
||||
if criteria.__class__.__name__ == 'Equal' and criteria.attribute == 'formdef_klass':
|
||||
formdef_class = criteria.value
|
||||
continue
|
||||
|
||||
if criteria.__class__.__name__ == 'Equal' and criteria.attribute == 'formdef_id':
|
||||
# if there's a formdef_id specified, switch to using the
|
||||
# specific table so we have access to all fields
|
||||
from wcs.formdef import FormDef
|
||||
|
||||
table_name = get_formdef_table_name(FormDef.get(criteria.value))
|
||||
table_name = get_formdef_table_name(formdef_class.get(criteria.value))
|
||||
continue
|
||||
clause.append(criteria)
|
||||
if period_start:
|
||||
|
|
|
@ -23,7 +23,9 @@ from quixote import get_publisher
|
|||
|
||||
from wcs import sql
|
||||
from wcs.api_utils import is_url_signed
|
||||
from wcs.backoffice.data_management import CardPage
|
||||
from wcs.backoffice.management import FormPage
|
||||
from wcs.carddef import CardDef
|
||||
from wcs.categories import Category
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.qommon import _, misc
|
||||
|
@ -47,11 +49,14 @@ class IndexView(RestrictedView):
|
|||
category_options = [{'id': '_all', 'label': C_('categories|All')}] + [
|
||||
{'id': x.url_name, 'label': x.name} for x in categories
|
||||
]
|
||||
forms = FormDef.select()
|
||||
forms = FormDef.select(lightweight=True)
|
||||
forms.sort(key=lambda x: misc.simplify(x.name))
|
||||
form_options = [{'id': '_all', 'label': _('All')}] + [
|
||||
form_options = [{'id': '_all', 'label': _('All Forms')}] + [
|
||||
{'id': x.url_name, 'label': x.name} for x in forms
|
||||
]
|
||||
cards = CardDef.select(lightweight=True)
|
||||
cards.sort(key=lambda x: misc.simplify(x.name))
|
||||
card_options = [{'id': x.url_name, 'label': x.name} for x in cards]
|
||||
return JsonResponse(
|
||||
{
|
||||
'data': [
|
||||
|
@ -100,13 +105,57 @@ class IndexView(RestrictedView):
|
|||
'has_subfilters': True,
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': _('Cards Count'),
|
||||
'url': request.build_absolute_uri(reverse('api-statistics-cards-count')),
|
||||
'id': 'cards_counts',
|
||||
'filters': [
|
||||
{
|
||||
'id': 'time_interval',
|
||||
'label': _('Interval'),
|
||||
'options': [
|
||||
{
|
||||
'id': 'month',
|
||||
'label': _('Month'),
|
||||
},
|
||||
{
|
||||
'id': 'year',
|
||||
'label': _('Year'),
|
||||
},
|
||||
{
|
||||
'id': 'weekday',
|
||||
'label': _('Week day'),
|
||||
},
|
||||
{
|
||||
'id': 'hour',
|
||||
'label': _('Hour'),
|
||||
},
|
||||
],
|
||||
'required': True,
|
||||
'default': 'month',
|
||||
},
|
||||
{
|
||||
'id': 'form',
|
||||
'label': _('Card'),
|
||||
'options': card_options,
|
||||
'required': True,
|
||||
'default': '',
|
||||
'has_subfilters': True,
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class FormsCountView(RestrictedView):
|
||||
formdef_class = FormDef
|
||||
formpage_class = FormPage
|
||||
has_global_count_support = True
|
||||
label = _('Forms Count')
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
time_interval = request.GET.get('time_interval', 'month')
|
||||
totals_kwargs = {
|
||||
|
@ -115,16 +164,19 @@ class FormsCountView(RestrictedView):
|
|||
'criterias': [],
|
||||
}
|
||||
category_slug = request.GET.get('category', '_all')
|
||||
formdef_slug = request.GET.get('form', '_all')
|
||||
formdef_slug = request.GET.get('form', '_all' if self.has_global_count_support else '_nothing')
|
||||
group_by = request.GET.get('group-by')
|
||||
subfilters = []
|
||||
if formdef_slug != '_all':
|
||||
try:
|
||||
formdef = FormDef.get_by_urlname(formdef_slug, ignore_migration=True)
|
||||
formdef = self.formdef_class.get_by_urlname(formdef_slug, ignore_migration=True)
|
||||
except KeyError:
|
||||
return HttpResponseBadRequest('invalid form')
|
||||
form_page = FormPage(formdef=formdef, update_breadcrumbs=False)
|
||||
form_page = self.formpage_class(formdef=formdef, update_breadcrumbs=False)
|
||||
|
||||
# formdef_klass is a fake criteria, it will be used in time interval functions
|
||||
# to switch to appropriate class, it must appear before formdef_id.
|
||||
totals_kwargs['criterias'].append(Equal('formdef_klass', self.formdef_class))
|
||||
totals_kwargs['criterias'].append(Equal('formdef_id', formdef.id))
|
||||
totals_kwargs['criterias'].extend(self.get_filters_criterias(formdef, form_page))
|
||||
if group_by:
|
||||
|
@ -161,7 +213,7 @@ class FormsCountView(RestrictedView):
|
|||
|
||||
if 'group_by' not in totals_kwargs:
|
||||
x_labels = [x[0] for x in totals]
|
||||
series = [{'label': _('Forms Count'), 'data': [x[1] for x in totals]}]
|
||||
series = [{'label': self.label, 'data': [x[1] for x in totals]}]
|
||||
else:
|
||||
x_labels, series = self.get_grouped_data(totals, group_by_field, formdef, form_page)
|
||||
|
||||
|
@ -307,3 +359,10 @@ class FormsCountView(RestrictedView):
|
|||
]
|
||||
series.sort(key=lambda x: x['label'].lower())
|
||||
return x_labels, series
|
||||
|
||||
|
||||
class CardsCountView(FormsCountView):
|
||||
formdef_class = CardDef
|
||||
formpage_class = CardPage
|
||||
has_global_count_support = False
|
||||
label = _('Cards Count')
|
||||
|
|
|
@ -51,6 +51,11 @@ urlpatterns = [
|
|||
statistics_views.FormsCountView.as_view(),
|
||||
name='api-statistics-forms-count',
|
||||
),
|
||||
url(
|
||||
r'^api/statistics/cards/count/$',
|
||||
statistics_views.CardsCountView.as_view(),
|
||||
name='api-statistics-cards-count',
|
||||
),
|
||||
# provide django.contrib.auth view names for compatibility with
|
||||
# templates created for classic django applications.
|
||||
url(r'^login/$', compat.quixote, name='auth_login'),
|
||||
|
|
Loading…
Reference in New Issue