Projet

Général

Profil

0001-api-add-sms-count-statistics-53856.patch

Valentin Deniaud, 10 mai 2021 15:41

Télécharger (6,08 ko)

Voir les différences:

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(-)
passerelle/api/urls.py
16 16

  
17 17
from django.conf.urls import url
18 18

  
19
from .views import JobDetailView
19
from .views import JobDetailView, SMSStatisticsView, StatisticsListView
20 20

  
21 21
urlpatterns = [
22 22
    url(r'jobs/(?P<pk>[\w,-]+)/$', JobDetailView.as_view(), name='api-job'),
23
    url(r'statistics/$', StatisticsListView.as_view(), name='api-statistics-list'),
24
    url(r'statistics/sms/$', SMSStatisticsView.as_view(), name='api-statistics-sms'),
23 25
]
passerelle/api/views.py
14 14
# You should have received a copy of the GNU Affero General Public License
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17
import datetime
18

  
17 19
from django.core.exceptions import PermissionDenied
20
from django.db.models import Count
21
from django.db.models.functions import TruncDay
18 22
from django.http import Http404, JsonResponse
19
from django.views.generic import DetailView
23
from django.urls import reverse
24
from django.utils.dateparse import parse_date, parse_datetime
25
from django.utils.translation import ugettext_lazy as _
26
from django.views.generic import DetailView, View
20 27

  
21 28
from passerelle.base.models import Job
29
from passerelle.sms.models import SMSLog
22 30
from passerelle.utils import is_authorized
23 31

  
24 32

  
......
45 53
            'done_timestamp': job.done_timestamp,
46 54
        }
47 55
        return JsonResponse({'err': 0, 'data': data})
56

  
57

  
58
class StatisticsListView(View):
59
    def get(self, request, *args, **kwargs):
60
        return JsonResponse(
61
            {
62
                'data': [
63
                    {
64
                        'name': _('SMS Count'),
65
                        'url': request.build_absolute_uri(reverse('api-statistics-sms')),
66
                        'id': 'sms_count',
67
                        'filters': [
68
                            {
69
                                'id': 'time_interval',
70
                                'label': _('Interval'),
71
                                'options': [{'id': 'day', 'label': _('Day')}],
72
                                'required': True,
73
                                'default': 'day',
74
                            },
75
                        ],
76
                    }
77
                ]
78
            }
79
        )
80

  
81

  
82
class SMSStatisticsView(View):
83
    def get(self, request, *args, **kwargs):
84
        if 'time_interval' in request.GET and request.GET['time_interval'] != 'day':
85
            return JsonResponse({'err': 1, 'err_desc': 'unsupported time interval'})
86

  
87
        logs = SMSLog.objects
88
        if 'start' in request.GET:
89
            start = datetime.datetime.strptime(request.GET['start'], '%Y-%m-%d')
90
            logs = logs.filter(timestamp__gte=start)
91
        if 'end' in request.GET:
92
            end = datetime.datetime.strptime(request.GET['end'], '%Y-%m-%d')
93
            logs = logs.filter(timestamp__lte=end)
94

  
95
        logs = logs.annotate(day=TruncDay('timestamp'))
96
        logs = logs.values('day').annotate(total=Count('id')).order_by('day')
97

  
98
        x_labels, data = [], []
99
        for log in logs:
100
            x_labels.append(log['day'].strftime('%Y-%m-%d'))
101
            data.append(log['total'])
102

  
103
        return JsonResponse(
104
            {
105
                'data': {
106
                    'x_labels': x_labels,
107
                    'series': [
108
                        {
109
                            'label': _('SMS Count'),
110
                            'data': data,
111
                        }
112
                    ],
113
                }
114
            }
115
        )
tests/test_api.py
23 23

  
24 24
from passerelle.apps.ovh.models import OVHSMSGateway
25 25
from passerelle.base.models import AccessRight, ApiUser, Job
26
from passerelle.sms.models import SMSLog
26 27

  
27 28
pytestmark = pytest.mark.django_db
28 29

  
......
104 105
    assert resp.json['data']['status'] == 'failed'
105 106
    assert resp.json['data']['status_details'] == {'error_summary': 'Exception: my error message'}
106 107
    assert resp.json['data']['done_timestamp'] is not None
108

  
109

  
110
def test_api_statistics_list(app):
111
    resp = app.get('/api/statistics/')
112
    assert resp.json['data'][0]['name'] == 'SMS Count'
113

  
114

  
115
def test_api_statistics_sms(app, freezer):
116
    resp = app.get('/api/statistics/')
117
    url = [x for x in resp.json['data'] if x['id'] == 'sms_count'][0]['url']
118

  
119
    resp = app.get(url)
120
    assert len(resp.json['data']['series'][0]['data']) == 0
121

  
122
    freezer.move_to('2021-01-01 12:00')
123
    for _ in range(5):
124
        SMSLog.objects.create(appname='ovh', slug='sms')
125

  
126
    freezer.move_to('2021-02-03 13:00')
127
    for _ in range(3):
128
        SMSLog.objects.create(appname='ovh', slug='sms')
129

  
130
    freezer.move_to('2021-02-06 13:00')
131
    SMSLog.objects.create(appname='ovh', slug='sms')
132

  
133
    resp = app.get(url + '?time_interval=day')
134
    assert resp.json['data'] == {
135
        'x_labels': ['2021-01-01', '2021-02-03', '2021-02-06'],
136
        'series': [{'label': 'SMS Count', 'data': [5, 3, 1]}],
137
    }
138

  
139
    resp = app.get(url + '?start=2021-02-04&end=2021-02-07')
140
    assert resp.json['data'] == {
141
        'x_labels': ['2021-02-06'],
142
        'series': [{'label': 'SMS Count', 'data': [1]}],
143
    }
144

  
145
    # invalid time_interval
146
    resp = app.get(url + '?time_interval=month')
147
    assert resp.json['err'] == 1
107
-