From 9f19a82ec99c9b614132f4f08928b1776260ce62 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 20 Jun 2019 23:29:56 +0530 Subject: [PATCH] fix: scheduling bug if out of bussiness hours --- erpnext/support/doctype/issue/issue.py | 6 +- erpnext/support/doctype/issue/test_issue.py | 59 ++++++++++++++----- .../service_level_agreement.json | 8 +-- .../service_level_agreement.py | 4 ++ 4 files changed, 54 insertions(+), 23 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 3fe8ca0bc6..b8d213c6c4 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -7,7 +7,7 @@ import json from frappe import _ from frappe import utils from frappe.model.document import Document -from frappe.utils import now, time_diff_in_hours, now_datetime, getdate, get_weekdays, add_to_date, today, get_time, get_datetime +from frappe.utils import now, time_diff_in_hours, now_datetime, getdate, get_weekdays, add_to_date, today, get_time, get_datetime, get_time_in_timedelta from datetime import datetime, timedelta from frappe.model.mapper import get_mapped_doc from frappe.utils.user import is_website_user @@ -217,7 +217,9 @@ def get_expected_time_for(parameter, service_level, start_date_time): current_weekday = weekdays[current_date_time.weekday()] if not is_holiday(current_date_time, holidays) and current_weekday in support_days: - start_time = current_date_time - datetime(current_date_time.year, current_date_time.month, current_date_time.day) if getdate(current_date_time) == getdate(start_date_time) else support_days[current_weekday].start_time + start_time = current_date_time - datetime(current_date_time.year, current_date_time.month, current_date_time.day) \ + if getdate(current_date_time) == getdate(start_date_time) and get_time_in_timedelta(current_date_time.time()) > support_days[current_weekday].start_time \ + else support_days[current_weekday].start_time end_time = support_days[current_weekday].end_time time_left_today = time_diff_in_hours(end_time, start_time) diff --git a/erpnext/support/doctype/issue/test_issue.py b/erpnext/support/doctype/issue/test_issue.py index 1a793a6144..519c107608 100644 --- a/erpnext/support/doctype/issue/test_issue.py +++ b/erpnext/support/doctype/issue/test_issue.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe import unittest from erpnext.support.doctype.service_level_agreement.test_service_level_agreement import create_service_level_agreements_for_issues -from frappe.utils import now_datetime +from frappe.utils import now_datetime, get_datetime import datetime from datetime import timedelta from frappe.desk.form import assign_to @@ -20,38 +20,65 @@ class TestIssue(unittest.TestCase): def test_response_time_and_resolution_time_based_on_different_sla(self): create_service_level_agreements_for_issues() - creation = "2019-03-04 12:00:00" - - # make issue with customer specific SLA + creation = datetime.datetime(2019, 3, 4, 12, 0) + """ + make issue with customer specific SLA + """ customer = create_customer("_Test Customer", "__Test SLA Customer Group", "__Test SLA Territory") - issue = make_issue(creation, "_Test Customer") + issue = make_issue(creation, "_Test Customer", 1) self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0)) self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0)) - # make issue with customer_group specific SLA + """ + make issue with customer_group specific SLA + """ customer = create_customer("__Test Customer", "_Test SLA Customer Group", "__Test SLA Territory") - issue = make_issue(creation, "__Test Customer") + issue = make_issue(creation, "__Test Customer", 2) self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0)) self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0)) - # make issue with territory specific SLA + """ + make issue with territory specific SLA + """ customer = create_customer("___Test Customer", "__Test SLA Customer Group", "_Test SLA Territory") - issue = make_issue(creation, "___Test Customer") + issue = make_issue(creation, "___Test Customer", 3) self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0)) self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0)) - # make issue with default SLA - issue = make_issue(creation) + """ + make issue with default SLA + """ + issue = make_issue(creation=creation, index=4) self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 16, 0)) self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 18, 0)) - creation = "2019-03-04 14:00:00" - # make issue with default SLA next day - issue = make_issue(creation) + """ + make issue with default SLA before working hours + """ + creation = datetime.datetime(2019, 3, 4, 7, 0) + issue = make_issue(creation=creation, index=5) + + self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0)) + self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 16, 0)) + + """ + make issue with default SLA after working hours + """ + creation = datetime.datetime(2019, 3, 4, 20, 0) + issue = make_issue(creation, index=6) + + self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 6, 14, 0)) + self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 6, 16, 0)) + + """ + make issue with default SLA next day + """ + creation = datetime.datetime(2019, 3, 4, 14, 0) + issue = make_issue(creation=creation, index=7) self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 18, 0)) self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 6, 12, 0)) @@ -63,11 +90,11 @@ class TestIssue(unittest.TestCase): self.assertEqual(issue.agreement_fulfilled, 'Fulfilled') -def make_issue(creation=None, customer=None): +def make_issue(creation=None, customer=None, index=0): issue = frappe.get_doc({ "doctype": "Issue", - "subject": "Service Level Agreement Issue", + "subject": "Service Level Agreement Issue {0}".format(index), "customer": customer, "raised_by": "test@example.com", "description": "Service Level Agreement Issue", 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 17ccb5c76a..f91a80c60d 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -31,8 +31,7 @@ "depends_on": "eval: !doc.customer;", "fieldname": "default_service_level_agreement", "fieldtype": "Check", - "label": "Default Service Level Agreement", - "set_only_once": 1 + "label": "Default Service Level Agreement" }, { "fieldname": "service_level", @@ -41,8 +40,7 @@ "in_standard_filter": 1, "label": "Service Level", "options": "Service Level", - "reqd": 1, - "set_only_once": 1 + "reqd": 1 }, { "fetch_from": "service_level.holiday_list", @@ -153,7 +151,7 @@ "options": "\nCustomer\nCustomer Group\nTerritory" } ], - "modified": "2019-06-20 10:34:58.634693", + "modified": "2019-06-20 18:04:14.293378", "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 6231812744..b804581298 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -21,6 +21,10 @@ class ServiceLevelAgreement(Document): if self.end_date < frappe.utils.getdate(): frappe.throw(_("End Date of Agreement can't be less than today.")) + if self.entity_type and self.entity: + if frappe.db.exists("Service Level Agreement", {"entity_type": self.entity_type, "entity": self.entity, "name": ["!=", self.name]}): + frappe.throw(_("Service Level Agreement with Entity Type {0} and Entity {1} already exists.").format(self.entity_type, self.entity)) + def get_service_level_agreement_priority(self, priority): priority = frappe.get_doc("Service Level Priority", {"priority": priority, "parent": self.name})