feat(Support): Service Level Agreements (#16828)
* init SLA * Added more inputs to the forms * set priority of issue * Removed UOM in favor of hours for tracking * updated js to autofill values * Removed unwanted fields * timer functionality * code refactor * parenthesis fix * fixed typo * added new fields * Updated fields * Updated fields for issue doctype * Updated fields for issue doctype * changed doctype structure * added new fields to issue * code refactor * new function to set criticality level * changed dropdown options * set timer for sla * calculation of resolution and response time * stopwatch counter * dashboard changes * renamed sla to support contract * countdown timer section * issue doctype changes * removed unwanted imports * fixed wrong response time and resolution time * update response and resolution time * calculate time to respond and resolve * feature enhancements * probable scheduling bug fix * fixed scheduling issue support sent out of support time * removed issue criticality link from support * Changed day order * skip date validation when support contract is default * removed mandatory field * fix scheduling conditions for now * code refactor * removed duplicate doctypes * fixed day inserted twice in service level * check to not add another default contract * default support contracts * removed commented code * removed unused imports * fix sla for non-listed days * reduced redundant code and optimized it and starting unit tests * added condition check to compute days correctly * renamed doc as per guidelines and added conditions for scheduling * removed per day support timings * added response and resolution time to support contract * scheduling based on hours kinda fix * set sla before_update and finally fixed time scheduling out of support time * DocType Issue removed test_records and rewrote test cases * test cases and codacy fixes * Doctype SLA instead of Support Contract to avoid confusion with Contract * fixed tests failing due to change in options for time period * change naming to Prompt * remove unknown doctype from help_desk * revert unwanted changes to default * refactor get_list for fetching service_level_agreement * change datatypes * fix tests * refactored tests * remove unused imports * code and comments refactor for better understandability * removed and renamed doctype to service days and minor fixes * Refactor test cases for response and resolution time for issue * add validation to check if response time < resolution time * minor fix for checking if current day is start day * calculate time in js rather than python * fix: parenthesis fixing customer dashboard * json changes to rename sections * refactor: alignment * refactor: beautify code * fix: use frm api to get the element * fix: replace '__' with '_' * refactor: remove pointless test
This commit is contained in:
parent
51eec69164
commit
f3e5213190
@ -2,61 +2,81 @@ from __future__ import unicode_literals
|
||||
from frappe import _
|
||||
|
||||
def get_data():
|
||||
return [
|
||||
{
|
||||
"label": _("Issues"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Issue",
|
||||
"description": _("Support queries from customers."),
|
||||
return [
|
||||
{
|
||||
"label": _("Issues"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Issue",
|
||||
"description": _("Support queries from customers."),
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Communication",
|
||||
"description": _("Communication log."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Communication",
|
||||
"description": _("Communication log."),
|
||||
"onboard": 1,
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Warranty"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Warranty Claim",
|
||||
"description": _("Warranty Claim against Serial No."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Serial No",
|
||||
"description": _("Single unit of an Item."),
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Reports"),
|
||||
"icon": "fa fa-list",
|
||||
"items": [
|
||||
{
|
||||
"type": "page",
|
||||
"name": "support-analytics",
|
||||
"label": _("Support Analytics"),
|
||||
"icon": "fa fa-bar-chart"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Minutes to First Response for Issues",
|
||||
"doctype": "Issue",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Support Hours",
|
||||
"doctype": "Issue",
|
||||
"is_query_report": True
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Warranty"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Warranty Claim",
|
||||
"description": _("Warranty Claim against Serial No."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Serial No",
|
||||
"description": _("Single unit of an Item."),
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Service Level Agreement"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Group",
|
||||
"description": _("Support Team."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Service Level",
|
||||
"description": _("Service Level."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Service Level Agreement",
|
||||
"description": _("Service Level Agreement."),
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Reports"),
|
||||
"icon": "fa fa-list",
|
||||
"items": [
|
||||
{
|
||||
"type": "page",
|
||||
"name": "support-analytics",
|
||||
"label": _("Support Analytics"),
|
||||
"icon": "fa fa-bar-chart"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Minutes to First Response for Issues",
|
||||
"doctype": "Issue",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Support Hours",
|
||||
"doctype": "Issue",
|
||||
"is_query_report": True
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
80
erpnext/config/support.py
Normal file
80
erpnext/config/support.py
Normal file
@ -0,0 +1,80 @@
|
||||
from __future__ import unicode_literals
|
||||
from frappe import _
|
||||
|
||||
def get_data():
|
||||
return [
|
||||
{
|
||||
"label": _("Issues"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Issue",
|
||||
"description": _("Support queries from customers."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Communication",
|
||||
"description": _("Communication log."),
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Warranty"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Warranty Claim",
|
||||
"description": _("Warranty Claim against Serial No."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Serial No",
|
||||
"description": _("Single unit of an Item."),
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Reports"),
|
||||
"icon": "fa fa-list",
|
||||
"items": [
|
||||
{
|
||||
"type": "page",
|
||||
"name": "support-analytics",
|
||||
"label": _("Support Analytics"),
|
||||
"icon": "fa fa-bar-chart"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Minutes to First Response for Issues",
|
||||
"doctype": "Issue",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Support Hours",
|
||||
"doctype": "Issue",
|
||||
"is_query_report": True
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Service Level Agreement"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Group",
|
||||
"description": _("Support Team."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Service Level",
|
||||
"description": _("Service Level."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Service Level Agreement",
|
||||
"description": _("Service Level Agreement."),
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
@ -241,7 +241,8 @@ scheduler_events = {
|
||||
"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.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.update_support_timer",
|
||||
],
|
||||
"daily": [
|
||||
"erpnext.stock.reorder_item.reorder_item",
|
||||
@ -262,7 +263,8 @@ scheduler_events = {
|
||||
"erpnext.crm.doctype.contract.contract.update_status_for_contracts",
|
||||
"erpnext.projects.doctype.project.project.update_project_sales_billing",
|
||||
"erpnext.projects.doctype.project.project.send_project_status_email_to_users",
|
||||
"erpnext.quality_management.doctype.quality_review.quality_review.review"
|
||||
"erpnext.quality_management.doctype.quality_review.quality_review.review",
|
||||
"erpnext.support.doctype.service_level_agreement.service_level_agreement.check_agreement_status"
|
||||
],
|
||||
"daily_long": [
|
||||
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms"
|
||||
|
0
erpnext/hr/doctype/employee_group/__init__.py
Normal file
0
erpnext/hr/doctype/employee_group/__init__.py
Normal file
6
erpnext/hr/doctype/employee_group/employee_group.js
Normal file
6
erpnext/hr/doctype/employee_group/employee_group.js
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Employee Group', {
|
||||
|
||||
});
|
162
erpnext/hr/doctype/employee_group/employee_group.json
Normal file
162
erpnext/hr/doctype/employee_group/employee_group.json
Normal file
@ -0,0 +1,162 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "field:employee_group_name",
|
||||
"beta": 0,
|
||||
"creation": "2018-11-19 12:33:31.351364",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "employee_group_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_00",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "employee_list",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Employee Group Table",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-12-27 19:52:34.791538",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Group",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
9
erpnext/hr/doctype/employee_group/employee_group.py
Normal file
9
erpnext/hr/doctype/employee_group/employee_group.py
Normal file
@ -0,0 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from frappe.model.document import Document
|
||||
|
||||
class EmployeeGroup(Document):
|
||||
pass
|
32
erpnext/hr/doctype/employee_group/test_employee_group.py
Normal file
32
erpnext/hr/doctype/employee_group/test_employee_group.py
Normal file
@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import unittest
|
||||
from erpnext.hr.doctype.employee.test_employee import make_employee
|
||||
|
||||
class TestEmployeeGroup(unittest.TestCase):
|
||||
pass
|
||||
|
||||
def make_employee_group():
|
||||
employee = make_employee("testemployee@example.com")
|
||||
employee_group = frappe.get_doc({
|
||||
"doctype": "Employee Group",
|
||||
"employee_group_name": "_Test Employee Group",
|
||||
"employee_list": [
|
||||
{
|
||||
"employee": employee
|
||||
}
|
||||
]
|
||||
})
|
||||
employee_group_exist = frappe.db.exists("Employee Group", "_Test Employee Group")
|
||||
if not employee_group_exist:
|
||||
employee_group.insert()
|
||||
return employee_group.employee_group_name
|
||||
else:
|
||||
return employee_group_exist
|
||||
|
||||
def get_employee_group():
|
||||
employee_group = frappe.db.exists("Employee Group", "_Test Employee Group")
|
||||
return employee_group
|
0
erpnext/hr/doctype/employee_group_table/__init__.py
Normal file
0
erpnext/hr/doctype/employee_group_table/__init__.py
Normal file
@ -0,0 +1,109 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2018-11-19 12:39:46.153061",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "employee",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Employee",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "employee.first_name",
|
||||
"fieldname": "employee_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-11-19 13:18:17.281656",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Group Table",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from frappe.model.document import Document
|
||||
|
||||
class EmployeeGroupTable(Document):
|
||||
pass
|
@ -2,6 +2,8 @@
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
import frappe
|
||||
test_records = frappe.get_test_records('Holiday List')
|
||||
import unittest
|
||||
|
||||
class TestHolidayList(unittest.TestCase):
|
||||
pass
|
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,10 @@ def get_data():
|
||||
'label': _('Orders'),
|
||||
'items': ['Sales Order', 'Delivery Note', 'Sales Invoice']
|
||||
},
|
||||
{
|
||||
'label': _('Service Level Agreement'),
|
||||
'items': ['Service Level Agreement']
|
||||
},
|
||||
{
|
||||
'label': _('Payments'),
|
||||
'items': ['Payment Entry']
|
||||
|
@ -1,6 +1,7 @@
|
||||
frappe.ui.form.on("Issue", {
|
||||
onload: function(frm) {
|
||||
frm.email_field = "raised_by";
|
||||
set_time_to_resolve_and_response(frm);
|
||||
},
|
||||
|
||||
refresh: function (frm) {
|
||||
@ -74,5 +75,39 @@ frappe.ui.form.on("Issue", {
|
||||
frm.timeline.wrapper.data("split-issue-event-attached", true)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
function set_time_to_resolve_and_response(frm) {
|
||||
|
||||
const customer = frm.fields_dict['customer'].$wrapper;
|
||||
const email_account = frm.fields_dict['email_account'].$wrapper;
|
||||
|
||||
const time_to_respond = $(get_time_left_element(__('Time To Respond'), frm.doc.response_by));
|
||||
const time_to_resolve = $(get_time_left_element(__('Time To Resolve'), frm.doc.resolve_by));
|
||||
|
||||
time_to_respond.insertAfter(customer);
|
||||
time_to_resolve.insertAfter(email_account);
|
||||
}
|
||||
|
||||
function get_time_left_element(label, timestamp) {
|
||||
return `
|
||||
<div class="frappe-control input-max-width" data-field_name="${label.replace(/ /g, "_").toLowerCase()}">
|
||||
<div class="form-group">
|
||||
<div class="clearfix">
|
||||
<label class="control-label" style="padding-right: 0px;">
|
||||
${label}
|
||||
</label>
|
||||
</div>
|
||||
<div class="control-input-wrapper">
|
||||
<div class="control-value like-disabled-input">${get_time_left(timestamp)}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function get_time_left(timestamp) {
|
||||
const diff = moment(timestamp).diff(moment());
|
||||
return diff >= 44500 ? moment.duration().humanize() : 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -5,11 +5,13 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
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 datetime import datetime, timedelta
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from frappe.utils import now
|
||||
from frappe.utils.user import is_website_user
|
||||
from ..service_level_agreement.service_level_agreement import get_active_service_level_agreement_for
|
||||
|
||||
sender_field = "raised_by"
|
||||
|
||||
@ -108,6 +110,91 @@ class Issue(Document):
|
||||
|
||||
return replicated_issue.name
|
||||
|
||||
def before_insert(self):
|
||||
self.set_response_and_resolution_time()
|
||||
|
||||
def set_response_and_resolution_time(self):
|
||||
service_level_agreement = get_active_service_level_agreement_for(self.customer)
|
||||
if service_level_agreement:
|
||||
self.service_level_agreement = service_level_agreement.name
|
||||
self.priority = service_level_agreement.priority
|
||||
|
||||
if not self.service_level_agreement: return
|
||||
|
||||
service_level = frappe.get_doc("Service Level", service_level_agreement.service_level)
|
||||
|
||||
if not self.creation:
|
||||
self.creation = now_datetime()
|
||||
|
||||
start_date_time = get_datetime(self.creation)
|
||||
|
||||
self.response_by, self.time_to_respond = get_expected_time_for('response', service_level, start_date_time)
|
||||
self.resolution_by, self.time_to_resolve = get_expected_time_for('resolution', service_level, start_date_time)
|
||||
|
||||
def get_expected_time_for(parameter, service_level, start_date_time):
|
||||
current_date_time = start_date_time
|
||||
expected_time = current_date_time
|
||||
start_time = None
|
||||
end_time = None
|
||||
|
||||
# lets assume response time is in days by default
|
||||
if parameter == 'response':
|
||||
allotted_days = service_level.response_time
|
||||
time_period = service_level.response_time_period
|
||||
elif parameter == 'resolution':
|
||||
allotted_days = service_level.resolution_time
|
||||
time_period = service_level.resolution_time_period
|
||||
else:
|
||||
frappe.throw(_("{0} parameter is invalid".format(parameter)))
|
||||
|
||||
allotted_hours = 0
|
||||
if time_period == 'Hour':
|
||||
allotted_hours = allotted_days
|
||||
allotted_days = 0
|
||||
elif time_period == 'Week':
|
||||
allotted_days *= 7
|
||||
|
||||
expected_time_is_set = 1 if allotted_days == 0 and time_period in ['Day', 'Week'] else 0
|
||||
|
||||
support_days = {}
|
||||
for service in service_level.support_and_resolution:
|
||||
support_days[service.workday] = frappe._dict({
|
||||
'start_time': service.start_time,
|
||||
'end_time': service.end_time,
|
||||
})
|
||||
|
||||
holidays = get_holidays(service_level.holiday_list)
|
||||
weekdays = get_weekdays()
|
||||
|
||||
while not expected_time_is_set:
|
||||
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
|
||||
end_time = support_days[current_weekday].end_time
|
||||
time_left_today = time_diff_in_hours(end_time, start_time)
|
||||
|
||||
# no time left for support today
|
||||
if time_left_today < 0: pass
|
||||
elif time_period == 'Hour':
|
||||
if time_left_today >= allotted_hours:
|
||||
expected_time = datetime.combine(getdate(current_date_time), get_time(start_time))
|
||||
expected_time = add_to_date(expected_time, hours=allotted_hours)
|
||||
expected_time_is_set = 1
|
||||
else:
|
||||
allotted_hours = allotted_hours - time_left_today
|
||||
else:
|
||||
allotted_days -= 1
|
||||
expected_time_is_set = allotted_days <= 0
|
||||
|
||||
current_date_time = add_to_date(current_date_time, days=1)
|
||||
|
||||
if end_time and time_period != 'Hour':
|
||||
current_date_time = datetime.combine(getdate(current_date_time), get_time(end_time))
|
||||
else:
|
||||
current_date_time = expected_time
|
||||
|
||||
return current_date_time, round(time_diff_in_hours(current_date_time, start_date_time), 2)
|
||||
|
||||
def get_list_context(context=None):
|
||||
return {
|
||||
@ -168,18 +255,35 @@ def auto_close_tickets():
|
||||
doc.flags.ignore_mandatory = True
|
||||
doc.save()
|
||||
|
||||
|
||||
def has_website_permission(doc, ptype, user, verbose=False):
|
||||
from erpnext.controllers.website_list_for_contact import has_website_permission
|
||||
permission_based_on_customer = has_website_permission(doc, ptype, user, verbose)
|
||||
|
||||
return permission_based_on_customer or doc.raised_by==user
|
||||
|
||||
|
||||
def update_issue(contact, method):
|
||||
"""Called when Contact is deleted"""
|
||||
frappe.db.sql("""UPDATE `tabIssue` set contact='' where contact=%s""", contact.name)
|
||||
|
||||
def update_support_timer():
|
||||
issues = frappe.get_list("Issue", filters={"status": "Open"}, order_by="creation DESC")
|
||||
for issue in issues:
|
||||
issue = frappe.get_doc("Issue", issue.name)
|
||||
|
||||
if round(time_diff_in_hours(issue.response_by, now_datetime()), 2) < 0 or round(time_diff_in_hours(issue.resolution_by, now_datetime()), 2) < 0:
|
||||
issue.agreement_status = "Failed"
|
||||
else:
|
||||
issue.agreement_status = "Fulfilled"
|
||||
issue.save()
|
||||
|
||||
|
||||
def get_holidays(holiday_list_name):
|
||||
holiday_list = frappe.get_cached_doc("Holiday List", holiday_list_name)
|
||||
holidays = [holiday.holiday_date for holiday in holiday_list.holidays]
|
||||
return holidays
|
||||
|
||||
def is_holiday(date, holidays):
|
||||
return getdate(date) in holidays
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_task(source_name, target_doc=None):
|
||||
|
@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Issue", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Issue
|
||||
() => frappe.tests.make('Issue', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
@ -4,8 +4,46 @@ from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
test_records = frappe.get_test_records('Issue')
|
||||
from erpnext.support.doctype.service_level_agreement.test_service_level_agreement import make_service_level_agreement
|
||||
from frappe.utils import now_datetime
|
||||
import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
class TestIssue(unittest.TestCase):
|
||||
pass
|
||||
|
||||
def test_response_time_and_resolution_time_based_on_different_sla(self):
|
||||
make_service_level_agreement()
|
||||
|
||||
creation = "2019-03-04 12:00:00"
|
||||
|
||||
# make issue with customer specific SLA
|
||||
issue = make_issue(creation, '_Test Customer')
|
||||
|
||||
self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 7, 18, 0))
|
||||
self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 9, 18, 0))
|
||||
|
||||
# make issue with default SLA
|
||||
issue = make_issue(creation)
|
||||
|
||||
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)
|
||||
|
||||
self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 18, 0))
|
||||
self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 6, 12, 0))
|
||||
|
||||
|
||||
def make_issue(creation, customer=None):
|
||||
|
||||
issue = frappe.get_doc({
|
||||
"doctype": "Issue",
|
||||
"subject": "Issue 1",
|
||||
"customer": customer,
|
||||
"raised_by": "test@example.com",
|
||||
"creation": creation
|
||||
}).insert()
|
||||
|
||||
return issue
|
@ -1,8 +0,0 @@
|
||||
[
|
||||
{
|
||||
"doctype": "Issue",
|
||||
"name": "_Test Issue 1",
|
||||
"subject": "Test Support",
|
||||
"raised_by": "test@example.com"
|
||||
}
|
||||
]
|
@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Issue Type", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Issue Type
|
||||
() => frappe.tests.make('Issue Type', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
0
erpnext/support/doctype/service_day/__init__.py
Normal file
0
erpnext/support/doctype/service_day/__init__.py
Normal file
203
erpnext/support/doctype/service_day/service_day.json
Normal file
203
erpnext/support/doctype/service_day/service_day.json
Normal file
@ -0,0 +1,203 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2019-03-04 12:55:36.403035",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "workday",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Workday",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Monday\nTuesday\nWednesday\nThursday\nFriday\nSaturday\nSunday",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_2",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "start_time",
|
||||
"fieldtype": "Time",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Start Time",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "end_time",
|
||||
"fieldtype": "Time",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "End Time",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-03-04 12:55:36.403035",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Support",
|
||||
"name": "Service Day",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
10
erpnext/support/doctype/service_day/service_day.py
Normal file
10
erpnext/support/doctype/service_day/service_day.py
Normal file
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class ServiceDay(Document):
|
||||
pass
|
0
erpnext/support/doctype/service_level/__init__.py
Normal file
0
erpnext/support/doctype/service_level/__init__.py
Normal file
6
erpnext/support/doctype/service_level/service_level.js
Normal file
6
erpnext/support/doctype/service_level/service_level.js
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Service Level', {
|
||||
|
||||
});
|
488
erpnext/support/doctype/service_level/service_level.json
Normal file
488
erpnext/support/doctype/service_level/service_level.json
Normal file
@ -0,0 +1,488 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "field:service_level",
|
||||
"beta": 0,
|
||||
"creation": "2018-11-19 12:44:30.407502",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "service_level",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Level",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "priority",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Priority",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Low\nMedium\nHigh",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "holiday_list",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Holiday List (ignored during SLA calculation)",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Holiday List",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "employee_group",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee Group",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Employee Group",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "response_and_resoution_time",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Response and Resoution Time",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "response_time",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Response Time",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "resolution_time",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Resolution Time",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "column_break_9",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "response_time_period",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Response Time Period",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Hour\nDay\nWeek",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "resolution_time_period",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Resolution Time Period",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Hour\nDay\nWeek",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "section_break_01",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Support and Resolution",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "support_and_resolution",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Support and Resolution",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Service Day",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-03-04 12:55:53.215841",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Support",
|
||||
"name": "Service Level",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
46
erpnext/support/doctype/service_level/service_level.py
Normal file
46
erpnext/support/doctype/service_level/service_level.py
Normal file
@ -0,0 +1,46 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from datetime import datetime
|
||||
from frappe.utils import get_weekdays
|
||||
|
||||
class ServiceLevel(Document):
|
||||
|
||||
def validate(self):
|
||||
week = get_weekdays()
|
||||
indexes = []
|
||||
|
||||
self.check_response_and_resolution_time()
|
||||
|
||||
for support_and_resolution in self.support_and_resolution:
|
||||
indexes.append(week.index(support_and_resolution.workday))
|
||||
support_and_resolution.idx = week.index(support_and_resolution.workday) + 1
|
||||
start_time, end_time = (datetime.strptime(support_and_resolution.start_time, '%H:%M:%S').time(),
|
||||
datetime.strptime(support_and_resolution.end_time, '%H:%M:%S').time())
|
||||
if start_time > end_time:
|
||||
frappe.throw(_("Start Time can't be greater than End Time for {0}.".format(support_and_resolution.workday)))
|
||||
if not len(set(indexes)) == len(indexes):
|
||||
frappe.throw(_("Workday has been repeated twice"))
|
||||
|
||||
def check_response_and_resolution_time(self):
|
||||
if self.response_time_period == "Hour":
|
||||
response = self.response_time * 0.0416667
|
||||
elif self.response_time_period == "Day":
|
||||
response = self.response_time
|
||||
elif self.response_time_period == "Week":
|
||||
response = self.response_time * 7
|
||||
|
||||
if self.resolution_time_period == "Hour":
|
||||
resolution = self.resolution_time * 0.0416667
|
||||
elif self.resolution_time_period == "Day":
|
||||
resolution = self.resolution_time
|
||||
elif self.resolution_time_period == "Week":
|
||||
resolution = self.resolution_time * 7
|
||||
|
||||
if response > resolution:
|
||||
frappe.throw(_("Response Time can't be greater than Resolution Time"))
|
156
erpnext/support/doctype/service_level/test_service_level.py
Normal file
156
erpnext/support/doctype/service_level/test_service_level.py
Normal file
@ -0,0 +1,156 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
from erpnext.hr.doctype.employee_group.test_employee_group import make_employee_group
|
||||
from frappe.utils import now_datetime
|
||||
import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
class TestServiceLevel(unittest.TestCase):
|
||||
pass
|
||||
|
||||
def make_service_level():
|
||||
employee_group = make_employee_group()
|
||||
make_holiday_list()
|
||||
|
||||
# Default Service Level Agreement
|
||||
default_service_level = frappe.get_doc({
|
||||
"doctype": "Service Level",
|
||||
"service_level": "__Test Service Level",
|
||||
"holiday_list": "__Test Holiday List",
|
||||
"priority": "Medium",
|
||||
"employee_group": employee_group,
|
||||
"response_time": 4,
|
||||
"response_time_period": "Hour",
|
||||
"resolution_time": 6,
|
||||
"resolution_time_period": "Hour",
|
||||
"support_and_resolution": [
|
||||
{
|
||||
"workday": "Monday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Tuesday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Wednesday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Thursday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Friday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Saturday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Sunday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
default_service_level_exists = frappe.db.exists("Service Level", "__Test Service Level")
|
||||
if not default_service_level_exists:
|
||||
default_service_level.insert()
|
||||
|
||||
service_level = frappe.get_doc({
|
||||
"doctype": "Service Level",
|
||||
"service_level": "_Test Service Level",
|
||||
"holiday_list": "__Test Holiday List",
|
||||
"priority": "Medium",
|
||||
"employee_group": employee_group,
|
||||
"response_time": 2,
|
||||
"response_time_period": "Day",
|
||||
"resolution_time": 3,
|
||||
"resolution_time_period": "Day",
|
||||
"support_and_resolution": [
|
||||
{
|
||||
"workday": "Monday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Tuesday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Wednesday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Thursday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Friday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Saturday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Sunday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
}
|
||||
]
|
||||
})
|
||||
service_level_exist = frappe.db.exists("Service Level", "_Test Service Level")
|
||||
if not service_level_exist:
|
||||
service_level.insert()
|
||||
return service_level.service_level
|
||||
else:
|
||||
return service_level_exist
|
||||
|
||||
def get_service_level():
|
||||
service_level = frappe.db.exists("Service Level", "_Test Service Level")
|
||||
return service_level
|
||||
|
||||
def make_holiday_list():
|
||||
holiday_list = frappe.db.exists("Holiday List", "__Test Holiday List")
|
||||
if not holiday_list:
|
||||
now = datetime.datetime.now()
|
||||
holiday_list = frappe.get_doc({
|
||||
"doctype": "Holiday List",
|
||||
"holiday_list_name": "__Test Holiday List",
|
||||
"from_date": "2019-01-01",
|
||||
"to_date": "2019-12-31",
|
||||
"holidays": [
|
||||
{
|
||||
"description": "Test Holiday 1",
|
||||
"holiday_date": "2019-03-05"
|
||||
},
|
||||
{
|
||||
"description": "Test Holiday 2",
|
||||
"holiday_date": "2019-03-07"
|
||||
},
|
||||
{
|
||||
"description": "Test Holiday 3",
|
||||
"holiday_date": "2019-02-11"
|
||||
},
|
||||
]
|
||||
}).insert()
|
@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Service Level Agreement', {
|
||||
service_level: function(frm) {
|
||||
frm.fields_dict.support_and_resolution.grid.remove_all();
|
||||
frappe.call({
|
||||
"method": "frappe.client.get",
|
||||
args: {
|
||||
doctype: "Service Level",
|
||||
name: frm.doc.service_level
|
||||
},
|
||||
callback: function(data){
|
||||
for (var i = 0; i < data.message.support_and_resolution.length; i++){
|
||||
frm.add_child("support_and_resolution", data.message.support_and_resolution[i]);
|
||||
}
|
||||
frm.refresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,764 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "Prompt",
|
||||
"beta": 0,
|
||||
"creation": "2018-12-26 21:08:15.448812",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"depends_on": "eval: !doc.default_service_level_agreement",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Customer",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Customer",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval: !doc.customer",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "default_service_level_agreement",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Default Service Level Agreement",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "service_level",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Service Level",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Service Level",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "service_level.holiday_list",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "holiday_list",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Holiday List",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Holiday List",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fetch_from": "service_level.priority",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "priority",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Priority",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "service_level.employee_group",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "employee_group",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee Group",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Employee Group",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"collapsible_depends_on": "",
|
||||
"columns": 0,
|
||||
"depends_on": "eval: !doc.default_service_level_agreement",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "agreement_details_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Agreement Details",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval: !doc.default_service_level_agreement",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "start_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Start Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Active",
|
||||
"depends_on": "eval: !doc.default_service_level_agreement",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "agreement_status",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Agreement Status",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Active\nExpired",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval: !doc.default_contract",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_7",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval: !doc.default_service_level_agreement",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "end_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "End Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "response_and_resolution_time_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Response and Resolution Time",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "service_level.response_time",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "response_time",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Response Time",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "service_level.resolution_time",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "resolution_time",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Resolution Time",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_16",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "service_level.response_time_period",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "response_time_period",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Response Time Period",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "service_level.resolution_time_period",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "resolution_time_period",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Resolution Time Period",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "support_and_resolution_section_break",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Support and Resolution",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "support_and_resolution",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Support and Resolution",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Service Day",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-03-17 22:36:53.576464",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Support",
|
||||
"name": "Service Level Agreement",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "All",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe import _
|
||||
|
||||
class ServiceLevelAgreement(Document):
|
||||
|
||||
def before_insert(self):
|
||||
if self.default_service_level_agreement:
|
||||
doc = frappe.get_list("Service Level Agreement", filters=[{"default_service_level_agreement": "1"}])
|
||||
if doc:
|
||||
frappe.throw(_("A Default Service Level Agreement already exists."))
|
||||
|
||||
def validate(self):
|
||||
if not self.default_service_level_agreement:
|
||||
if not (self.start_date and self.end_date):
|
||||
frappe.throw(_("Enter Start and End Date for the Agreement."))
|
||||
if self.start_date >= self.end_date:
|
||||
frappe.throw(_("Start Date of Agreement can't be greater than or equal to End Date."))
|
||||
|
||||
def check_agreement_status():
|
||||
service_level_agreements = frappe.get_list("Service Level Agreement", filters=[
|
||||
{"agreement_status": "Active"},
|
||||
{"default_service_level_agreement": 0}
|
||||
])
|
||||
service_level_agreements.reverse()
|
||||
for service_level_agreement in service_level_agreements:
|
||||
service_level_agreement = frappe.get_doc("Service Level Agreement", service_level_agreement)
|
||||
if service_level_agreement.end_date < frappe.utils.getdate():
|
||||
service_level_agreement.agreement_status = "Expired"
|
||||
service_level_agreement.save()
|
||||
|
||||
def get_active_service_level_agreement_for(customer):
|
||||
agreement = frappe.get_list("Service Level Agreement",
|
||||
filters=[{"agreement_status": "Active"}],
|
||||
or_filters=[{'customer': customer},{"default_service_level_agreement": "1"}],
|
||||
fields=["name", "service_level", "holiday_list", "priority"],
|
||||
order_by='customer DESC',
|
||||
limit=1)
|
||||
|
||||
return agreement[0] if agreement else None
|
@ -0,0 +1,149 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
from erpnext.support.doctype.service_level.test_service_level import make_service_level
|
||||
|
||||
class TestServiceLevelAgreement(unittest.TestCase):
|
||||
pass
|
||||
|
||||
def make_service_level_agreement():
|
||||
make_service_level()
|
||||
|
||||
# Default Service Level Agreement
|
||||
default_service_level_agreement = frappe.get_doc({
|
||||
"doctype": "Service Level Agreement",
|
||||
"name": "__Test Service Level Agreement",
|
||||
"default_service_level_agreement": 1,
|
||||
"service_level": "__Test Service Level",
|
||||
"holiday_list": "__Test Holiday List",
|
||||
"priority": "Medium",
|
||||
"employee_group": "_Test Employee Group",
|
||||
"start_date": frappe.utils.getdate(),
|
||||
"end_date": frappe.utils.add_to_date(frappe.utils.getdate(), days=100),
|
||||
"response_time": 4,
|
||||
"response_time_period": "Hour",
|
||||
"resolution_time": 6,
|
||||
"resolution_time_period": "Hour",
|
||||
"support_and_resolution": [
|
||||
{
|
||||
"workday": "Monday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Tuesday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Wednesday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Thursday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Friday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Saturday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Sunday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
default_service_level_agreement_exists = frappe.db.exists("Service Level Agreement", "__Test Service Level Agreement")
|
||||
if not default_service_level_agreement_exists:
|
||||
default_service_level_agreement.insert()
|
||||
|
||||
|
||||
customer = frappe.get_doc({
|
||||
"doctype": "Customer",
|
||||
"customer_name": "_Test Customer",
|
||||
"customer_group": "Commercial",
|
||||
"customer_type": "Individual",
|
||||
"territory": "Rest Of The World"
|
||||
})
|
||||
if not frappe.db.exists("Customer", "_Test Customer"):
|
||||
customer.insert()
|
||||
else:
|
||||
customer = frappe.get_doc("Customer", "_Test Customer")
|
||||
|
||||
service_level_agreement = frappe.get_doc({
|
||||
"doctype": "Service Level Agreement",
|
||||
"name": "_Test Service Level Agreement",
|
||||
"customer": customer.customer_name,
|
||||
"service_level": "_Test Service Level",
|
||||
"holiday_list": "__Test Holiday List",
|
||||
"priority": "Medium",
|
||||
"employee_group": "_Test Employee Group",
|
||||
"start_date": frappe.utils.getdate(),
|
||||
"end_date": frappe.utils.add_to_date(frappe.utils.getdate(), days=100),
|
||||
"response_time": 2,
|
||||
"response_time_period": "Day",
|
||||
"resolution_time": 3,
|
||||
"resolution_time_period": "Day",
|
||||
"support_and_resolution": [
|
||||
{
|
||||
"workday": "Monday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Tuesday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Wednesday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Thursday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Friday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Saturday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
},
|
||||
{
|
||||
"workday": "Sunday",
|
||||
"start_time": "10:00:00",
|
||||
"end_time": "18:00:00",
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
service_level_agreement_exists = frappe.db.exists("Service Level Agreement", "_Test Service Level Agreement")
|
||||
if not service_level_agreement_exists:
|
||||
service_level_agreement.insert()
|
||||
return service_level_agreement.name
|
||||
else:
|
||||
return service_level_agreement_exists
|
||||
|
||||
def get_service_level_agreement():
|
||||
service_level_agreement = frappe.db.exists("Service Level Agreement", "_Test Service Level Agreement")
|
||||
return service_level_agreement
|
Loading…
x
Reference in New Issue
Block a user