fix: calculate variance

This commit is contained in:
Himanshu Warekar 2019-05-10 23:49:42 +05:30
parent 488432c0e8
commit 6e6148be39
4 changed files with 67 additions and 26 deletions

View File

@ -242,7 +242,8 @@ scheduler_events = {
"erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_mws_settings.schedule_get_order_details",
"erpnext.accounts.doctype.gl_entry.gl_entry.rename_gle_sle_docs",
"erpnext.projects.doctype.project.project.hourly_reminder",
"erpnext.projects.doctype.project.project.collect_project_status"
"erpnext.projects.doctype.project.project.collect_project_status",
"erpnext.support.doctype.issue.issue.set_service_level_agreement_variance"
],
"daily": [
"erpnext.stock.reorder_item.reorder_item",

View File

@ -5,7 +5,7 @@ frappe.ui.form.on("Issue", {
refresh: function (frm) {
if (frm.doc.status !== "Closed") {
if (frm.doc.status !== "Closed" && frm.doc.agreement_fulfilled === "Ongoing") {
if (frm.doc.service_level_agreement) {
set_time_to_resolve_and_response(frm);
}
@ -25,14 +25,14 @@ frappe.ui.form.on("Issue", {
if (frm.doc.service_level_agreement) {
frm.dashboard.clear_headline();
let agreement_status = (frm.doc.agreement_status == "Fulfilled") ?
let agreement_fulfilled = (frm.doc.agreement_fulfilled == "Fulfilled") ?
{"indicator": "green", "msg": "Service Level Agreement has been fulfilled"} :
{"indicator": "red", "msg": "Service Level Agreement Failed"};
frm.dashboard.set_headline_alert(
'<div class="row">' +
'<div class="col-xs-12">' +
'<span class="indicator whitespace-nowrap '+ agreement_status.indicator +'"><span class="hidden-xs">'+ agreement_status.msg +'</span></span> ' +
'<span class="indicator whitespace-nowrap '+ agreement_fulfilled.indicator +'"><span class="hidden-xs">'+ agreement_fulfilled.msg +'</span></span> ' +
'</div>' +
'</div>'
);
@ -112,8 +112,8 @@ frappe.ui.form.on("Issue", {
function set_time_to_resolve_and_response(frm) {
frm.dashboard.clear_headline();
var time_to_respond = get_time_left(frm.doc.response_by, frm.doc.agreement_status);
var time_to_resolve = get_time_left(frm.doc.resolution_by, frm.doc.agreement_status);
var time_to_respond = get_time_left(frm.doc.response_by, frm.doc.agreement_fulfilled);
var time_to_resolve = get_time_left(frm.doc.resolution_by, frm.doc.agreement_fulfilled);
frm.dashboard.set_headline_alert(
'<div class="row">' +
@ -127,9 +127,9 @@ function set_time_to_resolve_and_response(frm) {
);
}
function get_time_left(timestamp, agreement_status) {
function get_time_left(timestamp, agreement_fulfilled) {
const diff = moment(timestamp).diff(moment());
const diff_display = diff >= 44500 ? moment.duration(diff).humanize() : moment(0, 'seconds').format('HH:mm');
let indicator = (diff_display == '00:00' && agreement_status != "Fulfilled") ? "red" : "green";
let indicator = (diff_display == '00:00' && agreement_fulfilled != "Fulfilled") ? "red" : "green";
return {"diff_display": diff_display, "indicator": indicator};
}

View File

@ -21,9 +21,11 @@
"service_level_section",
"service_level_agreement",
"response_by",
"response_by_variance",
"cb",
"agreement_status",
"agreement_fulfilled",
"resolution_by",
"resolution_by_variance",
"response",
"mins_to_first_response",
"first_responded_on",
@ -166,14 +168,6 @@
"options": "fa fa-pushpin",
"read_only": 1
},
{
"default": "Ongoing",
"fieldname": "agreement_status",
"fieldtype": "Select",
"label": "Agreement Status",
"options": "Ongoing\nFulfilled\nFailed",
"read_only": 1
},
{
"fieldname": "resolution_by",
"fieldtype": "Datetime",
@ -317,11 +311,33 @@
"fieldname": "via_customer_portal",
"fieldtype": "Check",
"label": "Via Customer Portal"
},
{
"default": "Ongoing",
"fieldname": "agreement_fulfilled",
"fieldtype": "Select",
"label": "Agreement Fulfilled",
"options": "Ongoing\nFulfilled\nFailed",
"read_only": 1
},
{
"description": "in hours",
"fieldname": "response_by_variance",
"fieldtype": "Int",
"label": "Response By Variance",
"read_only": 1
},
{
"description": "in hours",
"fieldname": "resolution_by_variance",
"fieldtype": "Int",
"label": "Resolution By Variance",
"read_only": 1
}
],
"icon": "fa fa-ticket",
"idx": 7,
"modified": "2019-05-03 14:36:19.117560",
"modified": "2019-05-10 22:31:09.391044",
"modified_by": "Administrator",
"module": "Support",
"name": "Issue",

View File

@ -68,22 +68,27 @@ class Issue(Document):
status = frappe.db.get_value("Issue", self.name, "status")
if self.status!="Open" and status =="Open" and not self.first_responded_on:
self.first_responded_on = now()
if self.status=="Closed" and status !="Closed":
self.resolution_date = now()
if not frappe.db.get_value("Issue", self.name, "agreement_fulfilled") == "Ongoing":
self.set_service_level_agreement_variance(issue=self.name)
self.update_agreement_status()
if self.status=="Open" and status !="Open":
# if no date, it should be set as None and not a blank string "", as per mysql strict config
self.resolution_date = None
def update_agreement_status(self):
current_time = frappe.flags.current_time or now_datetime()
if self.service_level_agreement and self.agreement_status == "Ongoing":
if self.service_level_agreement and self.agreement_fulfilled == "Ongoing":
response_time_diff = round(time_diff_in_hours(self.response_by, current_time), 2)
resolution_time_diff = round(time_diff_in_hours(self.resolution_by, current_time), 2)
if response_time_diff < 0 or resolution_time_diff < 0:
self.agreement_status = "Failed"
self.agreement_fulfilled = "Failed"
else:
self.agreement_status = "Fulfilled"
self.agreement_fulfilled = "Fulfilled"
def create_communication(self):
communication = frappe.new_doc("Communication")
@ -151,6 +156,9 @@ class Issue(Document):
self.response_by = get_expected_time_for(parameter='response', service_level=priority, start_date_time=start_date_time)
self.resolution_by = get_expected_time_for(parameter='resolution', service_level=priority, start_date_time=start_date_time)
self.response_by_variance = round(time_diff_in_hours(self.response_by, now_datetime()))
self.resolution_by_variance = round(time_diff_in_hours(self.resolution_by, now_datetime()))
@frappe.whitelist()
def change_sla_priority(self, priority):
self.set_response_and_resolution_time(priority=priority)
@ -222,16 +230,32 @@ def get_expected_time_for(parameter, service_level, start_date_time):
return current_date_time
def set_service_level_agreement_status():
issues = frappe.get_list("Issue", filters={"status": "Open", "agreement_status": "Ongoing"})
issues = frappe.get_list("Issue", filters={"status": "Open", "agreement_fulfilled": "Ongoing"})
for issue in issues:
doc = frappe.get_doc("Issue", issue.name)
if doc.service_level_agreement and doc.agreement_status == "Ongoing":
if doc.service_level_agreement and doc.agreement_fulfilled == "Ongoing":
response_time_diff = round(time_diff_in_hours(doc.response_by, now_datetime()), 2)
resolution_time_diff = round(time_diff_in_hours(doc.resolution_by, now_datetime()), 2)
if response_time_diff < 0 or resolution_time_diff < 0:
frappe.db.set_value("Issue", doc.name, "agreement_status", "Failed")
frappe.db.set_value("Issue", doc.name, "agreement_fulfilled", "Failed")
else:
frappe.db.set_value("Issue", doc.name, "agreement_status", "Fulfilled")
frappe.db.set_value("Issue", doc.name, "agreement_fulfilled", "Fulfilled")
def set_service_level_agreement_variance(issue=None):
filters = {"status": "Open", "agreement_fulfilled": "Ongoing"}
if issue:
filters = {"status": issue}
issues = frappe.get_list("Issue", filters=filters)
for issue in issues:
doc = frappe.get_doc("Issue", issue.name)
if not doc.first_responded_on and not doc.agreement_fulfilled == "Ongoing":
variance = round(time_diff_in_hours(doc.response_by, now_datetime()))
frappe.db.set_value("Issue", doc.name, "response_by_variance", variance)
if not doc.resolution_dateand and not doc.agreement_fulfilled == "Ongoing":
variance = round(time_diff_in_hours(self.resolution_by, now_datetime()))
frappe.db.set_value("Issue", doc.name, "resolution_by_variance", variance)
def get_list_context(context=None):
return {