From fbc163cea66b52494595435200c43ea581fe9bd2 Mon Sep 17 00:00:00 2001 From: Saqib Date: Wed, 18 Aug 2021 11:53:26 +0530 Subject: [PATCH] feat: dynamic conditions for applying SLA (#26662) --- .../service_level_agreement.json | 7 +---- .../service_level_agreement.py | 25 +++++++++--------- .../test_service_level_agreement.py | 26 +++++++++++++++++-- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index b67c7fceac9..b649b8768bb 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -181,11 +181,6 @@ "fieldtype": "Check", "label": "Apply SLA for Resolution Time" }, - { - "label": "Pause SLA On", - "fieldname": "pause_sla_on", - "options": "Pause SLA On Status" - }, { "fieldname": "filters_section", "fieldtype": "Section Break", @@ -208,7 +203,7 @@ } ], "links": [], - "modified": "2021-07-09 12:28:46.283334", + "modified": "2021-07-27 11:16:45.596579", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index 083bde9a42c..d9cffc231f4 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -11,6 +11,7 @@ from frappe.core.utils import get_parent_doc from frappe.utils import time_diff_in_seconds, getdate, get_weekdays, add_to_date, get_time, get_datetime, \ get_time_zone, to_timedelta, get_datetime_str, get_link_to_form, cint, nowdate from datetime import datetime +from frappe.utils.safe_exec import get_safe_globals from erpnext.support.doctype.issue.issue import get_holidays from frappe.utils.safe_exec import get_safe_globals @@ -100,7 +101,7 @@ class ServiceLevelAgreement(Document): frappe.bold(self.document_type))) def validate_condition(self): - temp_doc = frappe.new_doc('Issue') + temp_doc = frappe.new_doc(self.document_type) if self.condition: try: frappe.safe_eval(self.condition, None, get_context(temp_doc)) @@ -227,25 +228,26 @@ def get_active_service_level_agreement_for(doc): if doc.get('priority'): filters.append(["Service Level Priority", "priority", "=", doc.get('priority')]) - customer = doc.get('customer') - or_filters = [ - ["Service Level Agreement", "entity", "in", [customer, get_customer_group(customer), get_customer_territory(customer)]] - ] - - service_level_agreement = doc.get('service_level_agreement') - if service_level_agreement: + or_filters = [] + if doc.get('service_level_agreement'): or_filters = [ ["Service Level Agreement", "name", "=", doc.get('service_level_agreement')], ] + customer = doc.get('customer') + if customer: + or_filters.append( + ["Service Level Agreement", "entity", "in", [customer, get_customer_group(customer), get_customer_territory(customer)]] + ) + default_sla_filter = filters + [["Service Level Agreement", "default_service_level_agreement", "=", 1]] default_sla = frappe.get_all("Service Level Agreement", filters=default_sla_filter, - fields=["name", "default_priority", "condition"]) + fields=["name", "default_priority", "apply_sla_for_resolution", "condition"]) filters += [["Service Level Agreement", "default_service_level_agreement", "=", 0]] agreements = frappe.get_all("Service Level Agreement", filters=filters, or_filters=or_filters, - fields=["name", "default_priority", "condition"]) - + fields=["name", "default_priority", "apply_sla_for_resolution", "condition"]) + # check if the current document on which SLA is to be applied fulfills all the conditions filtered_agreements = [] for agreement in agreements: @@ -261,7 +263,6 @@ def get_active_service_level_agreement_for(doc): def get_context(doc): return {"doc": doc.as_dict(), "nowdate": nowdate, "frappe": frappe._dict(utils=get_safe_globals().get("frappe").get("utils"))} - def get_customer_group(customer): return frappe.db.get_value("Customer", customer, "customer_group") if customer else None diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py index 7bc97d60227..1a5ff27d2a4 100644 --- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py @@ -253,6 +253,26 @@ class TestServiceLevelAgreement(unittest.TestCase): lead.reload() self.assertEqual(lead.response_by_variance, 1800.0) + def test_service_level_agreement_filters(self): + doctype = "Lead" + lead_sla = create_service_level_agreement( + default_service_level_agreement=0, + doctype=doctype, + holiday_list="__Test Holiday List", + entity_type=None, entity=None, + condition='doc.source == "Test Source"', + response_time=14400, + sla_fulfilled_on=[{"status": "Replied"}], + apply_sla_for_resolution=0 + ) + creation = datetime.datetime(2019, 3, 4, 12, 0) + lead = make_lead(creation=creation, index=4) + self.assertFalse(lead.service_level_agreement) + + lead.source = "Test Source" + lead.save() + self.assertEqual(lead.service_level_agreement, lead_sla.name) + def tearDown(self): for d in frappe.get_all("Service Level Agreement"): frappe.delete_doc("Service Level Agreement", d.name, force=1) @@ -268,7 +288,7 @@ def get_service_level_agreement(default_service_level_agreement=None, entity_typ return service_level_agreement def create_service_level_agreement(default_service_level_agreement, holiday_list, response_time, entity_type, - entity, resolution_time=0, doctype="Issue", sla_fulfilled_on=[], pause_sla_on=[], apply_sla_for_resolution=1): + entity, resolution_time=0, doctype="Issue", condition="", sla_fulfilled_on=[], pause_sla_on=[], apply_sla_for_resolution=1): make_holiday_list() make_priorities() @@ -287,6 +307,7 @@ def create_service_level_agreement(default_service_level_agreement, holiday_list "document_type": doctype, "service_level": "__Test {} SLA".format(entity_type if entity_type else "Default"), "default_service_level_agreement": default_service_level_agreement, + "condition": condition, "default_priority": "Medium", "holiday_list": holiday_list, "entity_type": entity_type, @@ -488,5 +509,6 @@ def make_lead(creation=None, index=0): "lead_name": "_Test Lead {0}".format(index), "status": "Open", "creation": creation, - "service_level_agreement_creation": creation + "service_level_agreement_creation": creation, + "priority": "Medium" }).insert(ignore_permissions=True) \ No newline at end of file