From 1459055ef505ce8f49caa1554470415d8c5f9928 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Mon, 10 May 2021 15:40:16 +0200 Subject: [PATCH] api: add sms count statistics (#53856) --- passerelle/api/urls.py | 4 ++- passerelle/api/views.py | 70 ++++++++++++++++++++++++++++++++++++++++- tests/test_api.py | 41 ++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 2 deletions(-) diff --git a/passerelle/api/urls.py b/passerelle/api/urls.py index 0613e97e..0afab429 100644 --- a/passerelle/api/urls.py +++ b/passerelle/api/urls.py @@ -16,8 +16,10 @@ from django.conf.urls import url -from .views import JobDetailView +from .views import JobDetailView, SMSStatisticsView, StatisticsListView urlpatterns = [ url(r'jobs/(?P[\w,-]+)/$', JobDetailView.as_view(), name='api-job'), + url(r'statistics/$', StatisticsListView.as_view(), name='api-statistics-list'), + url(r'statistics/sms/$', SMSStatisticsView.as_view(), name='api-statistics-sms'), ] diff --git a/passerelle/api/views.py b/passerelle/api/views.py index edf7e073..e7b3611b 100644 --- a/passerelle/api/views.py +++ b/passerelle/api/views.py @@ -14,11 +14,19 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import datetime + from django.core.exceptions import PermissionDenied +from django.db.models import Count +from django.db.models.functions import TruncDay from django.http import Http404, JsonResponse -from django.views.generic import DetailView +from django.urls import reverse +from django.utils.dateparse import parse_date, parse_datetime +from django.utils.translation import ugettext_lazy as _ +from django.views.generic import DetailView, View from passerelle.base.models import Job +from passerelle.sms.models import SMSLog from passerelle.utils import is_authorized @@ -45,3 +53,63 @@ class JobDetailView(DetailView): 'done_timestamp': job.done_timestamp, } return JsonResponse({'err': 0, 'data': data}) + + +class StatisticsListView(View): + def get(self, request, *args, **kwargs): + return JsonResponse( + { + 'data': [ + { + 'name': _('SMS Count'), + 'url': request.build_absolute_uri(reverse('api-statistics-sms')), + 'id': 'sms_count', + 'filters': [ + { + 'id': 'time_interval', + 'label': _('Interval'), + 'options': [{'id': 'day', 'label': _('Day')}], + 'required': True, + 'default': 'day', + }, + ], + } + ] + } + ) + + +class SMSStatisticsView(View): + def get(self, request, *args, **kwargs): + if 'time_interval' in request.GET and request.GET['time_interval'] != 'day': + return JsonResponse({'err': 1, 'err_desc': 'unsupported time interval'}) + + logs = SMSLog.objects + if 'start' in request.GET: + start = datetime.datetime.strptime(request.GET['start'], '%Y-%m-%d') + logs = logs.filter(timestamp__gte=start) + if 'end' in request.GET: + end = datetime.datetime.strptime(request.GET['end'], '%Y-%m-%d') + logs = logs.filter(timestamp__lte=end) + + logs = logs.annotate(day=TruncDay('timestamp')) + logs = logs.values('day').annotate(total=Count('id')).order_by('day') + + x_labels, data = [], [] + for log in logs: + x_labels.append(log['day'].strftime('%Y-%m-%d')) + data.append(log['total']) + + return JsonResponse( + { + 'data': { + 'x_labels': x_labels, + 'series': [ + { + 'label': _('SMS Count'), + 'data': data, + } + ], + } + } + ) diff --git a/tests/test_api.py b/tests/test_api.py index 51bf84cb..f831c2b4 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -23,6 +23,7 @@ from test_manager import login from passerelle.apps.ovh.models import OVHSMSGateway from passerelle.base.models import AccessRight, ApiUser, Job +from passerelle.sms.models import SMSLog pytestmark = pytest.mark.django_db @@ -104,3 +105,43 @@ def test_api_jobs(mocked_send_job, app, connector, simple_user, admin_user): assert resp.json['data']['status'] == 'failed' assert resp.json['data']['status_details'] == {'error_summary': 'Exception: my error message'} assert resp.json['data']['done_timestamp'] is not None + + +def test_api_statistics_list(app): + resp = app.get('/api/statistics/') + assert resp.json['data'][0]['name'] == 'SMS Count' + + +def test_api_statistics_sms(app, freezer): + resp = app.get('/api/statistics/') + url = [x for x in resp.json['data'] if x['id'] == 'sms_count'][0]['url'] + + resp = app.get(url) + assert len(resp.json['data']['series'][0]['data']) == 0 + + freezer.move_to('2021-01-01 12:00') + for _ in range(5): + SMSLog.objects.create(appname='ovh', slug='sms') + + freezer.move_to('2021-02-03 13:00') + for _ in range(3): + SMSLog.objects.create(appname='ovh', slug='sms') + + freezer.move_to('2021-02-06 13:00') + SMSLog.objects.create(appname='ovh', slug='sms') + + resp = app.get(url + '?time_interval=day') + assert resp.json['data'] == { + 'x_labels': ['2021-01-01', '2021-02-03', '2021-02-06'], + 'series': [{'label': 'SMS Count', 'data': [5, 3, 1]}], + } + + resp = app.get(url + '?start=2021-02-04&end=2021-02-07') + assert resp.json['data'] == { + 'x_labels': ['2021-02-06'], + 'series': [{'label': 'SMS Count', 'data': [1]}], + } + + # invalid time_interval + resp = app.get(url + '?time_interval=month') + assert resp.json['err'] == 1 -- 2.20.1