statistics: add time between two statuses for cards (#72454) #8
|
@ -27,6 +27,7 @@ def pub():
|
|||
Category.wipe()
|
||||
FormDef.wipe()
|
||||
Workflow.wipe()
|
||||
CardDef.wipe()
|
||||
|
||||
req = HTTPRequest(None, {'SCRIPT_NAME': '/', 'SERVER_NAME': 'example.net'})
|
||||
pub.set_app_dir(req)
|
||||
|
@ -272,6 +273,19 @@ def test_statistics_index_resolution_time(pub):
|
|||
assert form_filter['options'] == [{'id': 'test-1', 'label': 'test 1'}]
|
||||
|
||||
|
||||
def test_statistics_index_resolution_time_cards(pub):
|
||||
carddef = CardDef()
|
||||
carddef.name = 'test 1'
|
||||
carddef.fields = []
|
||||
carddef.store()
|
||||
carddef.data_class().wipe()
|
||||
|
||||
resp = get_app(pub).get(sign_uri('/api/statistics/'))
|
||||
resolution_time_stat = [x for x in resp.json['data'] if x['id'] == 'resolution_time_cards'][0]
|
||||
card_filter = [x for x in resolution_time_stat['filters'] if x['id'] == 'form'][0]
|
||||
assert card_filter['options'] == [{'id': 'test-1', 'label': 'test 1'}]
|
||||
|
||||
|
||||
def test_statistics_forms_count(pub):
|
||||
category_a = Category(name='Category A')
|
||||
category_a.store()
|
||||
|
@ -1089,3 +1103,33 @@ def test_statistics_resolution_time_start_end_filter(pub, freezer):
|
|||
'4 day(s) and 0 hour(s)', # mean
|
||||
'4 day(s) and 0 hour(s)', # median
|
||||
]
|
||||
|
||||
|
||||
def test_statistics_resolution_time_cards(pub, freezer):
|
||||
workflow = Workflow(name='Workflow One')
|
||||
new_status = workflow.add_status(name='New status')
|
||||
workflow.add_status(name='End status')
|
||||
jump = new_status.add_action('jump', id='_jump')
|
||||
jump.status = '2'
|
||||
workflow.store()
|
||||
|
||||
carddef = CardDef()
|
||||
carddef.name = 'test'
|
||||
carddef.workflow_id = workflow.id
|
||||
carddef.store()
|
||||
|
||||
for i in range(1, 10):
|
||||
carddata = carddef.data_class()()
|
||||
freezer.move_to(datetime.date(2021, 1, i))
|
||||
carddata.just_created()
|
||||
freezer.move_to(datetime.date(2021, 1, i * 2))
|
||||
carddata.jump_status('2')
|
||||
carddata.store()
|
||||
|
||||
resp = get_app(pub).get(sign_uri('/api/statistics/resolution-time-cards/?form=test'))
|
||||
assert get_humanized_duration_serie(resp.json) == [
|
||||
'1 day(s) and 0 hour(s)',
|
||||
'9 day(s) and 0 hour(s)',
|
||||
'5 day(s) and 0 hour(s)',
|
||||
'5 day(s) and 0 hour(s)',
|
||||
]
|
||||
|
|
|
@ -157,7 +157,7 @@ class IndexView(RestrictedView):
|
|||
],
|
||||
},
|
||||
{
|
||||
'name': _('Time between two statuses'),
|
||||
'name': _('Time between two statuses (forms)'),
|
||||
'url': request.build_absolute_uri(reverse('api-statistics-resolution-time')),
|
||||
'id': 'resolution_time',
|
||||
'data_type': 'seconds',
|
||||
|
@ -171,6 +171,21 @@ class IndexView(RestrictedView):
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
'name': _('Time between two statuses (cards)'),
|
||||
'url': request.build_absolute_uri(reverse('api-statistics-resolution-time-cards')),
|
||||
'id': 'resolution_time_cards',
|
||||
'data_type': 'seconds',
|
||||
'filters': [
|
||||
{
|
||||
'id': 'form',
|
||||
'label': _('Card'),
|
||||
'options': self.get_form_options(CardDef, include_all_option=False),
|
||||
'required': True,
|
||||
'has_subfilters': True,
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
|
@ -546,12 +561,13 @@ class CardsCountView(FormsCountView):
|
|||
|
||||
|
||||
class ResolutionTimeView(RestrictedView):
|
||||
label = _('Time between two statuses')
|
||||
formdef_class = FormDef
|
||||
label = _('Time between two statuses (forms)')
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
formdef_slug = request.GET.get('form', '_nothing')
|
||||
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')
|
||||
|
||||
|
@ -653,3 +669,8 @@ class ResolutionTimeView(RestrictedView):
|
|||
(_('Mean'), mean),
|
||||
(_('Median'), median),
|
||||
]
|
||||
|
||||
|
||||
class CardsResolutionTimeView(ResolutionTimeView):
|
||||
label = _('Time between two statuses (cards)')
|
||||
formdef_class = CardDef
|
||||
|
|
|
@ -66,6 +66,11 @@ urlpatterns = [
|
|||
statistics_views.ResolutionTimeView.as_view(),
|
||||
name='api-statistics-resolution-time',
|
||||
),
|
||||
path(
|
||||
'api/statistics/resolution-time-cards/',
|
||||
statistics_views.CardsResolutionTimeView.as_view(),
|
||||
name='api-statistics-resolution-time-cards',
|
||||
),
|
||||
# provide django.contrib.auth view names for compatibility with
|
||||
# templates created for classic django applications.
|
||||
path('login/', compat.quixote, name='auth_login'),
|
||||
|
|
Loading…
Reference in New Issue