fix: calculate variance
This commit is contained in:
parent
488432c0e8
commit
6e6148be39
@ -242,7 +242,8 @@ scheduler_events = {
|
|||||||
"erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_mws_settings.schedule_get_order_details",
|
"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.accounts.doctype.gl_entry.gl_entry.rename_gle_sle_docs",
|
||||||
"erpnext.projects.doctype.project.project.hourly_reminder",
|
"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": [
|
"daily": [
|
||||||
"erpnext.stock.reorder_item.reorder_item",
|
"erpnext.stock.reorder_item.reorder_item",
|
||||||
|
@ -5,7 +5,7 @@ frappe.ui.form.on("Issue", {
|
|||||||
|
|
||||||
refresh: function (frm) {
|
refresh: function (frm) {
|
||||||
|
|
||||||
if (frm.doc.status !== "Closed") {
|
if (frm.doc.status !== "Closed" && frm.doc.agreement_fulfilled === "Ongoing") {
|
||||||
if (frm.doc.service_level_agreement) {
|
if (frm.doc.service_level_agreement) {
|
||||||
set_time_to_resolve_and_response(frm);
|
set_time_to_resolve_and_response(frm);
|
||||||
}
|
}
|
||||||
@ -25,14 +25,14 @@ frappe.ui.form.on("Issue", {
|
|||||||
if (frm.doc.service_level_agreement) {
|
if (frm.doc.service_level_agreement) {
|
||||||
frm.dashboard.clear_headline();
|
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": "green", "msg": "Service Level Agreement has been fulfilled"} :
|
||||||
{"indicator": "red", "msg": "Service Level Agreement Failed"};
|
{"indicator": "red", "msg": "Service Level Agreement Failed"};
|
||||||
|
|
||||||
frm.dashboard.set_headline_alert(
|
frm.dashboard.set_headline_alert(
|
||||||
'<div class="row">' +
|
'<div class="row">' +
|
||||||
'<div class="col-xs-12">' +
|
'<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>' +
|
||||||
'</div>'
|
'</div>'
|
||||||
);
|
);
|
||||||
@ -112,8 +112,8 @@ frappe.ui.form.on("Issue", {
|
|||||||
function set_time_to_resolve_and_response(frm) {
|
function set_time_to_resolve_and_response(frm) {
|
||||||
frm.dashboard.clear_headline();
|
frm.dashboard.clear_headline();
|
||||||
|
|
||||||
var time_to_respond = get_time_left(frm.doc.response_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_status);
|
var time_to_resolve = get_time_left(frm.doc.resolution_by, frm.doc.agreement_fulfilled);
|
||||||
|
|
||||||
frm.dashboard.set_headline_alert(
|
frm.dashboard.set_headline_alert(
|
||||||
'<div class="row">' +
|
'<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 = moment(timestamp).diff(moment());
|
||||||
const diff_display = diff >= 44500 ? moment.duration(diff).humanize() : moment(0, 'seconds').format('HH:mm');
|
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};
|
return {"diff_display": diff_display, "indicator": indicator};
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,11 @@
|
|||||||
"service_level_section",
|
"service_level_section",
|
||||||
"service_level_agreement",
|
"service_level_agreement",
|
||||||
"response_by",
|
"response_by",
|
||||||
|
"response_by_variance",
|
||||||
"cb",
|
"cb",
|
||||||
"agreement_status",
|
"agreement_fulfilled",
|
||||||
"resolution_by",
|
"resolution_by",
|
||||||
|
"resolution_by_variance",
|
||||||
"response",
|
"response",
|
||||||
"mins_to_first_response",
|
"mins_to_first_response",
|
||||||
"first_responded_on",
|
"first_responded_on",
|
||||||
@ -166,14 +168,6 @@
|
|||||||
"options": "fa fa-pushpin",
|
"options": "fa fa-pushpin",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"default": "Ongoing",
|
|
||||||
"fieldname": "agreement_status",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"label": "Agreement Status",
|
|
||||||
"options": "Ongoing\nFulfilled\nFailed",
|
|
||||||
"read_only": 1
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "resolution_by",
|
"fieldname": "resolution_by",
|
||||||
"fieldtype": "Datetime",
|
"fieldtype": "Datetime",
|
||||||
@ -317,11 +311,33 @@
|
|||||||
"fieldname": "via_customer_portal",
|
"fieldname": "via_customer_portal",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Via Customer Portal"
|
"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",
|
"icon": "fa fa-ticket",
|
||||||
"idx": 7,
|
"idx": 7,
|
||||||
"modified": "2019-05-03 14:36:19.117560",
|
"modified": "2019-05-10 22:31:09.391044",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Support",
|
"module": "Support",
|
||||||
"name": "Issue",
|
"name": "Issue",
|
||||||
|
@ -68,22 +68,27 @@ class Issue(Document):
|
|||||||
status = frappe.db.get_value("Issue", self.name, "status")
|
status = frappe.db.get_value("Issue", self.name, "status")
|
||||||
if self.status!="Open" and status =="Open" and not self.first_responded_on:
|
if self.status!="Open" and status =="Open" and not self.first_responded_on:
|
||||||
self.first_responded_on = now()
|
self.first_responded_on = now()
|
||||||
|
|
||||||
if self.status=="Closed" and status !="Closed":
|
if self.status=="Closed" and status !="Closed":
|
||||||
self.resolution_date = now()
|
self.resolution_date = now()
|
||||||
self.update_agreement_status()
|
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 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
|
# if no date, it should be set as None and not a blank string "", as per mysql strict config
|
||||||
self.resolution_date = None
|
self.resolution_date = None
|
||||||
|
|
||||||
def update_agreement_status(self):
|
def update_agreement_status(self):
|
||||||
current_time = frappe.flags.current_time or now_datetime()
|
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)
|
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)
|
resolution_time_diff = round(time_diff_in_hours(self.resolution_by, current_time), 2)
|
||||||
|
|
||||||
if response_time_diff < 0 or resolution_time_diff < 0:
|
if response_time_diff < 0 or resolution_time_diff < 0:
|
||||||
self.agreement_status = "Failed"
|
self.agreement_fulfilled = "Failed"
|
||||||
else:
|
else:
|
||||||
self.agreement_status = "Fulfilled"
|
self.agreement_fulfilled = "Fulfilled"
|
||||||
|
|
||||||
def create_communication(self):
|
def create_communication(self):
|
||||||
communication = frappe.new_doc("Communication")
|
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.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.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()
|
@frappe.whitelist()
|
||||||
def change_sla_priority(self, priority):
|
def change_sla_priority(self, priority):
|
||||||
self.set_response_and_resolution_time(priority=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
|
return current_date_time
|
||||||
|
|
||||||
def set_service_level_agreement_status():
|
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:
|
for issue in issues:
|
||||||
doc = frappe.get_doc("Issue", issue.name)
|
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)
|
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)
|
resolution_time_diff = round(time_diff_in_hours(doc.resolution_by, now_datetime()), 2)
|
||||||
if response_time_diff < 0 or resolution_time_diff < 0:
|
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:
|
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):
|
def get_list_context(context=None):
|
||||||
return {
|
return {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user