diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js
index bad40cc37f..66c62d1ff2 100644
--- a/erpnext/support/doctype/issue/issue.js
+++ b/erpnext/support/doctype/issue/issue.js
@@ -41,7 +41,19 @@ frappe.ui.form.on("Issue", {
if (frm.doc.status !== "Closed" && frm.doc.agreement_fulfilled === "Ongoing") {
if (frm.doc.service_level_agreement) {
- set_time_to_resolve_and_response(frm);
+ if (frm.doc.status == "Replied") {
+ frm.dashboard.clear_headline();
+ let message = {"indicator": "orange", "msg": __("Replied {0}", [moment(frm.doc.on_hold_since).fromNow()])};
+ frm.dashboard.set_headline_alert(
+ '
' +
+ '
' +
+ ''+ message.msg +' ' +
+ '
' +
+ '
'
+ );
+ } else {
+ set_time_to_resolve_and_response(frm);
+ }
}
frm.add_custom_button(__("Close"), function () {
diff --git a/erpnext/support/doctype/issue/issue.json b/erpnext/support/doctype/issue/issue.json
index 131e1cb9bf..82443a51cb 100644
--- a/erpnext/support/doctype/issue/issue.json
+++ b/erpnext/support/doctype/issue/issue.json
@@ -31,6 +31,8 @@
"resolution_by",
"resolution_by_variance",
"service_level_agreement_creation",
+ "on_hold_since",
+ "total_hold_time",
"response",
"mins_to_first_response",
"first_responded_on",
@@ -395,12 +397,28 @@
"read_only": 1,
"show_days": 1,
"show_seconds": 1
+ },
+ {
+ "fieldname": "on_hold_since",
+ "fieldtype": "Datetime",
+ "label": "On Hold Since",
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "total_hold_time",
+ "fieldtype": "Duration",
+ "label": "Total Hold Time",
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
}
],
"icon": "fa fa-ticket",
"idx": 7,
"links": [],
- "modified": "2020-05-06 12:28:58.093654",
+ "modified": "2020-05-14 23:59:01.172007",
"modified_by": "Administrator",
"module": "Support",
"name": "Issue",
diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py
index a9c4897017..47b9c05161 100644
--- a/erpnext/support/doctype/issue/issue.py
+++ b/erpnext/support/doctype/issue/issue.py
@@ -72,7 +72,36 @@ class Issue(Document):
# if no date, it should be set as None and not a blank string "", as per mysql strict config
self.resolution_date = None
self.reset_issue_metrics()
- self.agreement_fulfilled = "Ongoing"
+
+ if self.status == "Replied" and status != "Replied":
+ self.on_hold_since = frappe.flags.current_time or now_datetime()
+ if not self.first_responded_on:
+ self.response_by = None
+ self.response_by_variance = None
+ self.resolution_by = None
+ self.resolution_by_variance = None
+
+ if self.status != "Replied" and status == "Replied":
+ hold_time = self.total_hold_time if self.total_hold_time else 0
+ self.total_hold_time = hold_time + time_diff_in_seconds(now_datetime(), self.on_hold_since)
+
+ if self.status == "Open" and status == "Replied":
+ start_date_time = get_datetime(self.service_level_agreement_creation)
+ priority = get_priority(self)
+ hold_time = time_diff_in_seconds(now_datetime(), self.on_hold_since)
+
+ if not self.first_responded_on:
+ response_by = get_expected_time_for(parameter='response', service_level=priority, start_date_time=start_date_time)
+ self.response_by = add_to_date(response_by, seconds=round(hold_time))
+ response_by_variance = round(time_diff_in_hours(self.response_by, now_datetime()))
+ self.response_by_variance = response_by_variance + (hold_time // 3600)
+
+ resolution_by = get_expected_time_for(parameter='resolution', service_level=priority, start_date_time=start_date_time)
+ self.resolution_by = add_to_date(resolution_by, seconds=round(hold_time))
+ resolution_by_variance = round(time_diff_in_hours(self.resolution_by, now_datetime()))
+ self.resolution_by_variance = resolution_by_variance + (hold_time // 3600)
+ self.on_hold_since = None
+
def update_agreement_status(self):
if self.service_level_agreement and self.agreement_fulfilled == "Ongoing":
@@ -233,6 +262,16 @@ class Issue(Document):
self.db_set('avg_response_time', None)
+def get_priority(issue):
+ service_level_agreement = frappe.get_doc("Service Level Agreement", issue.service_level_agreement)
+ priority = service_level_agreement.get_service_level_agreement_priority(issue.priority)
+ priority.update({
+ "support_and_resolution": service_level_agreement.support_and_resolution,
+ "holiday_list": service_level_agreement.holiday_list
+ })
+ return priority
+
+
def get_expected_time_for(parameter, service_level, start_date_time):
current_date_time = start_date_time
expected_time = current_date_time