style: format code with black
This commit is contained in:
@@ -12,6 +12,7 @@ from frappe.utils import flt
|
||||
def execute(filters=None):
|
||||
return IssueSummary(filters).run()
|
||||
|
||||
|
||||
class IssueSummary(object):
|
||||
def __init__(self, filters=None):
|
||||
self.filters = frappe._dict(filters or {})
|
||||
@@ -27,83 +28,78 @@ class IssueSummary(object):
|
||||
def get_columns(self):
|
||||
self.columns = []
|
||||
|
||||
if self.filters.based_on == 'Customer':
|
||||
self.columns.append({
|
||||
'label': _('Customer'),
|
||||
'options': 'Customer',
|
||||
'fieldname': 'customer',
|
||||
'fieldtype': 'Link',
|
||||
'width': 200
|
||||
})
|
||||
if self.filters.based_on == "Customer":
|
||||
self.columns.append(
|
||||
{
|
||||
"label": _("Customer"),
|
||||
"options": "Customer",
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"width": 200,
|
||||
}
|
||||
)
|
||||
|
||||
elif self.filters.based_on == 'Assigned To':
|
||||
self.columns.append({
|
||||
'label': _('User'),
|
||||
'fieldname': 'user',
|
||||
'fieldtype': 'Link',
|
||||
'options': 'User',
|
||||
'width': 200
|
||||
})
|
||||
elif self.filters.based_on == "Assigned To":
|
||||
self.columns.append(
|
||||
{"label": _("User"), "fieldname": "user", "fieldtype": "Link", "options": "User", "width": 200}
|
||||
)
|
||||
|
||||
elif self.filters.based_on == 'Issue Type':
|
||||
self.columns.append({
|
||||
'label': _('Issue Type'),
|
||||
'fieldname': 'issue_type',
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Issue Type',
|
||||
'width': 200
|
||||
})
|
||||
elif self.filters.based_on == "Issue Type":
|
||||
self.columns.append(
|
||||
{
|
||||
"label": _("Issue Type"),
|
||||
"fieldname": "issue_type",
|
||||
"fieldtype": "Link",
|
||||
"options": "Issue Type",
|
||||
"width": 200,
|
||||
}
|
||||
)
|
||||
|
||||
elif self.filters.based_on == 'Issue Priority':
|
||||
self.columns.append({
|
||||
'label': _('Issue Priority'),
|
||||
'fieldname': 'priority',
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Issue Priority',
|
||||
'width': 200
|
||||
})
|
||||
elif self.filters.based_on == "Issue Priority":
|
||||
self.columns.append(
|
||||
{
|
||||
"label": _("Issue Priority"),
|
||||
"fieldname": "priority",
|
||||
"fieldtype": "Link",
|
||||
"options": "Issue Priority",
|
||||
"width": 200,
|
||||
}
|
||||
)
|
||||
|
||||
self.statuses = ['Open', 'Replied', 'On Hold', 'Resolved', 'Closed']
|
||||
self.statuses = ["Open", "Replied", "On Hold", "Resolved", "Closed"]
|
||||
for status in self.statuses:
|
||||
self.columns.append({
|
||||
'label': _(status),
|
||||
'fieldname': scrub(status),
|
||||
'fieldtype': 'Int',
|
||||
'width': 80
|
||||
})
|
||||
self.columns.append(
|
||||
{"label": _(status), "fieldname": scrub(status), "fieldtype": "Int", "width": 80}
|
||||
)
|
||||
|
||||
self.columns.append({
|
||||
'label': _('Total Issues'),
|
||||
'fieldname': 'total_issues',
|
||||
'fieldtype': 'Int',
|
||||
'width': 100
|
||||
})
|
||||
self.columns.append(
|
||||
{"label": _("Total Issues"), "fieldname": "total_issues", "fieldtype": "Int", "width": 100}
|
||||
)
|
||||
|
||||
self.sla_status_map = {
|
||||
'SLA Failed': 'failed',
|
||||
'SLA Fulfilled': 'fulfilled',
|
||||
'First Response Due': 'first_response_due',
|
||||
'Resolution Due': 'resolution_due'
|
||||
"SLA Failed": "failed",
|
||||
"SLA Fulfilled": "fulfilled",
|
||||
"First Response Due": "first_response_due",
|
||||
"Resolution Due": "resolution_due",
|
||||
}
|
||||
|
||||
for label, fieldname in self.sla_status_map.items():
|
||||
self.columns.append({
|
||||
'label': _(label),
|
||||
'fieldname': fieldname,
|
||||
'fieldtype': 'Int',
|
||||
'width': 100
|
||||
})
|
||||
self.columns.append(
|
||||
{"label": _(label), "fieldname": fieldname, "fieldtype": "Int", "width": 100}
|
||||
)
|
||||
|
||||
self.metrics = ['Avg First Response Time', 'Avg Response Time', 'Avg Hold Time',
|
||||
'Avg Resolution Time', 'Avg User Resolution Time']
|
||||
self.metrics = [
|
||||
"Avg First Response Time",
|
||||
"Avg Response Time",
|
||||
"Avg Hold Time",
|
||||
"Avg Resolution Time",
|
||||
"Avg User Resolution Time",
|
||||
]
|
||||
|
||||
for metric in self.metrics:
|
||||
self.columns.append({
|
||||
'label': _(metric),
|
||||
'fieldname': scrub(metric),
|
||||
'fieldtype': 'Duration',
|
||||
'width': 170
|
||||
})
|
||||
self.columns.append(
|
||||
{"label": _(metric), "fieldname": scrub(metric), "fieldtype": "Duration", "width": 170}
|
||||
)
|
||||
|
||||
def get_data(self):
|
||||
self.get_issues()
|
||||
@@ -112,26 +108,37 @@ class IssueSummary(object):
|
||||
def get_issues(self):
|
||||
filters = self.get_common_filters()
|
||||
self.field_map = {
|
||||
'Customer': 'customer',
|
||||
'Issue Type': 'issue_type',
|
||||
'Issue Priority': 'priority',
|
||||
'Assigned To': '_assign'
|
||||
"Customer": "customer",
|
||||
"Issue Type": "issue_type",
|
||||
"Issue Priority": "priority",
|
||||
"Assigned To": "_assign",
|
||||
}
|
||||
|
||||
self.entries = frappe.db.get_all('Issue',
|
||||
fields=[self.field_map.get(self.filters.based_on), 'name', 'opening_date', 'status', 'avg_response_time',
|
||||
'first_response_time', 'total_hold_time', 'user_resolution_time', 'resolution_time', 'agreement_status'],
|
||||
filters=filters
|
||||
self.entries = frappe.db.get_all(
|
||||
"Issue",
|
||||
fields=[
|
||||
self.field_map.get(self.filters.based_on),
|
||||
"name",
|
||||
"opening_date",
|
||||
"status",
|
||||
"avg_response_time",
|
||||
"first_response_time",
|
||||
"total_hold_time",
|
||||
"user_resolution_time",
|
||||
"resolution_time",
|
||||
"agreement_status",
|
||||
],
|
||||
filters=filters,
|
||||
)
|
||||
|
||||
def get_common_filters(self):
|
||||
filters = {}
|
||||
filters['opening_date'] = ('between', [self.filters.from_date, self.filters.to_date])
|
||||
filters["opening_date"] = ("between", [self.filters.from_date, self.filters.to_date])
|
||||
|
||||
if self.filters.get('assigned_to'):
|
||||
filters['_assign'] = ('like', '%' + self.filters.get('assigned_to') + '%')
|
||||
if self.filters.get("assigned_to"):
|
||||
filters["_assign"] = ("like", "%" + self.filters.get("assigned_to") + "%")
|
||||
|
||||
for entry in ['company', 'status', 'priority', 'customer', 'project']:
|
||||
for entry in ["company", "status", "priority", "customer", "project"]:
|
||||
if self.filters.get(entry):
|
||||
filters[entry] = self.filters.get(entry)
|
||||
|
||||
@@ -142,20 +149,20 @@ class IssueSummary(object):
|
||||
self.get_summary_data()
|
||||
|
||||
for entity, data in self.issue_summary_data.items():
|
||||
if self.filters.based_on == 'Customer':
|
||||
row = {'customer': entity}
|
||||
elif self.filters.based_on == 'Assigned To':
|
||||
row = {'user': entity}
|
||||
elif self.filters.based_on == 'Issue Type':
|
||||
row = {'issue_type': entity}
|
||||
elif self.filters.based_on == 'Issue Priority':
|
||||
row = {'priority': entity}
|
||||
if self.filters.based_on == "Customer":
|
||||
row = {"customer": entity}
|
||||
elif self.filters.based_on == "Assigned To":
|
||||
row = {"user": entity}
|
||||
elif self.filters.based_on == "Issue Type":
|
||||
row = {"issue_type": entity}
|
||||
elif self.filters.based_on == "Issue Priority":
|
||||
row = {"priority": entity}
|
||||
|
||||
for status in self.statuses:
|
||||
count = flt(data.get(status, 0.0))
|
||||
row[scrub(status)] = count
|
||||
|
||||
row['total_issues'] = data.get('total_issues', 0.0)
|
||||
row["total_issues"] = data.get("total_issues", 0.0)
|
||||
|
||||
for sla_status in self.sla_status_map.values():
|
||||
value = flt(data.get(sla_status), 0.0)
|
||||
@@ -174,36 +181,41 @@ class IssueSummary(object):
|
||||
status = d.status
|
||||
agreement_status = scrub(d.agreement_status)
|
||||
|
||||
if self.filters.based_on == 'Assigned To':
|
||||
if self.filters.based_on == "Assigned To":
|
||||
if d._assign:
|
||||
for entry in json.loads(d._assign):
|
||||
self.issue_summary_data.setdefault(entry, frappe._dict()).setdefault(status, 0.0)
|
||||
self.issue_summary_data.setdefault(entry, frappe._dict()).setdefault(agreement_status, 0.0)
|
||||
self.issue_summary_data.setdefault(entry, frappe._dict()).setdefault('total_issues', 0.0)
|
||||
self.issue_summary_data.setdefault(entry, frappe._dict()).setdefault("total_issues", 0.0)
|
||||
self.issue_summary_data[entry][status] += 1
|
||||
self.issue_summary_data[entry][agreement_status] += 1
|
||||
self.issue_summary_data[entry]['total_issues'] += 1
|
||||
self.issue_summary_data[entry]["total_issues"] += 1
|
||||
|
||||
else:
|
||||
field = self.field_map.get(self.filters.based_on)
|
||||
value = d.get(field)
|
||||
if not value:
|
||||
value = _('Not Specified')
|
||||
value = _("Not Specified")
|
||||
|
||||
self.issue_summary_data.setdefault(value, frappe._dict()).setdefault(status, 0.0)
|
||||
self.issue_summary_data.setdefault(value, frappe._dict()).setdefault(agreement_status, 0.0)
|
||||
self.issue_summary_data.setdefault(value, frappe._dict()).setdefault('total_issues', 0.0)
|
||||
self.issue_summary_data.setdefault(value, frappe._dict()).setdefault("total_issues", 0.0)
|
||||
self.issue_summary_data[value][status] += 1
|
||||
self.issue_summary_data[value][agreement_status] += 1
|
||||
self.issue_summary_data[value]['total_issues'] += 1
|
||||
self.issue_summary_data[value]["total_issues"] += 1
|
||||
|
||||
self.get_metrics_data()
|
||||
|
||||
def get_metrics_data(self):
|
||||
issues = []
|
||||
|
||||
metrics_list = ['avg_response_time', 'avg_first_response_time', 'avg_hold_time',
|
||||
'avg_resolution_time', 'avg_user_resolution_time']
|
||||
metrics_list = [
|
||||
"avg_response_time",
|
||||
"avg_first_response_time",
|
||||
"avg_hold_time",
|
||||
"avg_resolution_time",
|
||||
"avg_user_resolution_time",
|
||||
]
|
||||
|
||||
for entry in self.entries:
|
||||
issues.append(entry.name)
|
||||
@@ -211,7 +223,7 @@ class IssueSummary(object):
|
||||
field = self.field_map.get(self.filters.based_on)
|
||||
|
||||
if issues:
|
||||
if self.filters.based_on == 'Assigned To':
|
||||
if self.filters.based_on == "Assigned To":
|
||||
assignment_map = frappe._dict()
|
||||
for d in self.entries:
|
||||
if d._assign:
|
||||
@@ -219,11 +231,15 @@ class IssueSummary(object):
|
||||
for metric in metrics_list:
|
||||
self.issue_summary_data.setdefault(entry, frappe._dict()).setdefault(metric, 0.0)
|
||||
|
||||
self.issue_summary_data[entry]['avg_response_time'] += d.get('avg_response_time') or 0.0
|
||||
self.issue_summary_data[entry]['avg_first_response_time'] += d.get('first_response_time') or 0.0
|
||||
self.issue_summary_data[entry]['avg_hold_time'] += d.get('total_hold_time') or 0.0
|
||||
self.issue_summary_data[entry]['avg_resolution_time'] += d.get('resolution_time') or 0.0
|
||||
self.issue_summary_data[entry]['avg_user_resolution_time'] += d.get('user_resolution_time') or 0.0
|
||||
self.issue_summary_data[entry]["avg_response_time"] += d.get("avg_response_time") or 0.0
|
||||
self.issue_summary_data[entry]["avg_first_response_time"] += (
|
||||
d.get("first_response_time") or 0.0
|
||||
)
|
||||
self.issue_summary_data[entry]["avg_hold_time"] += d.get("total_hold_time") or 0.0
|
||||
self.issue_summary_data[entry]["avg_resolution_time"] += d.get("resolution_time") or 0.0
|
||||
self.issue_summary_data[entry]["avg_user_resolution_time"] += (
|
||||
d.get("user_resolution_time") or 0.0
|
||||
)
|
||||
|
||||
if not assignment_map.get(entry):
|
||||
assignment_map[entry] = 0
|
||||
@@ -234,7 +250,8 @@ class IssueSummary(object):
|
||||
self.issue_summary_data[entry][metric] /= flt(assignment_map.get(entry))
|
||||
|
||||
else:
|
||||
data = frappe.db.sql("""
|
||||
data = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
{0}, AVG(first_response_time) as avg_frt,
|
||||
AVG(avg_response_time) as avg_resp_time,
|
||||
@@ -245,21 +262,30 @@ class IssueSummary(object):
|
||||
WHERE
|
||||
name IN %(issues)s
|
||||
GROUP BY {0}
|
||||
""".format(field), {'issues': issues}, as_dict=1)
|
||||
""".format(
|
||||
field
|
||||
),
|
||||
{"issues": issues},
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
for entry in data:
|
||||
value = entry.get(field)
|
||||
if not value:
|
||||
value = _('Not Specified')
|
||||
value = _("Not Specified")
|
||||
|
||||
for metric in metrics_list:
|
||||
self.issue_summary_data.setdefault(value, frappe._dict()).setdefault(metric, 0.0)
|
||||
|
||||
self.issue_summary_data[value]['avg_response_time'] = entry.get('avg_resp_time') or 0.0
|
||||
self.issue_summary_data[value]['avg_first_response_time'] = entry.get('avg_frt') or 0.0
|
||||
self.issue_summary_data[value]['avg_hold_time'] = entry.get('avg_hold_time') or 0.0
|
||||
self.issue_summary_data[value]['avg_resolution_time'] = entry.get('avg_resolution_time') or 0.0
|
||||
self.issue_summary_data[value]['avg_user_resolution_time'] = entry.get('avg_user_resolution_time') or 0.0
|
||||
self.issue_summary_data[value]["avg_response_time"] = entry.get("avg_resp_time") or 0.0
|
||||
self.issue_summary_data[value]["avg_first_response_time"] = entry.get("avg_frt") or 0.0
|
||||
self.issue_summary_data[value]["avg_hold_time"] = entry.get("avg_hold_time") or 0.0
|
||||
self.issue_summary_data[value]["avg_resolution_time"] = (
|
||||
entry.get("avg_resolution_time") or 0.0
|
||||
)
|
||||
self.issue_summary_data[value]["avg_user_resolution_time"] = (
|
||||
entry.get("avg_user_resolution_time") or 0.0
|
||||
)
|
||||
|
||||
def get_chart_data(self):
|
||||
self.chart = []
|
||||
@@ -273,47 +299,30 @@ class IssueSummary(object):
|
||||
|
||||
entity = self.filters.based_on
|
||||
entity_field = self.field_map.get(entity)
|
||||
if entity == 'Assigned To':
|
||||
entity_field = 'user'
|
||||
if entity == "Assigned To":
|
||||
entity_field = "user"
|
||||
|
||||
for entry in self.data:
|
||||
labels.append(entry.get(entity_field))
|
||||
open_issues.append(entry.get('open'))
|
||||
replied_issues.append(entry.get('replied'))
|
||||
on_hold_issues.append(entry.get('on_hold'))
|
||||
resolved_issues.append(entry.get('resolved'))
|
||||
closed_issues.append(entry.get('closed'))
|
||||
open_issues.append(entry.get("open"))
|
||||
replied_issues.append(entry.get("replied"))
|
||||
on_hold_issues.append(entry.get("on_hold"))
|
||||
resolved_issues.append(entry.get("resolved"))
|
||||
closed_issues.append(entry.get("closed"))
|
||||
|
||||
self.chart = {
|
||||
'data': {
|
||||
'labels': labels[:30],
|
||||
'datasets': [
|
||||
{
|
||||
'name': 'Open',
|
||||
'values': open_issues[:30]
|
||||
},
|
||||
{
|
||||
'name': 'Replied',
|
||||
'values': replied_issues[:30]
|
||||
},
|
||||
{
|
||||
'name': 'On Hold',
|
||||
'values': on_hold_issues[:30]
|
||||
},
|
||||
{
|
||||
'name': 'Resolved',
|
||||
'values': resolved_issues[:30]
|
||||
},
|
||||
{
|
||||
'name': 'Closed',
|
||||
'values': closed_issues[:30]
|
||||
}
|
||||
]
|
||||
"data": {
|
||||
"labels": labels[:30],
|
||||
"datasets": [
|
||||
{"name": "Open", "values": open_issues[:30]},
|
||||
{"name": "Replied", "values": replied_issues[:30]},
|
||||
{"name": "On Hold", "values": on_hold_issues[:30]},
|
||||
{"name": "Resolved", "values": resolved_issues[:30]},
|
||||
{"name": "Closed", "values": closed_issues[:30]},
|
||||
],
|
||||
},
|
||||
'type': 'bar',
|
||||
'barOptions': {
|
||||
'stacked': True
|
||||
}
|
||||
"type": "bar",
|
||||
"barOptions": {"stacked": True},
|
||||
}
|
||||
|
||||
def get_report_summary(self):
|
||||
@@ -326,41 +335,41 @@ class IssueSummary(object):
|
||||
closed = 0
|
||||
|
||||
for entry in self.data:
|
||||
open_issues += entry.get('open')
|
||||
replied += entry.get('replied')
|
||||
on_hold += entry.get('on_hold')
|
||||
resolved += entry.get('resolved')
|
||||
closed += entry.get('closed')
|
||||
open_issues += entry.get("open")
|
||||
replied += entry.get("replied")
|
||||
on_hold += entry.get("on_hold")
|
||||
resolved += entry.get("resolved")
|
||||
closed += entry.get("closed")
|
||||
|
||||
self.report_summary = [
|
||||
{
|
||||
'value': open_issues,
|
||||
'indicator': 'Red',
|
||||
'label': _('Open'),
|
||||
'datatype': 'Int',
|
||||
"value": open_issues,
|
||||
"indicator": "Red",
|
||||
"label": _("Open"),
|
||||
"datatype": "Int",
|
||||
},
|
||||
{
|
||||
'value': replied,
|
||||
'indicator': 'Grey',
|
||||
'label': _('Replied'),
|
||||
'datatype': 'Int',
|
||||
"value": replied,
|
||||
"indicator": "Grey",
|
||||
"label": _("Replied"),
|
||||
"datatype": "Int",
|
||||
},
|
||||
{
|
||||
'value': on_hold,
|
||||
'indicator': 'Grey',
|
||||
'label': _('On Hold'),
|
||||
'datatype': 'Int',
|
||||
"value": on_hold,
|
||||
"indicator": "Grey",
|
||||
"label": _("On Hold"),
|
||||
"datatype": "Int",
|
||||
},
|
||||
{
|
||||
'value': resolved,
|
||||
'indicator': 'Green',
|
||||
'label': _('Resolved'),
|
||||
'datatype': 'Int',
|
||||
"value": resolved,
|
||||
"indicator": "Green",
|
||||
"label": _("Resolved"),
|
||||
"datatype": "Int",
|
||||
},
|
||||
{
|
||||
'value': closed,
|
||||
'indicator': 'Green',
|
||||
'label': _('Closed'),
|
||||
'datatype': 'Int',
|
||||
}
|
||||
"value": closed,
|
||||
"indicator": "Green",
|
||||
"label": _("Closed"),
|
||||
"datatype": "Int",
|
||||
},
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user