Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
d385a95
fix: SLA for multiple doctypes
hrwX Jun 24, 2020
926c112
fix: set hold time
hrwX Jun 25, 2020
93879e7
Merge branch 'develop' of https://github.com/frappe/erpnext into mult…
hrwX Jun 25, 2020
9a1e931
Merge branch 'develop' into multiple_slas
hrwX Jun 25, 2020
10eab1e
fix: remove unwanted fields
hrwX Jun 25, 2020
a0932d7
fix: add custom fields
hrwX Jun 26, 2020
5c15f6c
Merge branch 'multiple_slas' of https://github.com/hrwx/erpnext into …
hrwX Jun 26, 2020
36972a4
fix: remove unused imports
hrwX Jun 26, 2020
f6fc6e4
Merge branch 'develop' into multiple_slas
hrwX Jun 26, 2020
efd7ab2
fix: ignore permissions
hrwX Jun 26, 2020
dd75c29
Merge branch 'multiple_slas' of https://github.com/hrwx/erpnext into …
hrwX Jun 26, 2020
20e985e
Merge branch 'develop' of https://github.com/frappe/erpnext into mult…
hrwX Jun 30, 2020
748163c
fix: sla not being applied
hrwX Jun 30, 2020
1d4407f
fix: consider user tz for sla
hrwX Jul 3, 2020
2d94968
fix: pass user as arg
hrwX Jul 3, 2020
08eace6
fix: convert time str to timedelta
hrwX Jul 6, 2020
086dbd8
fix: add first responded on field
hrwX Jul 8, 2020
2831187
fix: get timezone
hrwX Jul 8, 2020
d4d8ed5
fix: helper function to get user time
hrwX Jul 8, 2020
e40b90e
fix: set service_level_agreement_creation
hrwX Jul 10, 2020
d862370
Merge branch 'develop' into multiple_slas
hrwX Jul 11, 2020
fdb2d37
Merge branch 'develop' of https://github.com/frappe/erpnext into mult…
deepeshgarg007 Jul 28, 2020
012e6f9
fix: Codacy Issues
deepeshgarg007 Jul 28, 2020
0afd3d2
fix: Codacy issues and travis
deepeshgarg007 Jul 28, 2020
ebb7ee7
fix: Add resolved status field in Pause SLA
deepeshgarg007 Jul 29, 2020
681e2a2
fix: Put SLA on hold for resolved status
deepeshgarg007 Jul 29, 2020
6e63f43
Merge branch 'develop' into multiple_slas
hrwX Aug 4, 2020
323fb48
Merge branch 'develop' into multiple_slas
hrwX Aug 5, 2020
8080b47
Merge branch 'develop' into multiple_slas
ruchamahabal Aug 28, 2020
e05c3e7
Merge branch 'develop' into multiple_slas
ruchamahabal Oct 5, 2020
dbe074c
fix: codacy issues and patch
ruchamahabal Oct 5, 2020
e598d63
fix: codacy issue
ruchamahabal Oct 5, 2020
923ba47
fix: validate if doctype for SLA configuration has status field
ruchamahabal Oct 9, 2020
7ff66fa
Merge branch 'develop' into multiple_slas
ruchamahabal Nov 9, 2020
aa6a124
fix: remove duplicate code, fix sider and translation issues
ruchamahabal Nov 9, 2020
9531f6a
fix: SLA status not getting updated
ruchamahabal Nov 9, 2020
0de3163
fix: sider
ruchamahabal Nov 9, 2020
7c47cfc
fix: Response and Resolution variance duration fieldtype
ruchamahabal Nov 9, 2020
83927e2
fix: SLA not getting applied for custom doctypes
ruchamahabal Nov 9, 2020
c4afa5a
fix(hooks): update sla variance
ruchamahabal Nov 9, 2020
6bffd7c
feat: show SLA indicators
ruchamahabal Nov 9, 2020
55ef8ec
Merge branch 'develop' into multiple_slas
ruchamahabal Nov 9, 2020
9e0f2bc
fix: set SLA fulfilled on Resolved
ruchamahabal Nov 9, 2020
bf71838
fix: travis
ruchamahabal Nov 9, 2020
d7c7949
feat: Hold time for SLA on custom doctypes
ruchamahabal Nov 10, 2020
20e1781
fix(patch): rename enable to enabled in SLA
ruchamahabal Nov 10, 2020
628ddfe
fix: incorrect response and resolution variance calculation
ruchamahabal Nov 10, 2020
81e5662
fix: travis and hook for updating hold time on communication
ruchamahabal Nov 10, 2020
ee988ca
Merge branch 'develop' into multiple_slas
ruchamahabal Nov 11, 2020
3e5b5ca
Merge branch 'develop' into multiple_slas
ruchamahabal Nov 30, 2020
6251226
Merge branch 'develop' into multiple_slas
ruchamahabal May 26, 2021
18762e6
fix: sider issues
ruchamahabal May 26, 2021
a350dbe
fix: add code lost in merge conflict resolution
ruchamahabal May 26, 2021
ce331df
feat: Ability to configure SLA Fulfilled On statuses
ruchamahabal May 26, 2021
ab616e2
fix: tests
ruchamahabal May 28, 2021
4f8c3e8
Merge branch 'develop' into multiple_slas
ruchamahabal May 28, 2021
352f0cd
test: added more tests for SLA
ruchamahabal May 29, 2021
4db87cd
fix: sider
ruchamahabal May 29, 2021
ee5c60a
refactor: shorter functions for sla application
ruchamahabal May 29, 2021
b05c8c4
Merge branch 'develop' into multiple_slas
ruchamahabal May 29, 2021
a37b0aa
feat: Apply SLA for Resolution configuration
ruchamahabal May 29, 2021
7bce2fe
fix: sider
ruchamahabal May 29, 2021
981c23d
test: apply SLA for resolution disabled
ruchamahabal May 29, 2021
bff1b1f
fix: show resolution time in gridview only if 'apply sla on resolutio…
ruchamahabal May 29, 2021
d645cf5
fix: update custom dt after adding SLA fields
ruchamahabal May 29, 2021
0c4b7b1
Merge branch 'develop' into multiple_slas
ruchamahabal May 29, 2021
f926611
Merge branch 'develop' into multiple_slas
nextchamp-saqib May 31, 2021
dfc17ba
Merge branch 'develop' into multiple_slas
nextchamp-saqib Jun 1, 2021
cc8467c
Merge branch 'develop' into multiple_slas
nextchamp-saqib Jun 3, 2021
d793a1b
fix: update resolution while updating hold time only if 'apply SLA fo…
ruchamahabal Jun 4, 2021
d7c0081
chore: breakdown handle_hold_time function into smaller functions
ruchamahabal Jun 4, 2021
70a649e
fix(ux): resolution time field not visible on enabling resolution app…
ruchamahabal Jun 4, 2021
940bb85
Merge branch 'develop' into multiple_slas
ruchamahabal Jun 4, 2021
f98d13d
Merge branch 'develop' into multiple_slas
ruchamahabal Jun 12, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions erpnext/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@

doc_events = {
"*": {
"validate": "erpnext.support.doctype.service_level_agreement.service_level_agreement.apply",
"on_submit": "erpnext.healthcare.doctype.patient_history_settings.patient_history_settings.create_medical_record",
"on_update_after_submit": "erpnext.healthcare.doctype.patient_history_settings.patient_history_settings.update_medical_record",
"on_cancel": "erpnext.healthcare.doctype.patient_history_settings.patient_history_settings.delete_medical_record"
Expand All @@ -242,6 +243,9 @@
"on_update": ["erpnext.hr.doctype.employee.employee.update_user_permissions",
"erpnext.portal.utils.set_default_role"]
},
"Communication": {
"on_update": "erpnext.support.doctype.service_level_agreement.service_level_agreement.update_hold_time"
},
("Sales Taxes and Charges Template", 'Price List'): {
"on_update": "erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings.validate_cart_settings"
},
Expand Down Expand Up @@ -332,8 +336,8 @@
"erpnext.projects.doctype.project.project.hourly_reminder",
"erpnext.projects.doctype.project.project.collect_project_status",
"erpnext.hr.doctype.shift_type.shift_type.process_auto_attendance_for_all_shifts",
"erpnext.support.doctype.issue.issue.set_service_level_agreement_variance",
"erpnext.erpnext_integrations.connectors.shopify_connection.sync_old_orders"
"erpnext.erpnext_integrations.connectors.shopify_connection.sync_old_orders",
"erpnext.support.doctype.service_level_agreement.service_level_agreement.set_service_level_agreement_variance"
],
"hourly_long": [
"erpnext.stock.doctype.repost_item_valuation.repost_item_valuation.repost_entries"
Expand Down
1 change: 1 addition & 0 deletions erpnext/patches.txt
Original file line number Diff line number Diff line change
Expand Up @@ -285,4 +285,5 @@ erpnext.patches.v13_0.germany_make_custom_fields
erpnext.patches.v13_0.germany_fill_debtor_creditor_number
erpnext.patches.v13_0.set_pos_closing_as_failed
erpnext.patches.v13_0.update_timesheet_changes
erpnext.patches.v13_0.add_doctype_to_sla
erpnext.patches.v13_0.set_training_event_attendance
20 changes: 20 additions & 0 deletions erpnext/patches/v13_0/add_doctype_to_sla.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright (c) 2020, Frappe and Contributors
# License: GNU General Public License v3. See license.txt

from __future__ import unicode_literals

import frappe
from frappe.model.utils.rename_field import rename_field

def execute():
frappe.reload_doc('support', 'doctype', 'service_level_agreement')
if frappe.db.has_column('Service Level Agreement', 'enable'):
rename_field('Service Level Agreement', 'enable', 'enabled')

for sla in frappe.get_all('Service Level Agreement'):
agreement = frappe.get_doc('Service Level Agreement', sla.name)
agreement.document_type = 'Issue'
agreement.apply_sla_for_resolution = 1
agreement.append('sla_fulfilled_on', {'status': 'Resolved'})
agreement.append('sla_fulfilled_on', {'status': 'Closed'})
agreement.save()
145 changes: 145 additions & 0 deletions erpnext/public/js/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,151 @@ $(document).on('app_ready', function() {
}
});

// Show SLA dashboard
$(document).on('app_ready', function() {
frappe.call({
method: 'erpnext.support.doctype.service_level_agreement.service_level_agreement.get_sla_doctypes',
callback: function(r) {
if (!r.message)
return;

$.each(r.message, function(_i, d) {
frappe.ui.form.on(d, {
onload: function(frm) {
if (!frm.doc.service_level_agreement)
return;

frappe.call({
method: 'erpnext.support.doctype.service_level_agreement.service_level_agreement.get_service_level_agreement_filters',
args: {
doctype: frm.doc.doctype,
name: frm.doc.service_level_agreement,
customer: frm.doc.customer
},
callback: function (r) {
if (r && r.message) {
frm.set_query('priority', function() {
return {
filters: {
'name': ['in', r.message.priority],
}
};
});
frm.set_query('service_level_agreement', function() {
return {
filters: {
'name': ['in', r.message.service_level_agreements],
}
};
});
}
}
});
},

refresh: function(frm) {
if (frm.doc.status !== 'Closed' && frm.doc.service_level_agreement
&& frm.doc.agreement_status === 'Ongoing') {
frappe.call({
'method': 'frappe.client.get',
args: {
doctype: 'Service Level Agreement',
name: frm.doc.service_level_agreement
},
callback: function(data) {
let statuses = data.message.pause_sla_on;
const hold_statuses = [];
$.each(statuses, (_i, entry) => {
hold_statuses.push(entry.status);
});
if (hold_statuses.includes(frm.doc.status)) {
frm.dashboard.clear_headline();
let message = {'indicator': 'orange', 'msg': __('SLA is on hold since {0}', [moment(frm.doc.on_hold_since).fromNow(true)])};
frm.dashboard.set_headline_alert(
'<div class="row">' +
'<div class="col-xs-12">' +
'<span class="indicator whitespace-nowrap '+ message.indicator +'"><span>'+ message.msg +'</span></span> ' +
'</div>' +
'</div>'
);
} else {
set_time_to_resolve_and_response(frm, data.message.apply_sla_for_resolution);
}
}
});
} else if (frm.doc.service_level_agreement) {
frm.dashboard.clear_headline();

let agreement_status = (frm.doc.agreement_status == '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> ' +
'</div>' +
'</div>'
);
}
},
});
});
}
});
});

function set_time_to_resolve_and_response(frm, apply_sla_for_resolution) {
frm.dashboard.clear_headline();

let time_to_respond = get_status(frm.doc.response_by_variance);
if (!frm.doc.first_responded_on && frm.doc.agreement_status === 'Ongoing') {
time_to_respond = get_time_left(frm.doc.response_by, frm.doc.agreement_status);
}

let alert = `
<div class="row">
<div class="col-xs-12 col-sm-6">
<span class="indicator whitespace-nowrap ${time_to_respond.indicator}">
<span>Time to Respond: ${time_to_respond.diff_display}</span>
</span>
</div>`;


if (apply_sla_for_resolution) {
let time_to_resolve = get_status(frm.doc.resolution_by_variance);
if (!frm.doc.resolution_date && frm.doc.agreement_status === 'Ongoing') {
time_to_resolve = get_time_left(frm.doc.resolution_by, frm.doc.agreement_status);
}

alert += `
<div class="col-xs-12 col-sm-6">
<span class="indicator whitespace-nowrap ${time_to_resolve.indicator}">
<span>Time to Resolve: ${time_to_resolve.diff_display}</span>
</span>
</div>`;
}

alert += '</div>';

frm.dashboard.set_headline_alert(alert);
}

function get_time_left(timestamp, agreement_status) {
const diff = moment(timestamp).diff(moment());
const diff_display = diff >= 44500 ? moment.duration(diff).humanize() : 'Failed';
let indicator = (diff_display == 'Failed' && agreement_status != 'Fulfilled') ? 'red' : 'green';
return {'diff_display': diff_display, 'indicator': indicator};
}

function get_status(variance) {
if (variance > 0) {
return {'diff_display': 'Fulfilled', 'indicator': 'green'};
} else {
return {'diff_display': 'Failed', 'indicator': 'red'};
}
}

function attach_selector_button(inner_text, append_loction, context, grid_row) {
let $btn_div = $("<div>").css({"margin-bottom": "10px", "margin-top": "10px"})
.appendTo(append_loction);
Expand Down
135 changes: 8 additions & 127 deletions erpnext/support/doctype/issue/issue.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,94 +9,15 @@ frappe.ui.form.on("Issue", {
};
});

if (frappe.model.can_read("Support Settings")) {
frappe.db.get_value("Support Settings", {name: "Support Settings"},
["allow_resetting_service_level_agreement", "track_service_level_agreement"], (r) => {
if (r && r.track_service_level_agreement == "0") {
frm.set_df_property("service_level_section", "hidden", 1);
}
if (r && r.allow_resetting_service_level_agreement == "0") {
frm.set_df_property("reset_service_level_agreement", "hidden", 1);
}
});
}

if (frm.doc.service_level_agreement) {
frappe.call({
method: "erpnext.support.doctype.service_level_agreement.service_level_agreement.get_service_level_agreement_filters",
args: {
name: frm.doc.service_level_agreement,
customer: frm.doc.customer
},
callback: function (r) {
if (r && r.message) {
frm.set_query("priority", function() {
return {
filters: {
"name": ["in", r.message.priority],
}
};
});
frm.set_query("service_level_agreement", function() {
return {
filters: {
"name": ["in", r.message.service_level_agreements],
}
};
});
}
frappe.db.get_value("Support Settings", {name: "Support Settings"},
["allow_resetting_service_level_agreement", "track_service_level_agreement"], (r) => {
if (r && r.track_service_level_agreement == "0") {
frm.set_df_property("service_level_section", "hidden", 1);
}
});
}
},

refresh: function(frm) {

// alert messages
if (frm.doc.status !== "Closed" && frm.doc.service_level_agreement
&& frm.doc.agreement_status === "Ongoing") {
frappe.call({
"method": "frappe.client.get",
args: {
doctype: "Service Level Agreement",
name: frm.doc.service_level_agreement
},
callback: function(data) {
let statuses = data.message.pause_sla_on;
const hold_statuses = [];
$.each(statuses, (_i, entry) => {
hold_statuses.push(entry.status);
});
if (hold_statuses.includes(frm.doc.status)) {
frm.dashboard.clear_headline();
let message = { "indicator": "orange", "msg": __("SLA is on hold since {0}", [moment(frm.doc.on_hold_since).fromNow(true)]) };
frm.dashboard.set_headline_alert(
'<div class="row">' +
'<div class="col-xs-12">' +
'<span class="indicator whitespace-nowrap ' + message.indicator + '"><span>' + message.msg + '</span></span> ' +
'</div>' +
'</div>'
);
} else {
set_time_to_resolve_and_response(frm);
}
if (r && r.allow_resetting_service_level_agreement == "0") {
frm.set_df_property("reset_service_level_agreement", "hidden", 1);
}
});
} else if (frm.doc.service_level_agreement) {
frm.dashboard.clear_headline();

let agreement_status = (frm.doc.agreement_status == "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> ' +
'</div>' +
'</div>'
);
}

// buttons
if (frm.doc.status !== "Closed") {
Expand Down Expand Up @@ -142,7 +63,7 @@ frappe.ui.form.on("Issue", {
message: __("Resetting Service Level Agreement.")
});

frm.call("reset_service_level_agreement", {
frappe.call("erpnext.support.doctype.service_level_agreement.service_level_agreement.reset_service_level_agreement", {
reason: values.reason,
user: frappe.session.user_email
}, () => {
Expand Down Expand Up @@ -224,44 +145,4 @@ frappe.ui.form.on("Issue", {
// frm.timeline.wrapper.data("help-article-event-attached", true);
// }
},
});

function set_time_to_resolve_and_response(frm) {
frm.dashboard.clear_headline();

var time_to_respond = get_status(frm.doc.response_by_variance);
if (!frm.doc.first_responded_on && frm.doc.agreement_status === "Ongoing") {
time_to_respond = get_time_left(frm.doc.response_by, frm.doc.agreement_status);
}

var time_to_resolve = get_status(frm.doc.resolution_by_variance);
if (!frm.doc.resolution_date && frm.doc.agreement_status === "Ongoing") {
time_to_resolve = get_time_left(frm.doc.resolution_by, frm.doc.agreement_status);
}

frm.dashboard.set_headline_alert(
'<div class="row">' +
'<div class="col-xs-12 col-sm-6">' +
'<span class="indicator whitespace-nowrap '+ time_to_respond.indicator +'"><span>Time to Respond: '+ time_to_respond.diff_display +'</span></span> ' +
'</div>' +
'<div class="col-xs-12 col-sm-6">' +
'<span class="indicator whitespace-nowrap '+ time_to_resolve.indicator +'"><span>Time to Resolve: '+ time_to_resolve.diff_display +'</span></span> ' +
'</div>' +
'</div>'
);
}

function get_time_left(timestamp, agreement_status) {
const diff = moment(timestamp).diff(moment());
const diff_display = diff >= 44500 ? moment.duration(diff).humanize() : "Failed";
let indicator = (diff_display == "Failed" && agreement_status != "Fulfilled") ? "red" : "green";
return {"diff_display": diff_display, "indicator": indicator};
}

function get_status(variance) {
if (variance > 0) {
return {"diff_display": "Fulfilled", "indicator": "green"};
} else {
return {"diff_display": "Failed", "indicator": "red"};
}
}
});
Loading