1
|
|
|
# Copyright 2013 Mathias WOLFF |
2
|
|
|
# This file is part of pyfreebilling. |
3
|
|
|
# |
4
|
|
|
# pyfreebilling is free software: you can redistribute it and/or modify |
5
|
|
|
# it under the terms of the GNU General Public License as published by |
6
|
|
|
# the Free Software Foundation, either version 3 of the License, or |
7
|
|
|
# (at your option) any later version. |
8
|
|
|
# |
9
|
|
|
# pyfreebilling is distributed in the hope that it will be useful, |
10
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
11
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12
|
|
|
# GNU General Public License for more details. |
13
|
|
|
# |
14
|
|
|
# You should have received a copy of the GNU General Public License |
15
|
|
|
# along with pyfreebilling. If not, see <http://www.gnu.org/licenses/> |
16
|
|
|
|
17
|
|
|
from django.shortcuts import render_to_response |
18
|
|
|
from django.template import RequestContext, Context, loader |
19
|
|
|
from django.http import HttpResponseRedirect, HttpResponse |
20
|
|
|
from django.conf import settings |
21
|
|
|
from django.contrib.admin.views.decorators import staff_member_required |
22
|
|
|
from django.db.models import Sum, Avg, Count, Max, Min |
23
|
|
|
from django.views.generic import TemplateView |
24
|
|
|
from django.utils import timezone |
25
|
|
|
from django.contrib import messages |
26
|
|
|
from django.contrib.auth.decorators import user_passes_test |
27
|
|
|
from django.utils.translation import ugettext_lazy as _ |
28
|
|
|
|
29
|
|
|
from django_tables2 import RequestConfig |
30
|
|
|
|
31
|
|
|
from qsstats import QuerySetStats |
32
|
|
|
import time |
33
|
|
|
import datetime |
34
|
|
|
import qsstats |
35
|
|
|
import json |
36
|
|
|
import pytz |
37
|
|
|
|
38
|
|
|
from switch import esl |
39
|
|
|
|
40
|
|
|
from pyfreebilling import __version__ |
41
|
|
|
|
42
|
|
|
from pyfreebill.utils import round_value, getvar, return_query_string |
43
|
|
|
from pyfreebill.forms import CDRSearchForm |
44
|
|
|
from pyfreebill.models import DimCustomerDestination, DimProviderDestination, DimCustomerHangupcause, CDR, Company, CustomerDirectory, SipProfile |
45
|
|
|
from pyfreebill.tables import TopCustTable, TopProvTable, TopDestCustTable, TopDestProvTable |
46
|
|
|
|
47
|
|
|
|
48
|
|
|
@staff_member_required |
49
|
|
|
def global_stats_view(request, vue): |
50
|
|
|
# set start_date and end_date |
51
|
|
|
# default yesterday stats |
52
|
|
|
if vue == 'customer' or vue == 'dest_customer': |
53
|
|
|
qs = DimCustomerDestination.objects.all() |
54
|
|
|
if vue == 'provider' or vue == 'dest_provider': |
55
|
|
|
qs = DimProviderDestination.objects.all() |
56
|
|
|
|
57
|
|
|
current_tz = pytz.utc |
58
|
|
|
dt = datetime.datetime.now() |
59
|
|
|
end_date = datetime.date(dt.year, dt.month, dt.day) |
60
|
|
|
# end_date = datetime.date(2014, 8, 28) |
61
|
|
|
start_date = end_date - datetime.timedelta(days=1) |
62
|
|
|
qs_orderby = '-total_sell' |
63
|
|
|
|
64
|
|
|
# Get the q GET parameter |
65
|
|
|
# date from and to and check value |
66
|
|
|
start_d = {'y': [], 'm': [], 'd': [], 'status': True} |
67
|
|
|
end_d = {'y': [], 'm': [], 'min': [], 'status': True} |
68
|
|
|
li = ['y', 'm', 'd'] |
69
|
|
|
for i in li: |
70
|
|
|
start_d[str(i)] = request.GET.get("from_" + str(i)) |
71
|
|
|
if start_d[str(i)] and start_d[str(i)].isnumeric(): |
72
|
|
|
start_d[str(i)] = int(start_d[str(i)]) |
73
|
|
|
else: |
74
|
|
|
start_d['status'] = False |
75
|
|
|
end_d[str(i)] = request.GET.get("to_" + str(i)) |
76
|
|
|
if end_d[str(i)] and end_d[str(i)].isnumeric(): |
77
|
|
|
end_d[str(i)] = int(end_d[str(i)]) |
78
|
|
|
else: |
79
|
|
|
end_d['status'] = False |
80
|
|
|
# dest num |
81
|
|
|
dest_num = request.GET.get("dest_num") |
82
|
|
|
company = request.GET.get("company") |
83
|
|
|
if start_d['status']: |
84
|
|
|
start_date = datetime.datetime( |
85
|
|
|
start_d['y'], start_d['m'], start_d['d'], 00, 00) |
86
|
|
|
if end_d['status']: |
87
|
|
|
end_date = datetime.datetime( |
88
|
|
|
end_d['y'], end_d['m'], end_d['d'], 00, 00) |
89
|
|
|
if start_date and end_date: |
90
|
|
|
qs = qs.filter(date__date__range=(start_date, end_date)) |
91
|
|
|
|
92
|
|
|
if dest_num: |
93
|
|
|
qs = qs.filter(destination__startswith=dest_num) |
94
|
|
|
|
95
|
|
|
if company: |
96
|
|
|
if vue == 'customer' or vue == 'dest_customer': |
97
|
|
|
qs = qs.filter(customer__name__contains=company) |
98
|
|
|
if vue == 'provider' or vue == 'dest_provider': |
99
|
|
|
qs = qs.filter(provider__name__contains=company) |
100
|
|
|
|
101
|
|
|
if vue == 'customer': |
102
|
|
|
qs1 = qs.values('customer__name', 'customer__cb_currency__code') |
103
|
|
|
if vue == 'dest_customer' or vue == 'dest_provider': |
104
|
|
|
qs1 = qs.values('destination') |
105
|
|
|
if vue == 'provider': |
106
|
|
|
qs1 = qs.values('provider__name', 'provider__cb_currency__code') |
107
|
|
|
stats_table = qs1.\ |
108
|
|
|
annotate(total_sell=Sum('total_sell')).\ |
109
|
|
|
annotate(success_calls=Sum('success_calls')).\ |
110
|
|
|
annotate(total_calls=Sum('total_calls')).\ |
111
|
|
|
annotate(total_cost=Sum('total_cost')).\ |
112
|
|
|
annotate(total_duration=Sum('total_duration')).\ |
113
|
|
|
annotate(max_duration=Max('max_duration')).\ |
114
|
|
|
annotate(min_duration=Min('min_duration')).\ |
115
|
|
|
annotate(avg_duration=Min('avg_duration')).\ |
116
|
|
|
order_by('-total_sell') |
117
|
|
|
total_table = qs.\ |
118
|
|
|
aggregate(total_sell=Sum('total_sell'), |
119
|
|
|
success_calls=Sum('success_calls'),\ |
120
|
|
|
total_calls=Sum('total_calls'),\ |
121
|
|
|
total_cost=Sum('total_cost'),\ |
122
|
|
|
total_duration=Sum('total_duration'),\ |
123
|
|
|
max_duration=Max('max_duration'),\ |
124
|
|
|
min_duration=Min('min_duration'),\ |
125
|
|
|
avg_duration=Min('avg_duration')) |
126
|
|
|
|
127
|
|
|
if vue == 'customer': |
128
|
|
|
table = TopCustTable(stats_table) |
129
|
|
|
if vue == 'dest_customer': |
130
|
|
|
table = TopDestCustTable(stats_table) |
131
|
|
|
if vue == 'provider': |
132
|
|
|
table = TopProvTable(stats_table) |
133
|
|
|
if vue == 'dest_provider': |
134
|
|
|
table = TopDestProvTable(stats_table) |
135
|
|
|
RequestConfig(request, paginate={"per_page": 100}).configure(table) |
136
|
|
|
#import pdb; pdb.set_trace() |
137
|
|
|
return render_to_response('admin/customers_stats.html', locals(), |
138
|
|
|
context_instance=RequestContext(request)) |
139
|
|
|
|
140
|
|
|
|
141
|
|
|
@staff_member_required |
142
|
|
|
def customers_stats_view(request): |
143
|
|
|
return global_stats_view(request, vue='customer') |
144
|
|
|
|
145
|
|
|
|
146
|
|
|
@staff_member_required |
147
|
|
|
def destination_customers_stats_view(request): |
148
|
|
|
return global_stats_view(request, vue='dest_customer') |
149
|
|
|
|
150
|
|
|
|
151
|
|
|
@staff_member_required |
152
|
|
|
def providers_stats_view(request): |
153
|
|
|
return global_stats_view(request, vue='provider') |
154
|
|
|
|
155
|
|
|
|
156
|
|
|
@staff_member_required |
157
|
|
|
def destination_providers_stats_view(request): |
158
|
|
|
return global_stats_view(request, vue='dest_provider') |
159
|
|
|
|
160
|
|
|
|
161
|
|
View Code Duplication |
@staff_member_required |
|
|
|
|
162
|
|
|
def FsDirectoryUpdateView(request): |
163
|
|
|
messages.info(request, """Reloading FS""") |
164
|
|
|
try: |
165
|
|
|
t = loader.get_template('xml/directory.conf.xml') |
166
|
|
|
except IOError: |
167
|
|
|
messages.error(request, """customer sip config xml file update failed. |
168
|
|
|
Can not load template file !""") |
169
|
|
|
customerdirectorys = CustomerDirectory.objects.filter( |
170
|
|
|
company__customer_enabled__exact=True, enabled=True) |
171
|
|
|
accounts = Company.objects.filter(customer_enabled=True) |
172
|
|
|
c = Context({"customerdirectorys": customerdirectorys, |
173
|
|
|
"accounts": accounts}) |
174
|
|
|
try: |
175
|
|
|
f = open('/usr/local/freeswitch/conf/directory/default.xml', 'w') |
176
|
|
|
try: |
177
|
|
|
f.write(t.render(c)) |
178
|
|
|
f.close() |
179
|
|
|
try: |
180
|
|
|
fs = esl.getReloadACL() |
181
|
|
|
messages.success(request, "FS successfully reload") |
182
|
|
|
except IOError: |
183
|
|
|
messages.error(request, """customer sip config xml file update |
184
|
|
|
failed. FS ACL update failed ! Try manually - %s""" % fs) |
185
|
|
|
finally: |
186
|
|
|
# f.close() |
187
|
|
|
messages.success(request, """customer sip config xml file update |
188
|
|
|
success""") |
189
|
|
|
except IOError: |
190
|
|
|
messages.error(request, """customer sip config xml file update failed. |
191
|
|
|
Can not create file !""") |
192
|
|
|
pfb_version = __version__ |
193
|
|
|
return render_to_response('admin/admin_status.html', locals(), |
194
|
|
|
context_instance=RequestContext(request)) |
195
|
|
|
|
196
|
|
|
|
197
|
|
View Code Duplication |
def FsSofiaUpdateView(request): |
|
|
|
|
198
|
|
|
""" generate new sofia xml config file """ |
199
|
|
|
try: |
200
|
|
|
t = loader.get_template('xml/sofia.conf.xml') |
201
|
|
|
except IOError: |
202
|
|
|
messages.error(request, |
203
|
|
|
"""sofia config xml file update failed. Can not load |
204
|
|
|
template file !""") |
205
|
|
|
sipprofiles = SipProfile.objects.all() |
206
|
|
|
accounts = Company.objects.filter(supplier_enabled=True) |
207
|
|
|
c = Context({"sipprofiles": sipprofiles, "accounts": accounts}) |
208
|
|
|
try: |
209
|
|
|
f = open('/usr/local/freeswitch/conf/autoload_configs/sofia.conf.xml', |
210
|
|
|
'w') |
211
|
|
|
try: |
212
|
|
|
f.write(t.render(c)) |
213
|
|
|
f.close() |
214
|
|
|
try: |
215
|
|
|
fs = esl.getReloadGateway(request) |
216
|
|
|
messages.success(request, "FS successfully reload") |
217
|
|
|
except IOError: |
218
|
|
|
messages.error(request, """customer sip config xml file update |
219
|
|
|
failed. FS ACL update failed ! Try manually -- %s""" % fs) |
220
|
|
|
finally: |
221
|
|
|
# f.close() |
222
|
|
|
messages.success(request, "sofia config xml file update success") |
223
|
|
|
except IOError: |
224
|
|
|
messages.error(request, """sofia config xml file update failed. Can |
225
|
|
|
not create file !""") |
226
|
|
|
pfb_version = __version__ |
227
|
|
|
return render_to_response('admin/admin_status.html', locals(), |
228
|
|
|
context_instance=RequestContext(request)) |
229
|
|
|
|
230
|
|
|
|
231
|
|
|
def time_series(queryset, date_field, interval, func=None): |
232
|
|
|
qsstats = QuerySetStats(queryset, date_field, func) |
233
|
|
|
return qsstats.time_series(*interval) |
234
|
|
|
|
235
|
|
|
|
236
|
|
|
@staff_member_required |
237
|
|
|
def admin_status_view(request): |
238
|
|
|
# print status page |
239
|
|
|
#pfb_version = settings.PFB_VERSION |
240
|
|
|
pfb_version = __version__ |
241
|
|
|
return render_to_response('admin/admin_status.html', locals(), |
242
|
|
|
context_instance=RequestContext(request)) |
243
|
|
|
|
244
|
|
|
|
245
|
|
|
@staff_member_required |
246
|
|
|
def admin_listmodels_view(request): |
247
|
|
|
# print status page |
248
|
|
|
#pfb_version = settings.PFB_VERSION |
249
|
|
|
|
250
|
|
|
return render_to_response('admin/list_models.html', locals(), |
251
|
|
|
context_instance=RequestContext(request)) |
252
|
|
|
|
253
|
|
|
|
254
|
|
|
def _margin_series(sell_series, cost_series): |
255
|
|
|
""" |
256
|
|
|
Substraction between sell time series to cost time series |
257
|
|
|
""" |
258
|
|
|
sum = 0 |
259
|
|
|
l = [] |
260
|
|
|
for ((d, sell), (_, cost)) in zip(sell_series, cost_series): |
261
|
|
|
if sell and cost: |
262
|
|
|
sum += (sell - cost) |
263
|
|
|
else: |
264
|
|
|
sum += 0 |
265
|
|
|
l.append((d, sum)) |
266
|
|
|
return l |
267
|
|
|
|
268
|
|
|
|
269
|
|
|
@user_passes_test(lambda u: u.is_superuser) |
270
|
|
|
@staff_member_required |
271
|
|
|
def live_report_view(request): |
272
|
|
|
""" selecting cdr and live stats calculated from selection """ |
273
|
|
|
|
274
|
|
|
form = CDRSearchForm(request.user, request.POST or None) |
275
|
|
|
|
276
|
|
|
if request.method == 'POST': |
277
|
|
|
|
278
|
|
|
if form.is_valid(): |
279
|
|
|
query_string = '' |
280
|
|
|
query_answer = '' |
281
|
|
|
|
282
|
|
|
tzname = settings.TIME_ZONE |
283
|
|
|
offset = datetime.datetime.now( |
284
|
|
|
pytz.timezone(tzname)).strftime('%z') |
285
|
|
|
|
286
|
|
|
from_date = getvar(request, 'from_date_0') |
287
|
|
View Code Duplication |
if from_date: |
|
|
|
|
288
|
|
|
formated_date = from_date[0:4] + '-' + from_date[8:10] + '-' + from_date[ |
289
|
|
|
5:7] + '+' + from_date[11:13] + '%3A' + from_date[14:16] + '%3A00' |
290
|
|
|
if offset[0] == '+': |
291
|
|
|
formated_date = formated_date + '%2B' |
292
|
|
|
else: |
293
|
|
|
formated_date = formated_date + '%2D' |
294
|
|
|
formated_date = formated_date + \ |
295
|
|
|
offset[1:3] + '%3A' + offset[3:5] |
296
|
|
|
date_string = 'start_stamp__gte=' + str(formated_date) |
297
|
|
|
query_string = return_query_string(query_string, date_string) |
298
|
|
|
#import pdb; pdb.set_trace() |
299
|
|
|
|
300
|
|
|
to_date = getvar(request, 'to_date_0') |
301
|
|
View Code Duplication |
if to_date: |
|
|
|
|
302
|
|
|
formated_date = to_date[0:4] + '-' + to_date[8:10] + '-' + to_date[ |
303
|
|
|
5:7] + '+' + to_date[11:13] + '%3A' + to_date[14:16] + '%3A00' |
304
|
|
|
if offset[0] == '+': |
305
|
|
|
formated_date = formated_date + '%2B' |
306
|
|
|
else: |
307
|
|
|
formated_date = formated_date + '%2D' |
308
|
|
|
formated_date = formated_date + \ |
309
|
|
|
offset[1:3] + '%3A' + offset[3:5] |
310
|
|
|
date_string = 'start_stamp__lt=' + str(formated_date) |
311
|
|
|
query_string = return_query_string(query_string, date_string) |
312
|
|
|
|
313
|
|
|
customer_id = getvar(request, 'customer_id') |
314
|
|
|
if customer_id and customer_id != '0': |
315
|
|
|
customer_string = 'customer__id__exact=' + str(customer_id) |
316
|
|
|
query_string = return_query_string( |
317
|
|
|
query_string, customer_string) |
318
|
|
|
|
319
|
|
|
provider_id = getvar(request, 'provider_id') |
320
|
|
|
if provider_id and provider_id != '0': |
321
|
|
|
provider_string = 'lcr_carrier_id__id__exact=' + \ |
322
|
|
|
str(provider_id) |
323
|
|
|
query_string = return_query_string( |
324
|
|
|
query_string, provider_string) |
325
|
|
|
|
326
|
|
|
ratecard_id = getvar(request, 'ratecard_id') |
327
|
|
|
if ratecard_id and ratecard_id != '0': |
328
|
|
|
ratecard_string = 'ratecard_id__id__exact=' + str(ratecard_id) |
329
|
|
|
query_string = return_query_string( |
330
|
|
|
query_string, ratecard_string) |
331
|
|
|
|
332
|
|
|
lcr_id = getvar(request, 'lcr_id') |
333
|
|
|
if lcr_id and lcr_id != '0': |
334
|
|
|
lcr_string = 'lcr_group_id__id__exact=' + str(lcr_id) |
335
|
|
|
query_string = return_query_string(query_string, lcr_string) |
336
|
|
|
|
337
|
|
|
dest_num = getvar(request, 'dest_num') |
338
|
|
|
if dest_num: |
339
|
|
|
dstnum_string = 'destination_number__startswith=' + \ |
340
|
|
|
str(dest_num) |
341
|
|
|
query_string = return_query_string(query_string, dstnum_string) |
342
|
|
|
|
343
|
|
|
if query_string: |
344
|
|
|
query_answer = '/extranet/pyfreebill/cdr/?' + str(query_string) |
345
|
|
|
else: |
346
|
|
|
query_answer = '/extranet/pyfreebill/cdr/' |
347
|
|
|
|
348
|
|
|
return HttpResponseRedirect(query_answer) |
349
|
|
|
else: |
350
|
|
|
form = CDRSearchForm(request.user) |
351
|
|
|
|
352
|
|
|
request.session['msg'] = '' |
353
|
|
|
request.session['error_msg'] = '' |
354
|
|
|
|
355
|
|
|
return render_to_response('admin/live_report.html', locals(), |
356
|
|
|
context_instance=RequestContext(request)) |
357
|
|
|
|
358
|
|
|
|
359
|
|
|
class ChartData(object): |
360
|
|
|
|
361
|
|
|
@classmethod |
362
|
|
|
def get_stats_revenue(cls): |
363
|
|
|
data = [] |
364
|
|
|
data1 = {'key': [], 'values': [], 'color': '#2ca02c'} |
365
|
|
|
data2 = {'key': [], 'values': []} |
366
|
|
|
data3 = {'key': [], 'area': 'true', 'values': [], 'color': '#ff7f0e'} |
367
|
|
|
data4 = {'key': [], 'area': 'true', 'values': [], 'color': '#7777ff'} |
368
|
|
|
|
369
|
|
|
values_sell = [] |
370
|
|
|
values_cost = [] |
371
|
|
|
values_duration = [] |
372
|
|
|
margin = [] |
373
|
|
|
values_margin = [] |
374
|
|
|
|
375
|
|
|
qs = CDR.objects.filter(effective_duration__gt="0") |
376
|
|
|
qs_d = DimCustomerDestination.objects.all() |
377
|
|
|
# qs_h = DimCustomerHangupcause.objects.all() |
378
|
|
|
qss_sell = qsstats.QuerySetStats(qs, 'start_stamp', |
379
|
|
|
aggregate=Sum('total_sell')) |
380
|
|
|
qss_cost = qsstats.QuerySetStats(qs, 'start_stamp', |
381
|
|
|
aggregate=Sum('total_cost')) |
382
|
|
|
qss_sum_duration = qsstats.QuerySetStats(qs, 'start_stamp', |
383
|
|
|
aggregate=Sum('effective_duration')) |
384
|
|
|
today = datetime.date.today() - datetime.timedelta(days=0) |
385
|
|
|
firstday = today - datetime.timedelta(days=90) |
386
|
|
|
# stats_sell = qss_sell.time_series(seven_days_ago, today) |
387
|
|
|
# stats_cost = qss_sell.time_series(seven_days_ago, today) |
388
|
|
|
# stats_duration = qss_sum_duration.time_series(seven_days_ago, today) |
389
|
|
|
|
390
|
|
|
ts_total_calls = time_series( |
391
|
|
|
qs_d, 'date__date', [firstday, today], func=Sum('total_calls')) |
392
|
|
|
ts_success_calls = time_series( |
393
|
|
|
qs_d, 'date__date', [firstday, today], func=Sum('success_calls')) |
394
|
|
|
stats_duration = time_series( |
395
|
|
|
qs_d, 'date__date', [firstday, today], func=Sum('total_duration')) |
396
|
|
|
stats_sell = time_series( |
397
|
|
|
qs_d, 'date__date', [firstday, today], func=Sum('total_sell')) |
398
|
|
|
stats_cost = time_series( |
399
|
|
|
qs_d, 'date__date', [firstday, today], func=Sum('total_cost')) |
400
|
|
|
|
401
|
|
|
for i in range(len(stats_sell)): |
402
|
|
|
values_sell.append( |
403
|
|
|
[int(time.mktime(stats_sell[i][0].timetuple()) * 1000), |
404
|
|
|
round_value(stats_sell[i][1])]) |
405
|
|
|
|
406
|
|
|
data1['key'].append("Revenue") |
407
|
|
|
data1['values'] = values_sell |
408
|
|
|
data.append(data1) |
409
|
|
|
|
410
|
|
|
for i in range(len(stats_sell)): |
411
|
|
|
temp_data = [ |
412
|
|
|
int(time.mktime(stats_sell[i][0].timetuple()) * 1000), |
413
|
|
|
# round_value(stats_sell[i][1]) |
414
|
|
|
# round_value(stats_cost[i][1]), |
415
|
|
|
int(round_value(stats_duration[i][1])) |
416
|
|
|
] |
417
|
|
|
values_duration.append(temp_data) |
418
|
|
|
|
419
|
|
|
data2['values'] = values_duration |
420
|
|
|
# data2['bar'].append('true') |
421
|
|
|
data2['key'].append("Duration") |
422
|
|
|
# data.append(data2) |
423
|
|
|
|
424
|
|
|
for i in range(len(stats_sell)): |
425
|
|
|
values_cost.append( |
426
|
|
|
[int(time.mktime(stats_cost[i][0].timetuple()) * 1000), |
427
|
|
|
round_value(stats_cost[i][1])]) |
428
|
|
|
|
429
|
|
|
data3['key'].append("Cost") |
430
|
|
|
data3['values'] = values_cost |
431
|
|
|
data.append(data3) |
432
|
|
|
|
433
|
|
|
for i in range(len(stats_sell)): |
434
|
|
|
if stats_sell[i][1]: |
435
|
|
|
if stats_cost[i][1]: |
436
|
|
|
margin.append(stats_sell[i][1] - stats_cost[i][1]) |
437
|
|
|
else: |
438
|
|
|
margin.append(stats_sell[i][1]) |
439
|
|
|
else: |
440
|
|
|
if stats_cost[i][1]: |
441
|
|
|
margin.append(0 - stats_cost[i][1]) |
442
|
|
|
else: |
443
|
|
|
margin.append(0) |
444
|
|
|
values_margin.append( |
445
|
|
|
[int(time.mktime(stats_cost[i][0].timetuple()) * 1000), |
446
|
|
|
round_value(margin[i])]) |
447
|
|
|
|
448
|
|
|
data4['key'].append("Margin") |
449
|
|
|
data4['values'] = values_margin |
450
|
|
|
data.append(data4) |
451
|
|
|
|
452
|
|
|
#data = [{"values": [[1400281200000, 3.36], [1400367600000, 0.03], [1400454000000, 30.15], [1400540400000, 34.57], [1400626800000, 30.73], [1400713200000, 32.12], [1400799600000, 60.69], [1400886000000, 3.61], [1400972400000, 0.05], [1401058800000, 68.54], [1401145200000, 339.0], [1401231600000, 130.58], [1401318000000, 17.12], [1401404400000, 133.52], [1401490800000, 111.67], [1401577200000, 0.02], [1401663600000, 640.63], [1401750000000, 565.65], [1401836400000, 646.74], [1401922800000, 639.96], [1402009200000, 798.42], [1402095600000, 493.09], [1402182000000, 65.13], [1402268400000, 380.07], [1402354800000, 17.01], [1402441200000, 388.32], [1402527600000, 0], [1402614000000, 0], [1402700400000, 0], [1402786800000, 0], [1402873200000, 0]], "bar": ["true"], "key": ["Revenue"]}, {"values": [[1400281200000, 25562], [1400367600000, 65], [1400454000000, 232339], [1400540400000, 225068], [1400626800000, 225401], [1400713200000, 198695], [1400799600000, 257652], [1400886000000, 14543], [1400972400000, 92], [1401058800000, 295177], [1401145200000, 980922], [1401231600000, 467542], [1401318000000, 70453], [1401404400000, 369460], [1401490800000, 307402], [1401577200000, 84], [1401663600000, 1814630], [1401750000000, 1578658], [1401836400000, 1799965], [1401922800000, 2344407], [1402009200000, 2540328], [1402095600000, 1345970], [1402182000000, 21832], [1402268400000, 1010094], [1402354800000, 66511], [1402441200000, 1078292], [1402527600000, 0], [1402614000000, 0], [1402700400000, 0], [1402786800000, 0], [1402873200000, 0]], "key": ["Duration"]}] |
453
|
|
|
|
454
|
|
|
return data |
455
|
|
|
|
456
|
|
|
@classmethod |
457
|
|
|
def get_stats_volume(cls): |
458
|
|
|
data = [] |
459
|
|
|
data1 = {'key': [], 'values': []} # , 'color': '#2ca02c' |
460
|
|
|
data2 = {'key': [], 'values': [], 'bar': 'true'} |
461
|
|
|
|
462
|
|
|
values_duration = [] |
463
|
|
|
values_total_calls = [] |
464
|
|
|
values_success_calls = [] |
465
|
|
|
|
466
|
|
|
qs_d = DimCustomerDestination.objects.all() |
467
|
|
|
#qs_h = DimCustomerHangupcause.objects.all() |
468
|
|
|
|
469
|
|
|
today = datetime.date.today() - datetime.timedelta(days=0) |
470
|
|
|
firstday = today - datetime.timedelta(days=90) |
471
|
|
|
|
472
|
|
|
ts_total_calls = time_series( |
473
|
|
|
qs_d, 'date__date', [firstday, today], func=Sum('total_calls')) |
474
|
|
|
ts_success_calls = time_series( |
475
|
|
|
qs_d, 'date__date', [firstday, today], func=Sum('success_calls')) |
476
|
|
|
stats_duration = time_series( |
477
|
|
|
qs_d, 'date__date', [firstday, today], func=Sum('total_duration')) |
478
|
|
|
|
479
|
|
|
for i in range(len(stats_duration)): |
480
|
|
|
temp_data = [ |
481
|
|
|
int(time.mktime(stats_duration[i][0].timetuple()) * 1000), |
482
|
|
|
int(round_value(ts_total_calls[i][1]))] |
483
|
|
|
|
484
|
|
|
values_total_calls.append(temp_data) |
485
|
|
|
|
486
|
|
|
data1['key'].append("Total calls") |
487
|
|
|
data1['values'] = values_total_calls |
488
|
|
|
data.append(data1) |
489
|
|
|
|
490
|
|
|
for i in range(len(stats_duration)): |
491
|
|
|
temp_data = [ |
492
|
|
|
int(time.mktime(stats_duration[i][0].timetuple()) * 1000), |
493
|
|
|
int(round_value(ts_success_calls[i][1]))] |
494
|
|
|
|
495
|
|
|
values_success_calls.append(temp_data) |
496
|
|
|
|
497
|
|
|
data2['values'] = values_success_calls |
498
|
|
|
# data2['bar'].append('true') |
499
|
|
|
data2['key'].append("Success calls") |
500
|
|
|
data.append(data2) |
501
|
|
|
|
502
|
|
|
return data |
503
|
|
|
|
504
|
|
|
@classmethod |
505
|
|
|
def get_stats_minute(cls): |
506
|
|
|
data = [] |
507
|
|
|
data1 = {'key': [], 'values': []} |
508
|
|
|
data2 = {'key': [], 'bar': 'true', 'values': []} |
509
|
|
|
|
510
|
|
|
values_duration = [] |
511
|
|
|
values_acd = [] |
512
|
|
|
acd = [] |
513
|
|
|
|
514
|
|
|
qs_d = DimCustomerDestination.objects.all() |
515
|
|
|
# qs_h = DimCustomerHangupcause.objects.all() |
516
|
|
|
|
517
|
|
|
today = datetime.date.today() - datetime.timedelta(days=0) |
518
|
|
|
firstday = today - datetime.timedelta(days=90) |
519
|
|
|
|
520
|
|
|
ts_success_calls = time_series( |
521
|
|
|
qs_d, 'date__date', [firstday, today], func=Sum('success_calls')) |
522
|
|
|
stats_duration = time_series( |
523
|
|
|
qs_d, 'date__date', [firstday, today], func=Sum('total_duration')) |
524
|
|
|
|
525
|
|
|
for i in range(len(stats_duration)): |
526
|
|
|
if stats_duration[i][1]: |
527
|
|
|
acd.append(stats_duration[i][1] / ts_success_calls[i][1]) |
528
|
|
|
else: |
529
|
|
|
acd.append(0) |
530
|
|
|
temp_data = [ |
531
|
|
|
int(time.mktime(stats_duration[i][0].timetuple()) * 1000), |
532
|
|
|
acd[i]] |
533
|
|
|
|
534
|
|
|
values_acd.append(temp_data) |
535
|
|
|
|
536
|
|
|
data1['key'].append("ACD in seconds") |
537
|
|
|
data1['values'] = values_acd |
538
|
|
|
data.append(data1) |
539
|
|
|
|
540
|
|
|
for i in range(len(stats_duration)): |
541
|
|
|
temp_data = [ |
542
|
|
|
int(time.mktime(stats_duration[i][0].timetuple()) * 1000), |
543
|
|
|
int(round_value(stats_duration[i][1]) / 60)] |
544
|
|
|
|
545
|
|
|
values_duration.append(temp_data) |
546
|
|
|
|
547
|
|
|
data2['values'] = values_duration |
548
|
|
|
# data2['bar'].append('true') |
549
|
|
|
data2['key'].append("Volume in minutes") |
550
|
|
|
data.append(data2) |
551
|
|
|
|
552
|
|
|
return data |
553
|
|
|
|
554
|
|
|
|
555
|
|
|
@staff_member_required |
556
|
|
|
def chart_stats_general_json(request): |
557
|
|
|
# if not request.method == "POST": |
558
|
|
|
# raise PermissionDenied |
559
|
|
|
data = [] |
560
|
|
|
params = request.GET |
561
|
|
|
name = params.get('name', '') |
562
|
|
|
if name == 'revenue': |
563
|
|
|
data = ChartData.get_stats_revenue() |
564
|
|
|
elif name == 'volume': |
565
|
|
|
data = ChartData.get_stats_volume() |
566
|
|
|
elif name == 'minute': |
567
|
|
|
data = ChartData.get_stats_minute() |
568
|
|
|
|
569
|
|
|
return HttpResponse(json.dumps(data), content_type='application/json') |
570
|
|
|
|
571
|
|
|
|
572
|
|
|
@user_passes_test(lambda u: u.is_superuser) |
573
|
|
|
@staff_member_required |
574
|
|
|
def general_stats(request): |
575
|
|
|
company_list = Company.objects.all() |
576
|
|
|
# filter(customer_enabled=True) |
577
|
|
|
datas['companies'] = company_list |
578
|
|
|
return render_to_response('snippets/general_stats.html', |
579
|
|
|
context_instance=RequestContext(request, datas)) |
580
|
|
|
|
581
|
|
|
|
582
|
|
|
@staff_member_required |
583
|
|
|
def companies_list(): |
584
|
|
|
company_list = Company.objects.all() |
585
|
|
|
# filter(customer_enabled=True) |
586
|
|
|
return {'companies': company_list} |
587
|
|
|
|
588
|
|
|
|
589
|
|
|
@user_passes_test(lambda u: u.is_superuser) |
590
|
|
|
@staff_member_required |
591
|
|
|
def admin_report_view(request): |
592
|
|
|
# view code |
593
|
|
|
qs_d = DimCustomerDestination.objects.all() |
594
|
|
|
qs_h = DimCustomerHangupcause.objects.all() |
595
|
|
|
|
596
|
|
|
# qss_total_calls = qsstats.QuerySetStats(qs, 'date__date', aggregate=Sum('total_calls')) |
597
|
|
|
# qss_success_calls = qsstats.QuerySetStats(qs, 'date__date', aggregate=Sum('success_calls')) |
598
|
|
|
# qss_total_duration = qsstats.QuerySetStats(qs, 'date__date', aggregate=Sum('total_duration')) |
599
|
|
|
# qss_total_sell = qsstats.QuerySetStats(qs, 'date__date', aggregate=Sum('total_sell')) |
600
|
|
|
# qss_total_cost = qsstats.QuerySetStats(qs, 'date__date', aggregate=Sum('total_cost')) |
601
|
|
|
|
602
|
|
|
today = datetime.date.today() |
603
|
|
|
firstday = today - datetime.timedelta(days=7) |
604
|
|
|
|
605
|
|
|
ts_total_calls = time_series( |
606
|
|
|
qs_h, 'date__date', [firstday, today], func=Sum('total_calls')) |
607
|
|
|
ts_success_calls = time_series( |
608
|
|
|
qs_d, 'date__date', [firstday, today], func=Sum('success_calls')) |
609
|
|
|
ts_total_duration = time_series( |
610
|
|
|
qs_d, 'date__date', [firstday, today], func=Sum('total_duration')) |
611
|
|
|
ts_total_sell = time_series( |
612
|
|
|
qs_d, 'date__date', [firstday, today], func=Sum('total_sell')) |
613
|
|
|
ts_total_cost = time_series( |
614
|
|
|
qs_d, 'date__date', [firstday, today], func=Sum('total_cost')) |
615
|
|
|
ts_total_margin = _margin_series(ts_total_sell, ts_total_cost) |
616
|
|
|
|
617
|
|
|
return render_to_response('admin/admin_report.html', locals(), |
618
|
|
|
context_instance=RequestContext(request)) |
619
|
|
|
|