Completed
Push — master ( 9ed73f...7648fa )
by
unknown
01:21
created

StatisticsMonthsDetailView   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 30
Duplicated Lines 0 %
Metric Value
wmc 7
dl 0
loc 30
rs 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
A get_object() 0 5 2
B get() 0 23 5
1
# coding: utf8
2
3
"""
4
This software is licensed under the Apache 2 license, quoted below.
5
6
Copyright 2014 Crystalnix Limited
7
8
Licensed under the Apache License, Version 2.0 (the "License"); you may not
9
use this file except in compliance with the License. You may obtain a copy of
10
the License at
11
12
    http://www.apache.org/licenses/LICENSE-2.0
13
14
Unless required by applicable law or agreed to in writing, software
15
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17
License for the specific language governing permissions and limitations under
18
the License.
19
"""
20
21
import datetime
22
import calendar
23
24
from django.http import Http404
25
from django.conf import settings
26
from django.utils import timezone
27
28
from rest_framework import viewsets
29
from rest_framework import mixins
30
from rest_framework import pagination
31
from rest_framework.views import APIView
32
from rest_framework.response import Response
33
34
35
from omaha.statistics import (
36
    get_users_statistics_months,
37
    get_users_versions,
38
    get_channel_statistics,
39
    get_users_live_versions
40
)
41
from omaha.serializers import (
42
    AppSerializer,
43
    DataSerializer,
44
    PlatformSerializer,
45
    ChannelSerializer,
46
    VersionSerializer,
47
    ActionSerializer,
48
    StatisticsMonthsSerializer,
49
    MonthRangeSerializer,
50
    ServerVersionSerializer,
51
)
52
from omaha.models import (
53
    Application,
54
    Data,
55
    Platform,
56
    Channel,
57
    Version,
58
    Action,
59
    AppRequest,
60
)
61
from omaha.utils import get_month_range_from_dict
62
63
class BaseView(mixins.ListModelMixin, mixins.CreateModelMixin,
64
               mixins.DestroyModelMixin, mixins.RetrieveModelMixin,
65
               viewsets.GenericViewSet):
66
    pass
67
68
69
class StandardResultsSetPagination(pagination.PageNumberPagination):
70
    page_size = 10
71
    page_size_query_param = 'page_size'
72
    max_page_size = 100
73
74
75
class AppViewSet(BaseView):
76
    """
77
    API endpoint that allows applications to be viewed.
78
79
    ## Applications Collection
80
81
    ### List all Applications [GET]
82
83
    URL: `http://example.com/api/app/`
84
85
    Response:
86
87
        [
88
            {
89
                "id": "{8A76FC95-0086-4BCE-9517-DC09DDB5652F}",
90
                "name": "Chromium"
91
            },
92
            {
93
                "id": "{430FD4D0-B729-4F61-AA34-91526481799D}",
94
                "name": "Potato"
95
            }
96
        ]
97
98
99
    ### Create a Application [POST]
100
101
    URL: `http://example.com/api/app/`
102
103
    Headers:
104
105
        Content-Type: application/json
106
107
    Body:
108
109
        {
110
            "id": "{8A76FC95-0086-4BCE-9517-DC09DDB5652F}",
111
            "name": "Chromium",
112
        }
113
114
    Response:
115
116
        HTTP 201 CREATED
117
        Content-Type: application/json
118
119
        {
120
            "id": "{8A76FC95-0086-4BCE-9517-DC09DDB5652F}",
121
            "name": "Chromium",
122
        }
123
124
    ## Application
125
126
    ### Retrieve a Application [GET]
127
128
    URL: `http://example.com/api/app/[app_id]`
129
130
    Response:
131
132
        HTTP 201 CREATED
133
        Content-Type: application/json
134
135
        {
136
            "id": "{8A76FC95-0086-4BCE-9517-DC09DDB5652F}",
137
            "name": "Chromium",
138
        }
139
140
    ### Remove a Application [DELETE]
141
142
    URL: `http://example.com/api/app/[app_id]`
143
144
    Response:
145
146
        HTTP 204 NO CONTENT
147
        Content-Type: application/json
148
    """
149
    queryset = Application.objects.all().order_by('-id')
150
    serializer_class = AppSerializer
151
152
153
class DataViewSet(BaseView):
154
    queryset = Data.objects.all().order_by('-id')
155
    serializer_class = DataSerializer
156
157
158
class PlatformViewSet(BaseView):
159
    queryset = Platform.objects.all().order_by('-id')
160
    serializer_class = PlatformSerializer
161
162
163
class ChannelViewSet(viewsets.ModelViewSet):
164
    queryset = Channel.objects.all().order_by('-id')
165
    serializer_class = ChannelSerializer
166
167
168
class VersionViewSet(BaseView):
169
    queryset = Version.objects.all().order_by('-id')
170
    serializer_class = VersionSerializer
171
172
173
class ActionViewSet(BaseView):
174
    queryset = Action.objects.all().order_by('-id')
175
    serializer_class = ActionSerializer
176
177
178
class StatisticsMonthsListView(APIView):
179
    def get(self, request, format=None):
180
        dates = MonthRangeSerializer(data=request.GET)
181
        dates.is_valid()
182
183
        start, end = get_month_range_from_dict(dates.validated_data)
184
185
186
        diapasons = [((start.month if year == start.year else 1, end.month if year == end.year else 12), year)
187
                     for year in range(start.year, end.year+1)]
188
189
        data = []
190
        for diapason in diapasons:
191
            data += get_users_statistics_months(year=diapason[1], start=diapason[0][0], end=diapason[0][1])
192
193
        serializer = StatisticsMonthsSerializer(dict(data=dict(data)))
194
        return Response(serializer.data)
195
196
197
class StatisticsMonthsDetailView(APIView):
198
    def get_object(self, name):
199
        try:
200
            return Application.objects.get(name=name)
201
        except Application.DoesNotExist:
202
            raise Http404
203
204
    def get(self, request, app_name, format=None):
205
        app = self.get_object(app_name)
206
207
        now = timezone.now()
208
        last_week = now - datetime.timedelta(days=7)
209
        dates = MonthRangeSerializer(data=request.GET)
210
        dates.is_valid()
211
212
        start, end = get_month_range_from_dict(dates.validated_data)
213
214
        diapasons = [((start.month if year == start.year else 1, end.month if year == end.year else 12), year)
215
                     for year in range(start.year, end.year+1)]
216
217
        data = []
218
        for diapason in diapasons:
219
            data += get_users_statistics_months(app_id=app.id, year=diapason[1], start=diapason[0][0], end=diapason[0][1])
220
221
        qs = AppRequest.objects.filter(appid=app.id,
222
                                       request__created__range=[last_week, now])
223
        data.append(('install_count', qs.filter(events__eventtype=2).count()))
224
        data.append(('update_count', qs.filter(events__eventtype=3).count()))
225
        serializer = StatisticsMonthsSerializer(dict(data=dict(data)))
226
        return Response(serializer.data)
227
228
class StatisticsVersionsView(APIView):
229
    def get_object(self, name):
230
        try:
231
            return Application.objects.get(name=name)
232
        except Application.DoesNotExist:
233
            raise Http404
234
235
    def get(self, request, app_name, format=None):
236
        app = self.get_object(app_name)
237
        data = get_users_versions(app.id)
238
        serializer = StatisticsMonthsSerializer(dict(data=dict(data)))
239
        return Response(serializer.data)
240
241
242
class StatisticsVersionsLiveView(APIView):
243
    def get_object(self, name):
244
        try:
245
            return Application.objects.get(name=name)
246
        except Application.DoesNotExist:
247
            raise Http404
248
249
    def get(self, request, app_name, format=None):
250
        app = self.get_object(app_name)
251
        data = get_users_live_versions(app.id, tz=request.session.get('django_timezone', 'UTC'))
252
        serializer = StatisticsMonthsSerializer(dict(data=dict(data)))
253
        return Response(serializer.data)
254
255
256
class StatisticsChannelsView(APIView):
257
    def get_object(self, name):
258
        try:
259
            return Application.objects.get(name=name)
260
        except Application.DoesNotExist:
261
            raise Http404
262
263
    def get(self, request, app_name, format=None):
264
        app = self.get_object(app_name)
265
        data = get_channel_statistics(app.id)
266
        serializer = StatisticsMonthsSerializer(dict(data=dict(data)))
267
        return Response(serializer.data)
268
269
270
class ServerVersionView(APIView):
271
    def get(self, request, format=None):
272
        version = settings.APP_VERSION
273
        serializer = ServerVersionSerializer(dict(version=version))
274
        return Response(serializer.data)