From db3c81d76337f9a49a88265f2da2b42594cc2712 Mon Sep 17 00:00:00 2001 From: Arvind Date: Tue, 11 Mar 2014 21:07:37 +0530 Subject: [PATCH] Readability counts. Breaking lines longer than 80. Minutes of a call should be counted after the user has answered the call not since the call has been started. This value is stored in the billsec column of cdr table. Answered calls should be counted when there is a disposition of answered, likewise for unanswered calls. Count number of calls which went unaccounted for, as in failed/busy/no answer with dcontext as default. --- query.py | 82 +++++++++++++++++++++++++++++++++++++++++++++---------------- report.py | 8 +++--- 2 files changed, 66 insertions(+), 24 deletions(-) diff --git a/query.py b/query.py index d175a81..789e212 100644 --- a/query.py +++ b/query.py @@ -21,8 +21,16 @@ class Query: self.t.lt.posted.between(date, dateRange)).count() - def totalMinutes(self, channel, date, dateRange): - query = self.t.lt.query.with_entities(func.sum(self.t.lt.duration).label('sum')).filter(self.t.lt.dcontext == "callback", self.t.lt.channel.like(channel+'%'), self.t.lt.calldate.between(date, dateRange)) + def totalMinutes(self, date, dateRange, channel=None): + query = self.t.lt.query.with_entities( + func.sum(self.t.lt.billsec).label('sum')).filter( + self.t.lt.dcontext == "callback", + self.t.lt.disposition == "ANSWERED", + self.t.lt.calldate.between(date, dateRange)) + + if channel is not None: + query = query.filter(self.t.lt.channel.like(channel+'%')) + sum = 0 for res in query: if res.sum is not None: @@ -31,53 +39,81 @@ class Query: def average(self, date, dateRange): - query = self.t.lt.query.with_entities(func.avg(self.t.lt.duration).label('average')).filter(self.t.lt.dcontext == "callback", self.t.lt.calldate.between(date, dateRange)) + query = self.t.lt.query.with_entities( + func.avg(self.t.lt.billsec).label('average')).filter( + self.t.lt.dcontext == "callback", + self.t.lt.disposition == "ANSWERED", + self.t.lt.calldate.between(date, dateRange)) + average = 0 for res in query: if res.average is not None: average = res.average/60 return round(average, 4) - def sum(self, date, dateRange): - query = self.t.lt.query.with_entities(func.sum(self.t.lt.duration).label('sum')).filter(self.t.lt.dcontext == "callback", self.t.lt.calldate.between(date, dateRange)) - sum = 0 - for res in query: - if res.sum is not None: - sum = res.sum/60 - return round(sum, 4) + # def sum(self, date, dateRange): + # query = self.t.lt.query.with_entities( + # func.sum(self.t.lt.billsec).label('sum')).filter( + # self.t.lt.dcontext == "callback", + # self.t.lt.disposition == "ANSWERED", + # self.t.lt.calldate.between(date, dateRange)) + # sum = 0 + # for res in query: + # if res.sum is not None: + # sum = res.sum/60 + # return round(sum, 4) def missedCalls(self, date, dateRange, modem=None): if modem is None: return self.t.lt.query.filter(((self.t.lt.dcontext == 'mobilink') | - (self.t.lt.dcontext == 'mobilinktata')) & - (self.t.lt.calldate.between(date, dateRange))).count() + (self.t.lt.dcontext == + 'mobilinktata')) & + (self.t.lt.calldate.between(date, + dateRange))).count() else: - return self.t.lt.query.filter(self.t.lt.dcontext == modem, self.t.lt.calldate.between(date, dateRange)).count() + return self.t.lt.query.filter(self.t.lt.dcontext == modem, + self.t.lt.calldate.between(date, + dateRange)).count() + + + def unAccountedCalls(self, date, dateRange): + return self.t.lt.query.filter(self.t.lt.dcontext == 'default', + self.t.lt.calldate.between(date, + dateRange)).count() def answeredCalls(self, date, dateRange): return self.t.lt.query.filter(self.t.lt.dcontext == 'callback', - self.t.lt.calldate.between(date, dateRange)).count() + self.t.lt.disposition == 'ANSWERED', + self.t.lt.calldate.between(date, + dateRange)).count() - def filter_calls_by_duration(self, date, dateRange, duration): - return self.t.lt.query.filter(self.t.lt.dcontext == 'callback', self.t.lt.duration < duration, self.t.lt.calldate.between(date, dateRange)).count() + def filter_calls_by_duration(self, date, dateRange, billsec): + return self.t.lt.query.filter( + self.t.lt.dcontext == 'callback', self.t.lt.billsec < billsec, + self.t.lt.calldate.between(date, dateRange)).count() def call_distribution(self, date, dateRange, dcontext): startTimeStamp = datetime.datetime.strptime(date, '%Y-%m-%d %H:%M:%S') endTimeStamp = datetime.datetime.strptime(dateRange, '%Y-%m-%d %H:%M:%S') - result = self.t.lt.query.filter(self.t.lt.dcontext == dcontext, self.t.lt.calldate.between(date, dateRange)) + result = self.t.lt.query.filter( + self.t.lt.dcontext == dcontext, self.t.lt.calldate.between(date, dateRange)) slots = {} while(startTimeStamp - endTimeStamp <= datetime.timedelta(0)): date1 = startTimeStamp date2 = startTimeStamp + datetime.timedelta(seconds=3600) startTimeStamp = date2 if slots.has_key('{0}-{1}'.format(date1.strftime('%H'), date2.strftime('%H'))): - slots['{0}-{1}'.format(date1.strftime('%H'), date2.strftime('%H'))] += result.filter(self.t.lt.calldate.between(date1, date2)).count() + slots['{0}-{1}'.format(date1.strftime('%H'), + date2.strftime('%H'))] += result.filter( + self.t.lt.calldate.between(date1, date2)).count() else: - slots['{0}-{1}'.format(date1.strftime('%H'), date2.strftime('%H'))] = result.filter(self.t.lt.calldate.between(date1, date2)).count() + slots['{0}-{1}'.format(date1.strftime('%H'), + date2.strftime('%H'))] = result.filter( + self.t.lt.calldate.between(date1, date2)).count() maxLoad = max(slots, key = lambda x: slots.get(x) ) minLoad = [] @@ -88,11 +124,15 @@ class Query: def calls_unanswered(self, date, dateRange): - return self.t.lt.query.filter(self.t.lt.dcontext=='default', self.t.lt.calldate.between(date,dateRange)).count() + return self.t.lt.query.filter(self.t.lt.disposition == 'NO ANSWER', + self.t.lt.dcontext == 'callback', + self.t.lt.calldate.between(date,dateRange)).count() def max_duration_UC(self, date, dateRange): - query = self.t.lt.query.with_entities(func.max(self.t.lt.duration).label('duration')).filter(self.t.lt.dcontext=='default', self.t.lt.calldate.between(date,dateRange)) + query = self.t.lt.query.with_entities( + func.max(self.t.lt.duration).label('duration')).filter( + self.t.lt.dcontext=='default', self.t.lt.calldate.between(date,dateRange)) duration = 0 for result in query: if result.duration is not None: diff --git a/report.py b/report.py index cd0ecf6..4eeb107 100644 --- a/report.py +++ b/report.py @@ -25,7 +25,7 @@ endDate = args.end_date + " " + args.end_time postings = query.Query('lb_postings') callDetails = query.Query('cdr') average_call_length = callDetails.average(startDate, endDate) -audio_minutes = callDetails.sum(startDate, endDate) +audio_minutes = callDetails.totalMinutes(startDate, endDate) mobilink_load = callDetails.call_distribution(startDate, endDate, 'mobilink') mobilink_tata_load = callDetails.call_distribution(startDate, endDate, 'mobilinktata') @@ -37,7 +37,7 @@ def individual_audio_minutes(): """ minutes = {} for ip in conf.ip_addr: - minutes[ip] = callDetails.totalMinutes(ip, startDate, endDate) + minutes[ip] = callDetails.totalMinutes(startDate, endDate, ip) return minutes def individual_load(): @@ -98,7 +98,9 @@ def genJSON(): callDetails.calls_unanswered(startDate, endDate), "Maximum_duration_of_unanswered_call": - callDetails.max_duration_UC(startDate, endDate) + callDetails.max_duration_UC(startDate, endDate), + + "Number of calls failed permanently": callDetails.unAccountedCalls(startDate, endDate) }) def genReport(): -- 1.7.10.4