Merge branch 'develop' into sales_analytics_with_order_type_develop
This commit is contained in:
commit
a01d0a5311
@ -49,7 +49,7 @@ The ERPNext code is licensed as GNU General Public License (v3) and the Document
|
|||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
1. [Issue Guidelines](https://github.com/frappe/erpnext/wiki/Issue-Guidelines)
|
1. [Issue Guidelines](https://github.com/frappe/erpnext/wiki/Issue-Guidelines)
|
||||||
1. [Report Security Vulnerabilities](https://erpnext.com/report)
|
1. [Report Security Vulnerabilities](https://erpnext.com/security)
|
||||||
1. [Pull Request Requirements](https://github.com/frappe/erpnext/wiki/Contribution-Guidelines)
|
1. [Pull Request Requirements](https://github.com/frappe/erpnext/wiki/Contribution-Guidelines)
|
||||||
1. [Translations](https://translate.erpnext.com)
|
1. [Translations](https://translate.erpnext.com)
|
||||||
1. [Chart of Accounts](https://charts.erpnext.com)
|
1. [Chart of Accounts](https://charts.erpnext.com)
|
||||||
|
@ -485,7 +485,7 @@ class SalesInvoice(SellingController):
|
|||||||
"""Set against account for debit to account"""
|
"""Set against account for debit to account"""
|
||||||
against_acc = []
|
against_acc = []
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
if d.income_account not in against_acc:
|
if d.income_account and d.income_account not in against_acc:
|
||||||
against_acc.append(d.income_account)
|
against_acc.append(d.income_account)
|
||||||
self.against_income_account = ','.join(against_acc)
|
self.against_income_account = ','.join(against_acc)
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ def get_ordered_to_be_billed_data(args):
|
|||||||
from
|
from
|
||||||
`{parent_tab}`, `{child_tab}`
|
`{parent_tab}`, `{child_tab}`
|
||||||
where
|
where
|
||||||
`{parent_tab}`.name = `{child_tab}`.parent and `{parent_tab}`.docstatus = 1 and `{parent_tab}`.status != 'Closed'
|
`{parent_tab}`.name = `{child_tab}`.parent and `{parent_tab}`.docstatus = 1
|
||||||
|
and `{parent_tab}`.status not in ('Closed', 'Completed')
|
||||||
and `{child_tab}`.amount > 0 and round(`{child_tab}`.billed_amt *
|
and `{child_tab}`.amount > 0 and round(`{child_tab}`.billed_amt *
|
||||||
ifnull(`{parent_tab}`.conversion_rate, 1), {precision}) < `{child_tab}`.base_amount
|
ifnull(`{parent_tab}`.conversion_rate, 1), {precision}) < `{child_tab}`.base_amount
|
||||||
order by
|
order by
|
||||||
|
@ -107,7 +107,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
|
|||||||
if(doc.docstatus == 1) {
|
if(doc.docstatus == 1) {
|
||||||
if(!in_list(["Closed", "Delivered"], doc.status)) {
|
if(!in_list(["Closed", "Delivered"], doc.status)) {
|
||||||
if (this.frm.has_perm("submit")) {
|
if (this.frm.has_perm("submit")) {
|
||||||
if(flt(doc.per_billed, 2) < 100 || doc.per_received < 100) {
|
if(flt(doc.per_billed, 6) < 100 || flt(doc.per_received, 6) < 100) {
|
||||||
if (doc.status != "On Hold") {
|
if (doc.status != "On Hold") {
|
||||||
this.frm.add_custom_button(__('Hold'), () => this.hold_purchase_order(), __("Status"));
|
this.frm.add_custom_button(__('Hold'), () => this.hold_purchase_order(), __("Status"));
|
||||||
} else{
|
} else{
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -557,7 +557,7 @@
|
|||||||
"print_hide": 1
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "1",
|
"default": "0",
|
||||||
"depends_on": "eval:parent.is_subcontracted == 'Yes'",
|
"depends_on": "eval:parent.is_subcontracted == 'Yes'",
|
||||||
"fieldname": "include_exploded_items",
|
"fieldname": "include_exploded_items",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
@ -701,7 +701,7 @@
|
|||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-06-02 06:34:47.495730",
|
"modified": "2019-06-23 20:03:13.818917",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Purchase Order Item",
|
"name": "Purchase Order Item",
|
||||||
@ -712,4 +712,4 @@
|
|||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
|
@ -40,17 +40,6 @@ def get_data():
|
|||||||
"description": _("Tree of financial accounts."),
|
"description": _("Tree of financial accounts."),
|
||||||
"onboard": 1,
|
"onboard": 1,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "doctype",
|
|
||||||
"name": "Journal Entry",
|
|
||||||
"description": _("Accounting journal entries."),
|
|
||||||
"onboard": 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "doctype",
|
|
||||||
"name": "Opening Invoice Creation Tool",
|
|
||||||
"description": _("Create Opening Sales and Purchase Invoices")
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -73,11 +62,6 @@ def get_data():
|
|||||||
"name": "Payment Request",
|
"name": "Payment Request",
|
||||||
"description": _("Payment Request"),
|
"description": _("Payment Request"),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "doctype",
|
|
||||||
"name": "Payment Entry",
|
|
||||||
"description": _("Bank/Cash transactions against party or for internal transfer")
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "doctype",
|
"type": "doctype",
|
||||||
"name": "Payment Term",
|
"name": "Payment Term",
|
||||||
@ -179,6 +163,26 @@ def get_data():
|
|||||||
"name": "Accounting Dimension",
|
"name": "Accounting Dimension",
|
||||||
"description": _("Setup custom dimensions for accounting")
|
"description": _("Setup custom dimensions for accounting")
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "doctype",
|
||||||
|
"name": "Opening Invoice Creation Tool",
|
||||||
|
"description": _("Create Opening Sales and Purchase Invoices")
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Accounting Entries"),
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "doctype",
|
||||||
|
"name": "Payment Entry",
|
||||||
|
"description": _("Bank/Cash transactions against party or for internal transfer")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "doctype",
|
||||||
|
"name": "Journal Entry",
|
||||||
|
"description": _("Accounting journal entries.")
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -18,6 +18,11 @@ def get_data():
|
|||||||
"onboard": 1,
|
"onboard": 1,
|
||||||
"dependencies": ["Employee"]
|
"dependencies": ["Employee"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "doctype",
|
||||||
|
"name": "Employee Group",
|
||||||
|
"dependencies": ["Employee"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "doctype",
|
"type": "doctype",
|
||||||
"name": "Attendance",
|
"name": "Attendance",
|
||||||
|
@ -12,6 +12,16 @@ def get_data():
|
|||||||
"description": _("Support queries from customers."),
|
"description": _("Support queries from customers."),
|
||||||
"onboard": 1,
|
"onboard": 1,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "doctype",
|
||||||
|
"name": "Issue Type",
|
||||||
|
"description": _("Issue Type."),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "doctype",
|
||||||
|
"name": "Issue Priority",
|
||||||
|
"description": _("Issue Priority."),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "doctype",
|
"type": "doctype",
|
||||||
"name": "Communication",
|
"name": "Communication",
|
||||||
@ -38,11 +48,6 @@ def get_data():
|
|||||||
{
|
{
|
||||||
"label": _("Service Level Agreement"),
|
"label": _("Service Level Agreement"),
|
||||||
"items": [
|
"items": [
|
||||||
{
|
|
||||||
"type": "doctype",
|
|
||||||
"name": "Employee Group",
|
|
||||||
"description": _("Support Team."),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "doctype",
|
"type": "doctype",
|
||||||
"name": "Service Level",
|
"name": "Service Level",
|
||||||
|
@ -778,7 +778,12 @@ class AccountsController(TransactionBase):
|
|||||||
count += 1
|
count += 1
|
||||||
item.qty = group_item_qty[item.item_code]
|
item.qty = group_item_qty[item.item_code]
|
||||||
item.amount = group_item_amount[item.item_code]
|
item.amount = group_item_amount[item.item_code]
|
||||||
item.rate = flt(flt(item.amount) / flt(item.qty), item.precision("rate"))
|
|
||||||
|
if item.qty:
|
||||||
|
item.rate = flt(flt(item.amount) / flt(item.qty), item.precision("rate"))
|
||||||
|
else:
|
||||||
|
item.rate = 0
|
||||||
|
|
||||||
item.idx = count
|
item.idx = count
|
||||||
del group_item_qty[item.item_code]
|
del group_item_qty[item.item_code]
|
||||||
else:
|
else:
|
||||||
|
@ -428,8 +428,9 @@ class BuyingController(StockController):
|
|||||||
elif not flt(d.rejected_qty):
|
elif not flt(d.rejected_qty):
|
||||||
d.rejected_qty = flt(d.received_qty) - flt(d.qty)
|
d.rejected_qty = flt(d.received_qty) - flt(d.qty)
|
||||||
|
|
||||||
|
val = flt(d.qty) + flt(d.rejected_qty)
|
||||||
# Check Received Qty = Accepted Qty + Rejected Qty
|
# Check Received Qty = Accepted Qty + Rejected Qty
|
||||||
if ((flt(d.qty) + flt(d.rejected_qty)) != flt(d.received_qty)):
|
if (flt(val, d.precision("received_qty")) != flt(d.received_qty, d.precision("received_qty"))):
|
||||||
frappe.throw(_("Accepted + Rejected Qty must be equal to Received quantity for Item {0}").format(d.item_code))
|
frappe.throw(_("Accepted + Rejected Qty must be equal to Received quantity for Item {0}").format(d.item_code))
|
||||||
|
|
||||||
def validate_negative_quantity(self, item_row, field_list):
|
def validate_negative_quantity(self, item_row, field_list):
|
||||||
|
@ -27,7 +27,7 @@ status_map = {
|
|||||||
],
|
],
|
||||||
"Quotation": [
|
"Quotation": [
|
||||||
["Draft", None],
|
["Draft", None],
|
||||||
["Submitted", "eval:self.docstatus==1"],
|
["Open", "eval:self.docstatus==1"],
|
||||||
["Lost", "eval:self.status=='Lost'"],
|
["Lost", "eval:self.status=='Lost'"],
|
||||||
["Ordered", "has_sales_order"],
|
["Ordered", "has_sales_order"],
|
||||||
["Cancelled", "eval:self.docstatus==2"],
|
["Cancelled", "eval:self.docstatus==2"],
|
||||||
|
@ -22,7 +22,16 @@ def verify_request():
|
|||||||
frappe.set_user(woocommerce_settings.creation_user)
|
frappe.set_user(woocommerce_settings.creation_user)
|
||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
@frappe.whitelist(allow_guest=True)
|
||||||
def order():
|
def order(*args, **kwargs):
|
||||||
|
try:
|
||||||
|
_order(*args, **kwargs)
|
||||||
|
except Exception:
|
||||||
|
error_message = frappe.get_traceback()+"\n\n Request Data: \n"+json.loads(frappe.request.data).__str__()
|
||||||
|
frappe.log_error(error_message, "WooCommerce Error")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def _order(*args, **kwargs):
|
||||||
woocommerce_settings = frappe.get_doc("Woocommerce Settings")
|
woocommerce_settings = frappe.get_doc("Woocommerce Settings")
|
||||||
if frappe.flags.woocomm_test_order_data:
|
if frappe.flags.woocomm_test_order_data:
|
||||||
fd = frappe.flags.woocomm_test_order_data
|
fd = frappe.flags.woocomm_test_order_data
|
||||||
|
@ -46,7 +46,7 @@ update_and_get_user_progress = "erpnext.utilities.user_progress_utils.update_def
|
|||||||
on_session_creation = "erpnext.shopping_cart.utils.set_cart_count"
|
on_session_creation = "erpnext.shopping_cart.utils.set_cart_count"
|
||||||
on_logout = "erpnext.shopping_cart.utils.clear_cart_count"
|
on_logout = "erpnext.shopping_cart.utils.clear_cart_count"
|
||||||
|
|
||||||
treeviews = ['Account', 'Cost Center', 'Warehouse', 'Item Group', 'Customer Group', 'Sales Person', 'Territory', 'Assessment Group']
|
treeviews = ['Account', 'Cost Center', 'Warehouse', 'Item Group', 'Customer Group', 'Sales Person', 'Territory', 'Assessment Group', 'Department']
|
||||||
|
|
||||||
# website
|
# website
|
||||||
update_website_context = ["erpnext.shopping_cart.utils.update_website_context", "erpnext.education.doctype.education_settings.education_settings.update_website_context"]
|
update_website_context = ["erpnext.shopping_cart.utils.update_website_context", "erpnext.education.doctype.education_settings.education_settings.update_website_context"]
|
||||||
@ -242,7 +242,8 @@ scheduler_events = {
|
|||||||
"erpnext.accounts.doctype.gl_entry.gl_entry.rename_gle_sle_docs",
|
"erpnext.accounts.doctype.gl_entry.gl_entry.rename_gle_sle_docs",
|
||||||
"erpnext.projects.doctype.project.project.hourly_reminder",
|
"erpnext.projects.doctype.project.project.hourly_reminder",
|
||||||
"erpnext.projects.doctype.project.project.collect_project_status",
|
"erpnext.projects.doctype.project.project.collect_project_status",
|
||||||
"erpnext.hr.doctype.shift_type.shift_type.process_auto_attendance_for_all_shifts"
|
"erpnext.hr.doctype.shift_type.shift_type.process_auto_attendance_for_all_shifts",
|
||||||
|
"erpnext.support.doctype.issue.issue.set_service_level_agreement_variance",
|
||||||
],
|
],
|
||||||
"daily": [
|
"daily": [
|
||||||
"erpnext.stock.reorder_item.reorder_item",
|
"erpnext.stock.reorder_item.reorder_item",
|
||||||
@ -264,7 +265,7 @@ scheduler_events = {
|
|||||||
"erpnext.projects.doctype.project.project.update_project_sales_billing",
|
"erpnext.projects.doctype.project.project.update_project_sales_billing",
|
||||||
"erpnext.projects.doctype.project.project.send_project_status_email_to_users",
|
"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"
|
"erpnext.support.doctype.service_level_agreement.service_level_agreement.check_agreement_status",
|
||||||
],
|
],
|
||||||
"daily_long": [
|
"daily_long": [
|
||||||
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms"
|
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms"
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
frappe.views.calendar["Attendance"] = {
|
frappe.views.calendar["Attendance"] = {
|
||||||
field_map: {
|
field_map: {
|
||||||
"start": "date",
|
"start": "attendance_date",
|
||||||
"end": "date",
|
"end": "attendance_date",
|
||||||
"id": "name",
|
"id": "name",
|
||||||
"docstatus": 1
|
"docstatus": 1
|
||||||
},
|
},
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
frappe.ui.form.on('Department', {
|
frappe.ui.form.on('Department', {
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
// read-only for root department
|
// read-only for root department
|
||||||
if(!frm.doc.parent_department) {
|
if(!frm.doc.parent_department && !frm.is_new()) {
|
||||||
frm.set_read_only();
|
frm.set_read_only();
|
||||||
frm.set_intro(__("This is a root department and cannot be edited."));
|
frm.set_intro(__("This is a root department and cannot be edited."));
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
|
"allow_events_in_timeline": 0,
|
||||||
"allow_guest_to_view": 0,
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
@ -19,6 +20,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "department_name",
|
"fieldname": "department_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -52,6 +54,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "parent_department",
|
"fieldname": "parent_department",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -85,6 +88,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -118,6 +122,7 @@
|
|||||||
"bold": 1,
|
"bold": 1,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "is_group",
|
"fieldname": "is_group",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -150,6 +155,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "disabled",
|
"fieldname": "disabled",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -182,6 +188,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "section_break_4",
|
"fieldname": "section_break_4",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -214,6 +221,7 @@
|
|||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"description": "Days for which Holidays are blocked for this department.",
|
"description": "Days for which Holidays are blocked for this department.",
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "leave_block_list",
|
"fieldname": "leave_block_list",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -246,6 +254,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "leave_section",
|
"fieldname": "leave_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -279,6 +288,7 @@
|
|||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"description": "The first Leave Approver in the list will be set as the default Leave Approver.",
|
"description": "The first Leave Approver in the list will be set as the default Leave Approver.",
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "leave_approvers",
|
"fieldname": "leave_approvers",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -312,6 +322,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "expense_section",
|
"fieldname": "expense_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -345,6 +356,7 @@
|
|||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"description": "The first Expense Approver in the list will be set as the default Expense Approver.",
|
"description": "The first Expense Approver in the list will be set as the default Expense Approver.",
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "expense_approvers",
|
"fieldname": "expense_approvers",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -378,6 +390,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "lft",
|
"fieldname": "lft",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
@ -410,6 +423,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "rgt",
|
"fieldname": "rgt",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
@ -442,6 +456,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "old_parent",
|
"fieldname": "old_parent",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
@ -479,7 +494,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-08-29 06:26:12.995703",
|
"modified": "2019-06-25 18:43:05.550387",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Department",
|
"name": "Department",
|
||||||
@ -543,7 +558,7 @@
|
|||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 1,
|
"quick_entry": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0,
|
"read_only_onload": 0,
|
||||||
"show_name_in_global_search": 1,
|
"show_name_in_global_search": 1,
|
||||||
|
@ -25,5 +25,13 @@ frappe.ui.form.on("Job Applicant", {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frm.set_query("job_title", function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
'status': 'Open'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
@ -400,19 +400,6 @@ def get_leave_balance_on(employee, leave_type, date, allocation_records=None, do
|
|||||||
|
|
||||||
return flt(allocation.total_leaves_allocated) - (flt(leaves_taken) + flt(leaves_encashed))
|
return flt(allocation.total_leaves_allocated) - (flt(leaves_taken) + flt(leaves_encashed))
|
||||||
|
|
||||||
def get_total_allocated_leaves(employee, leave_type, date):
|
|
||||||
filters= {
|
|
||||||
'from_date': ['<=', date],
|
|
||||||
'to_date': ['>=', date],
|
|
||||||
'docstatus': 1,
|
|
||||||
'leave_type': leave_type,
|
|
||||||
'employee': employee
|
|
||||||
}
|
|
||||||
|
|
||||||
leave_allocation_records = frappe.db.get_all('Leave Allocation', filters=filters, fields=['total_leaves_allocated'])
|
|
||||||
|
|
||||||
return flt(leave_allocation_records[0]['total_leaves_allocated']) if leave_allocation_records else flt(0)
|
|
||||||
|
|
||||||
def get_leaves_for_period(employee, leave_type, from_date, to_date, status, docname=None):
|
def get_leaves_for_period(employee, leave_type, from_date, to_date, status, docname=None):
|
||||||
leave_applications = frappe.db.sql("""
|
leave_applications = frappe.db.sql("""
|
||||||
select name, employee, leave_type, from_date, to_date, total_leave_days
|
select name, employee, leave_type, from_date, to_date, total_leave_days
|
||||||
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from erpnext.hr.doctype.leave_application.leave_application \
|
from erpnext.hr.doctype.leave_application.leave_application \
|
||||||
import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period, get_total_allocated_leaves
|
import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period
|
||||||
|
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
@ -35,6 +35,9 @@ def get_data(filters, leave_types):
|
|||||||
allocation_records_based_on_to_date = get_leave_allocation_records(filters.to_date)
|
allocation_records_based_on_to_date = get_leave_allocation_records(filters.to_date)
|
||||||
allocation_records_based_on_from_date = get_leave_allocation_records(filters.from_date)
|
allocation_records_based_on_from_date = get_leave_allocation_records(filters.from_date)
|
||||||
|
|
||||||
|
if filters.to_date <= filters.from_date:
|
||||||
|
frappe.throw(_("From date can not be greater than than To date"))
|
||||||
|
|
||||||
active_employees = frappe.get_all("Employee",
|
active_employees = frappe.get_all("Employee",
|
||||||
filters = { "status": "Active", "company": filters.company},
|
filters = { "status": "Active", "company": filters.company},
|
||||||
fields = ["name", "employee_name", "department", "user_id"])
|
fields = ["name", "employee_name", "department", "user_id"])
|
||||||
@ -51,7 +54,8 @@ def get_data(filters, leave_types):
|
|||||||
filters.from_date, filters.to_date)
|
filters.from_date, filters.to_date)
|
||||||
|
|
||||||
# opening balance
|
# opening balance
|
||||||
opening = get_total_allocated_leaves(employee.name, leave_type, filters.to_date)
|
opening = get_leave_balance_on(employee.name, leave_type, filters.from_date,
|
||||||
|
allocation_records_based_on_to_date.get(employee.name, frappe._dict()))
|
||||||
|
|
||||||
# closing balance
|
# closing balance
|
||||||
closing = get_leave_balance_on(employee.name, leave_type, filters.to_date,
|
closing = get_leave_balance_on(employee.name, leave_type, filters.to_date,
|
||||||
|
@ -383,10 +383,7 @@ class BOM(WebsiteGenerator):
|
|||||||
|
|
||||||
def check_recursion(self, bom_list=[]):
|
def check_recursion(self, bom_list=[]):
|
||||||
""" Check whether recursion occurs in any bom"""
|
""" Check whether recursion occurs in any bom"""
|
||||||
|
bom_list = self.traverse_tree()
|
||||||
if not bom_list:
|
|
||||||
bom_list = self.traverse_tree()
|
|
||||||
|
|
||||||
bom_nos = frappe.get_all('BOM Item', fields=["bom_no"],
|
bom_nos = frappe.get_all('BOM Item', fields=["bom_no"],
|
||||||
filters={'parent': ('in', bom_list), 'parenttype': 'BOM'})
|
filters={'parent': ('in', bom_list), 'parenttype': 'BOM'})
|
||||||
|
|
||||||
@ -402,7 +399,7 @@ class BOM(WebsiteGenerator):
|
|||||||
raise_exception = True
|
raise_exception = True
|
||||||
|
|
||||||
if raise_exception:
|
if raise_exception:
|
||||||
frappe.throw(_("BOM recursion: {0} cannot be parent or child of {2}").format(self.name, self.name))
|
frappe.throw(_("BOM recursion: {0} cannot be parent or child of {1}").format(self.name, self.name))
|
||||||
|
|
||||||
def update_cost_and_exploded_items(self, bom_list=[]):
|
def update_cost_and_exploded_items(self, bom_list=[]):
|
||||||
bom_list = self.traverse_tree(bom_list)
|
bom_list = self.traverse_tree(bom_list)
|
||||||
@ -415,8 +412,8 @@ class BOM(WebsiteGenerator):
|
|||||||
|
|
||||||
def traverse_tree(self, bom_list=None):
|
def traverse_tree(self, bom_list=None):
|
||||||
def _get_children(bom_no):
|
def _get_children(bom_no):
|
||||||
return [cstr(d[0]) for d in frappe.db.sql("""select bom_no from `tabBOM Item`
|
return frappe.db.sql_list("""select bom_no from `tabBOM Item`
|
||||||
where parent = %s and ifnull(bom_no, '') != '' and parenttype='BOM'""", bom_no)]
|
where parent = %s and ifnull(bom_no, '') != '' and parenttype='BOM'""", bom_no)
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
if not bom_list:
|
if not bom_list:
|
||||||
|
@ -90,7 +90,7 @@ class TestBOM(unittest.TestCase):
|
|||||||
self.assertEqual(bom.base_total_cost, 486000)
|
self.assertEqual(bom.base_total_cost, 486000)
|
||||||
|
|
||||||
def test_bom_cost_multi_uom_multi_currency_based_on_price_list(self):
|
def test_bom_cost_multi_uom_multi_currency_based_on_price_list(self):
|
||||||
frappe.db.set_value("Price List", "_Test Price List", "price_not_uom_dependant", 1)
|
frappe.db.set_value("Price List", "_Test Price List", "price_not_uom_dependent", 1)
|
||||||
for item_code, rate in (("_Test Item", 3600), ("_Test Item Home Desktop Manufactured", 3000)):
|
for item_code, rate in (("_Test Item", 3600), ("_Test Item Home Desktop Manufactured", 3000)):
|
||||||
frappe.db.sql("delete from `tabItem Price` where price_list='_Test Price List' and item_code=%s",
|
frappe.db.sql("delete from `tabItem Price` where price_list='_Test Price List' and item_code=%s",
|
||||||
item_code)
|
item_code)
|
||||||
|
@ -604,4 +604,6 @@ execute:frappe.delete_doc("Report", "Inactive Items")
|
|||||||
erpnext.patches.v11_1.delete_scheduling_tool
|
erpnext.patches.v11_1.delete_scheduling_tool
|
||||||
erpnext.patches.v12_0.make_custom_fields_for_bank_remittance #14-06-2019
|
erpnext.patches.v12_0.make_custom_fields_for_bank_remittance #14-06-2019
|
||||||
execute:frappe.delete_doc_if_exists("Page", "support-analytics")
|
execute:frappe.delete_doc_if_exists("Page", "support-analytics")
|
||||||
erpnext.patches.v12_0.make_item_manufacturer
|
erpnext.patches.v12_0.make_item_manufacturer
|
||||||
|
erpnext.patches.v12_0.set_quotation_status
|
||||||
|
erpnext.patches.v12_0.set_priority_for_support
|
||||||
|
78
erpnext/patches/v12_0/set_priority_for_support.py
Normal file
78
erpnext/patches/v12_0/set_priority_for_support.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doc("support", "doctype", "issue_priority")
|
||||||
|
frappe.reload_doc("support", "doctype", "service_level_priority")
|
||||||
|
|
||||||
|
set_issue_priority()
|
||||||
|
set_priority_for_issue()
|
||||||
|
set_priorities_service_level()
|
||||||
|
set_priorities_service_level_agreement()
|
||||||
|
|
||||||
|
def set_issue_priority():
|
||||||
|
# Adds priority from issue to Issue Priority DocType as Priority is a new DocType.
|
||||||
|
for priority in frappe.get_meta("Issue").get_field("priority").options.split("\n"):
|
||||||
|
if priority and not frappe.db.exists("Issue Priority", priority):
|
||||||
|
frappe.get_doc({
|
||||||
|
"doctype": "Issue Priority",
|
||||||
|
"name": priority
|
||||||
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
def set_priority_for_issue():
|
||||||
|
# Sets priority for Issues as Select field is changed to Link field.
|
||||||
|
issue_priority = frappe.get_list("Issue", fields=["name", "priority"])
|
||||||
|
frappe.reload_doc("support", "doctype", "issue")
|
||||||
|
|
||||||
|
for issue in issue_priority:
|
||||||
|
frappe.db.set_value("Issue", issue.name, "priority", issue.priority)
|
||||||
|
|
||||||
|
def set_priorities_service_level():
|
||||||
|
# Migrates "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period" to Child Table
|
||||||
|
# as a Service Level can have multiple priorities
|
||||||
|
try:
|
||||||
|
service_level_priorities = frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"])
|
||||||
|
|
||||||
|
frappe.reload_doc("support", "doctype", "service_level")
|
||||||
|
|
||||||
|
for service_level in service_level_priorities:
|
||||||
|
if service_level:
|
||||||
|
doc = frappe.get_doc("Service Level", service_level.name)
|
||||||
|
doc.append("priorities", {
|
||||||
|
"priority": service_level.priority,
|
||||||
|
"default_priority": 1,
|
||||||
|
"response_time": service_level.response_time,
|
||||||
|
"response_time_period": service_level.response_time_period,
|
||||||
|
"resolution_time": service_level.resolution_time,
|
||||||
|
"resolution_time_period": service_level.resolution_time_period
|
||||||
|
})
|
||||||
|
doc.save(ignore_permissions=True)
|
||||||
|
except frappe.db.TableMissingError:
|
||||||
|
frappe.reload_doc("support", "doctype", "service_level")
|
||||||
|
|
||||||
|
def set_priorities_service_level_agreement():
|
||||||
|
# Migrates "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period" to Child Table
|
||||||
|
# as a Service Level Agreement can have multiple priorities
|
||||||
|
try:
|
||||||
|
service_level_agreement_priorities = frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"])
|
||||||
|
|
||||||
|
frappe.reload_doc("support", "doctype", "service_level_agreement")
|
||||||
|
|
||||||
|
for service_level_agreement in service_level_agreement_priorities:
|
||||||
|
if service_level_agreement:
|
||||||
|
doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name)
|
||||||
|
|
||||||
|
if doc.customer:
|
||||||
|
doc.entity_type = "Customer"
|
||||||
|
doc.entity = doc.customer
|
||||||
|
|
||||||
|
doc.append("priorities", {
|
||||||
|
"priority": service_level_agreement.priority,
|
||||||
|
"default_priority": 1,
|
||||||
|
"response_time": service_level_agreement.response_time,
|
||||||
|
"response_time_period": service_level_agreement.response_time_period,
|
||||||
|
"resolution_time": service_level_agreement.resolution_time,
|
||||||
|
"resolution_time_period": service_level_agreement.resolution_time_period
|
||||||
|
})
|
||||||
|
doc.save(ignore_permissions=True)
|
||||||
|
except frappe.db.TableMissingError:
|
||||||
|
frappe.reload_doc("support", "doctype", "service_level_agreement")
|
7
erpnext/patches/v12_0/set_quotation_status.py
Normal file
7
erpnext/patches/v12_0/set_quotation_status.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
|
||||||
|
frappe.db.sql(""" UPDATE `tabQuotation` set status = 'Open'
|
||||||
|
where docstatus = 1 and status = 'Submitted' """)
|
@ -38,7 +38,8 @@ $.extend(frappe.create_routes, {
|
|||||||
"Item Group": "Tree/Item Group",
|
"Item Group": "Tree/Item Group",
|
||||||
"Sales Person": "Tree/Sales Person",
|
"Sales Person": "Tree/Sales Person",
|
||||||
"Account": "Tree/Account",
|
"Account": "Tree/Account",
|
||||||
"Cost Center": "Tree/Cost Center"
|
"Cost Center": "Tree/Cost Center",
|
||||||
|
"Department": "Tree/Department",
|
||||||
});
|
});
|
||||||
|
|
||||||
// preferred modules for breadcrumbs
|
// preferred modules for breadcrumbs
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2,11 +2,11 @@ frappe.listview_settings['Quotation'] = {
|
|||||||
add_fields: ["customer_name", "base_grand_total", "status",
|
add_fields: ["customer_name", "base_grand_total", "status",
|
||||||
"company", "currency", 'valid_till'],
|
"company", "currency", 'valid_till'],
|
||||||
get_indicator: function(doc) {
|
get_indicator: function(doc) {
|
||||||
if(doc.status==="Submitted") {
|
if(doc.status==="Open") {
|
||||||
if (doc.valid_till && doc.valid_till < frappe.datetime.nowdate()) {
|
if (doc.valid_till && doc.valid_till < frappe.datetime.nowdate()) {
|
||||||
return [__("Expired"), "darkgrey", "valid_till,<," + frappe.datetime.nowdate()];
|
return [__("Expired"), "darkgrey", "valid_till,<," + frappe.datetime.nowdate()];
|
||||||
} else {
|
} else {
|
||||||
return [__("Submitted"), "blue", "status,=,Submitted"];
|
return [__("Open"), "orange", "status,=,Open"];
|
||||||
}
|
}
|
||||||
} else if(doc.status==="Ordered") {
|
} else if(doc.status==="Ordered") {
|
||||||
return [__("Ordered"), "green", "status,=,Ordered"];
|
return [__("Ordered"), "green", "status,=,Ordered"];
|
||||||
|
@ -34,7 +34,7 @@ frappe.ui.form.on("Sales Order", {
|
|||||||
},
|
},
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
if(frm.doc.docstatus === 1 && frm.doc.status !== 'Closed'
|
if(frm.doc.docstatus === 1 && frm.doc.status !== 'Closed'
|
||||||
&& flt(frm.doc.per_delivered) < 100 && flt(frm.doc.per_billed) < 100) {
|
&& flt(frm.doc.per_delivered, 6) < 100 && flt(frm.doc.per_billed, 6) < 100) {
|
||||||
frm.add_custom_button(__('Update Items'), () => {
|
frm.add_custom_button(__('Update Items'), () => {
|
||||||
erpnext.utils.update_child_items({
|
erpnext.utils.update_child_items({
|
||||||
frm: frm,
|
frm: frm,
|
||||||
|
@ -90,70 +90,31 @@ erpnext.SalesFunnel = class SalesFunnel {
|
|||||||
|
|
||||||
get_data(btn) {
|
get_data(btn) {
|
||||||
var me = this;
|
var me = this;
|
||||||
if (me.options.chart == 'sales_funnel'){
|
const method_map = {
|
||||||
frappe.call({
|
"sales_funnel": "erpnext.selling.page.sales_funnel.sales_funnel.get_funnel_data",
|
||||||
method: "erpnext.selling.page.sales_funnel.sales_funnel.get_funnel_data",
|
"opp_by_lead_source": "erpnext.selling.page.sales_funnel.sales_funnel.get_opp_by_lead_source",
|
||||||
args: {
|
"sales_pipeline": "erpnext.selling.page.sales_funnel.sales_funnel.get_pipeline_data"
|
||||||
from_date: this.options.from_date,
|
};
|
||||||
to_date: this.options.to_date,
|
frappe.call({
|
||||||
company: this.company
|
method: method_map[this.options.chart],
|
||||||
},
|
args: {
|
||||||
btn: btn,
|
from_date: this.options.from_date,
|
||||||
callback: function(r) {
|
to_date: this.options.to_date,
|
||||||
if(!r.exc) {
|
company: this.company
|
||||||
me.options.data = r.message;
|
},
|
||||||
if (me.options.data=='empty') {
|
btn: btn,
|
||||||
const $parent = me.elements.funnel_wrapper;
|
callback: function(r) {
|
||||||
$parent.html(__('No data for this period'));
|
if(!r.exc) {
|
||||||
} else {
|
me.options.data = r.message;
|
||||||
me.render_funnel();
|
if (me.options.data=='empty') {
|
||||||
}
|
const $parent = me.elements.funnel_wrapper;
|
||||||
|
$parent.html(__('No data for this period'));
|
||||||
|
} else {
|
||||||
|
me.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
} else if (me.options.chart == 'opp_by_lead_source'){
|
});
|
||||||
frappe.call({
|
|
||||||
method: "erpnext.selling.page.sales_funnel.sales_funnel.get_opp_by_lead_source",
|
|
||||||
args: {
|
|
||||||
from_date: this.options.from_date,
|
|
||||||
to_date: this.options.to_date,
|
|
||||||
company: this.company
|
|
||||||
},
|
|
||||||
btn: btn,
|
|
||||||
callback: function(r) {
|
|
||||||
if(!r.exc) {
|
|
||||||
me.options.data = r.message;
|
|
||||||
if (me.options.data=='empty') {
|
|
||||||
const $parent = me.elements.funnel_wrapper;
|
|
||||||
$parent.html(__('No data for this period'));
|
|
||||||
} else {
|
|
||||||
me.render_opp_by_lead_source();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (me.options.chart == 'sales_pipeline'){
|
|
||||||
frappe.call({
|
|
||||||
method: "erpnext.selling.page.sales_funnel.sales_funnel.get_pipeline_data",
|
|
||||||
args: {
|
|
||||||
from_date: this.options.from_date,
|
|
||||||
to_date: this.options.to_date,
|
|
||||||
company: this.company
|
|
||||||
},
|
|
||||||
btn: btn,
|
|
||||||
callback: function(r) {
|
|
||||||
if(!r.exc) {
|
|
||||||
me.options.data = r.message;
|
|
||||||
if (me.options.data=='empty') {
|
|
||||||
const $parent = me.elements.funnel_wrapper;
|
|
||||||
$parent.html(__('No data for this period'));
|
|
||||||
} else {
|
|
||||||
me.render_pipeline();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -161,9 +122,9 @@ erpnext.SalesFunnel = class SalesFunnel {
|
|||||||
if (me.options.chart == 'sales_funnel'){
|
if (me.options.chart == 'sales_funnel'){
|
||||||
me.render_funnel();
|
me.render_funnel();
|
||||||
} else if (me.options.chart == 'opp_by_lead_source'){
|
} else if (me.options.chart == 'opp_by_lead_source'){
|
||||||
me.render_opp_by_lead_source();
|
me.render_chart("Sales Opportunities by Source");
|
||||||
} else if (me.options.chart == 'sales_pipeline'){
|
} else if (me.options.chart == 'sales_pipeline'){
|
||||||
me.render_pipeline();
|
me.render_chart("Sales Pipeline by Stage");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,15 +231,15 @@ erpnext.SalesFunnel = class SalesFunnel {
|
|||||||
context.fillText(__(title), width + 20, y_mid);
|
context.fillText(__(title), width + 20, y_mid);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_opp_by_lead_source() {
|
render_chart(title) {
|
||||||
let me = this;
|
let me = this;
|
||||||
let currency = frappe.defaults.get_default("currency");
|
let currency = frappe.defaults.get_default("currency");
|
||||||
|
|
||||||
let chart_data = me.options.data ? me.options.data : null;
|
let chart_data = me.options.data ? me.options.data : null;
|
||||||
|
|
||||||
const parent = me.elements.funnel_wrapper[0];
|
const parent = me.elements.funnel_wrapper[0];
|
||||||
this.chart = new Chart(parent, {
|
this.chart = new frappe.Chart(parent, {
|
||||||
title: __("Sales Opportunities by Source"),
|
title: title,
|
||||||
height: 400,
|
height: 400,
|
||||||
data: chart_data,
|
data: chart_data,
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
@ -290,23 +251,4 @@ erpnext.SalesFunnel = class SalesFunnel {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render_pipeline() {
|
|
||||||
let me = this;
|
|
||||||
let currency = frappe.defaults.get_default("currency");
|
|
||||||
|
|
||||||
let chart_data = me.options.data ? me.options.data : null;
|
|
||||||
|
|
||||||
const parent = me.elements.funnel_wrapper[0];
|
|
||||||
this.chart = new Chart(parent, {
|
|
||||||
title: __("Sales Pipeline by Stage"),
|
|
||||||
height: 400,
|
|
||||||
data: chart_data,
|
|
||||||
type: 'bar',
|
|
||||||
tooltipOptions: {
|
|
||||||
formatTooltipY: d => format_currency(d, currency),
|
|
||||||
},
|
|
||||||
colors: ['light-green', 'green']
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@ from frappe import _
|
|||||||
|
|
||||||
from frappe.utils.nestedset import NestedSet
|
from frappe.utils.nestedset import NestedSet
|
||||||
class CustomerGroup(NestedSet):
|
class CustomerGroup(NestedSet):
|
||||||
nsm_parent_field = 'parent_customer_group';
|
nsm_parent_field = 'parent_customer_group'
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
self.validate_name_with_customer()
|
self.validate_name_with_customer()
|
||||||
|
@ -173,6 +173,11 @@ def install(country=None):
|
|||||||
{"attribute_value": _("White"), "abbr": "WHI"}
|
{"attribute_value": _("White"), "abbr": "WHI"}
|
||||||
]},
|
]},
|
||||||
|
|
||||||
|
# Issue Priority
|
||||||
|
{'doctype': 'Issue Priority', 'name': _('Low')},
|
||||||
|
{'doctype': 'Issue Priority', 'name': _('Medium')},
|
||||||
|
{'doctype': 'Issue Priority', 'name': _('High')},
|
||||||
|
|
||||||
#Job Applicant Source
|
#Job Applicant Source
|
||||||
{'doctype': 'Job Applicant Source', 'source_name': _('Website Listing')},
|
{'doctype': 'Job Applicant Source', 'source_name': _('Website Listing')},
|
||||||
{'doctype': 'Job Applicant Source', 'source_name': _('Walk In')},
|
{'doctype': 'Job Applicant Source', 'source_name': _('Walk In')},
|
||||||
|
@ -419,6 +419,8 @@ def get_returned_qty_map(delivery_note):
|
|||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_sales_invoice(source_name, target_doc=None):
|
def make_sales_invoice(source_name, target_doc=None):
|
||||||
doc = frappe.get_doc('Delivery Note', source_name)
|
doc = frappe.get_doc('Delivery Note', source_name)
|
||||||
|
|
||||||
|
to_make_invoice_qty_map = {}
|
||||||
returned_qty_map = get_returned_qty_map(source_name)
|
returned_qty_map = get_returned_qty_map(source_name)
|
||||||
invoiced_qty_map = get_invoiced_qty_map(source_name)
|
invoiced_qty_map = get_invoiced_qty_map(source_name)
|
||||||
|
|
||||||
@ -439,8 +441,7 @@ def make_sales_invoice(source_name, target_doc=None):
|
|||||||
target.update(get_fetch_values("Sales Invoice", 'company_address', target.company_address))
|
target.update(get_fetch_values("Sales Invoice", 'company_address', target.company_address))
|
||||||
|
|
||||||
def update_item(source_doc, target_doc, source_parent):
|
def update_item(source_doc, target_doc, source_parent):
|
||||||
target_doc.qty, returned_qty = get_pending_qty(source_doc)
|
target_doc.qty = to_make_invoice_qty_map[source_doc.name]
|
||||||
returned_qty_map[source_doc.item_code] = returned_qty
|
|
||||||
|
|
||||||
if source_doc.serial_no and source_parent.per_billed > 0:
|
if source_doc.serial_no and source_parent.per_billed > 0:
|
||||||
target_doc.serial_no = get_delivery_note_serial_no(source_doc.item_code,
|
target_doc.serial_no = get_delivery_note_serial_no(source_doc.item_code,
|
||||||
@ -448,7 +449,12 @@ def make_sales_invoice(source_name, target_doc=None):
|
|||||||
|
|
||||||
def get_pending_qty(item_row):
|
def get_pending_qty(item_row):
|
||||||
pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0)
|
pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0)
|
||||||
returned_qty = flt(returned_qty_map.get(item_row.item_code, 0))
|
|
||||||
|
returned_qty = 0
|
||||||
|
if returned_qty_map.get(item_row.item_code, 0) > 0:
|
||||||
|
returned_qty = flt(returned_qty_map.get(item_row.item_code, 0))
|
||||||
|
returned_qty_map[item_row.item_code] -= pending_qty
|
||||||
|
|
||||||
if returned_qty:
|
if returned_qty:
|
||||||
if returned_qty >= pending_qty:
|
if returned_qty >= pending_qty:
|
||||||
pending_qty = 0
|
pending_qty = 0
|
||||||
@ -456,7 +462,10 @@ def make_sales_invoice(source_name, target_doc=None):
|
|||||||
else:
|
else:
|
||||||
pending_qty -= returned_qty
|
pending_qty -= returned_qty
|
||||||
returned_qty = 0
|
returned_qty = 0
|
||||||
return pending_qty, returned_qty
|
|
||||||
|
to_make_invoice_qty_map[item_row.name] = pending_qty
|
||||||
|
|
||||||
|
return pending_qty
|
||||||
|
|
||||||
doc = get_mapped_doc("Delivery Note", source_name, {
|
doc = get_mapped_doc("Delivery Note", source_name, {
|
||||||
"Delivery Note": {
|
"Delivery Note": {
|
||||||
@ -476,7 +485,7 @@ def make_sales_invoice(source_name, target_doc=None):
|
|||||||
"cost_center": "cost_center"
|
"cost_center": "cost_center"
|
||||||
},
|
},
|
||||||
"postprocess": update_item,
|
"postprocess": update_item,
|
||||||
"filter": lambda d: get_pending_qty(d)[0] <= 0 if not doc.get("is_return") else get_pending_qty(d)[0] > 0
|
"filter": lambda d: get_pending_qty(d) <= 0 if not doc.get("is_return") else get_pending_qty(d) > 0
|
||||||
},
|
},
|
||||||
"Sales Taxes and Charges": {
|
"Sales Taxes and Charges": {
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
|
"allow_events_in_timeline": 0,
|
||||||
"allow_guest_to_view": 0,
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
@ -22,6 +23,7 @@
|
|||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"default": "1",
|
"default": "1",
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "enabled",
|
"fieldname": "enabled",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -53,6 +55,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "sb_1",
|
"fieldname": "sb_1",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -83,6 +86,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "price_list_name",
|
"fieldname": "price_list_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -116,6 +120,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "currency",
|
"fieldname": "currency",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -148,6 +153,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "buying",
|
"fieldname": "buying",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -179,6 +185,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "selling",
|
"fieldname": "selling",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -210,7 +217,8 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "price_not_uom_dependant",
|
"fetch_if_empty": 0,
|
||||||
|
"fieldname": "price_not_uom_dependent",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
@ -219,7 +227,7 @@
|
|||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Price Not UOM Dependant",
|
"label": "Price Not UOM Dependent",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -242,6 +250,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "column_break_3",
|
"fieldname": "column_break_3",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -272,6 +281,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "countries",
|
"fieldname": "countries",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -310,7 +320,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 1,
|
"max_attachments": 1,
|
||||||
"modified": "2018-08-29 06:35:16.546274",
|
"modified": "2019-06-24 17:16:28.027302",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Price List",
|
"name": "Price List",
|
||||||
|
@ -7,7 +7,7 @@ QUnit.test("test price list with uom dependancy", function(assert) {
|
|||||||
|
|
||||||
() => frappe.set_route('Form', 'Price List', 'Standard Buying'),
|
() => frappe.set_route('Form', 'Price List', 'Standard Buying'),
|
||||||
() => {
|
() => {
|
||||||
cur_frm.set_value('price_not_uom_dependant','1');
|
cur_frm.set_value('price_not_uom_dependent','1');
|
||||||
frappe.timeout(1);
|
frappe.timeout(1);
|
||||||
},
|
},
|
||||||
() => cur_frm.save(),
|
() => cur_frm.save(),
|
||||||
|
@ -352,6 +352,7 @@ def get_auto_serial_nos(serial_no_series, qty):
|
|||||||
|
|
||||||
def auto_make_serial_nos(args):
|
def auto_make_serial_nos(args):
|
||||||
serial_nos = get_serial_nos(args.get('serial_no'))
|
serial_nos = get_serial_nos(args.get('serial_no'))
|
||||||
|
created_numbers = []
|
||||||
for serial_no in serial_nos:
|
for serial_no in serial_nos:
|
||||||
if frappe.db.exists("Serial No", serial_no):
|
if frappe.db.exists("Serial No", serial_no):
|
||||||
sr = frappe.get_doc("Serial No", serial_no)
|
sr = frappe.get_doc("Serial No", serial_no)
|
||||||
@ -366,7 +367,12 @@ def auto_make_serial_nos(args):
|
|||||||
sr.sales_order = None
|
sr.sales_order = None
|
||||||
sr.save(ignore_permissions=True)
|
sr.save(ignore_permissions=True)
|
||||||
elif args.get('actual_qty', 0) > 0:
|
elif args.get('actual_qty', 0) > 0:
|
||||||
make_serial_no(serial_no, args)
|
created_numbers.append(make_serial_no(serial_no, args))
|
||||||
|
|
||||||
|
if len(created_numbers) == 1:
|
||||||
|
frappe.msgprint(_("Serial No {0} created").format(created_numbers[0]))
|
||||||
|
elif len(created_numbers) > 0:
|
||||||
|
frappe.msgprint(_("The following serial numbers were created: <br> {0}").format(', '.join(created_numbers)))
|
||||||
|
|
||||||
def get_item_details(item_code):
|
def get_item_details(item_code):
|
||||||
return frappe.db.sql("""select name, has_batch_no, docstatus,
|
return frappe.db.sql("""select name, has_batch_no, docstatus,
|
||||||
@ -399,7 +405,6 @@ def make_serial_no(serial_no, args):
|
|||||||
sr.warehouse = args.get('warehouse')
|
sr.warehouse = args.get('warehouse')
|
||||||
sr.save()
|
sr.save()
|
||||||
|
|
||||||
frappe.msgprint(_("Serial No {0} created").format(sr.name))
|
|
||||||
return sr.name
|
return sr.name
|
||||||
|
|
||||||
def update_serial_nos_after_submit(controller, parentfield):
|
def update_serial_nos_after_submit(controller, parentfield):
|
||||||
|
@ -376,10 +376,10 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
# validate qty during submit
|
# validate qty during submit
|
||||||
if d.docstatus==1 and d.s_warehouse and not allow_negative_stock and flt(d.actual_qty, d.precision("actual_qty")) < flt(d.transfer_qty, d.precision("actual_qty")):
|
if d.docstatus==1 and d.s_warehouse and not allow_negative_stock and flt(d.actual_qty, d.precision("actual_qty")) < flt(d.transfer_qty, d.precision("actual_qty")):
|
||||||
frappe.throw(_("Row {0}: Qty not available for {4} in warehouse {1} at posting time of the entry ({2} {3})").format(d.idx,
|
frappe.throw(_("Row {0}: Quantity not available for {4} in warehouse {1} at posting time of the entry ({2} {3})").format(d.idx,
|
||||||
frappe.bold(d.s_warehouse), formatdate(self.posting_date),
|
frappe.bold(d.s_warehouse), formatdate(self.posting_date),
|
||||||
format_time(self.posting_time), frappe.bold(d.item_code))
|
format_time(self.posting_time), frappe.bold(d.item_code))
|
||||||
+ '<br><br>' + _("Available qty is {0}, you need {1}").format(frappe.bold(d.actual_qty),
|
+ '<br><br>' + _("Available quantity is {0}, you need {1}").format(frappe.bold(d.actual_qty),
|
||||||
frappe.bold(d.transfer_qty)),
|
frappe.bold(d.transfer_qty)),
|
||||||
NegativeStockError, title=_('Insufficient Stock'))
|
NegativeStockError, title=_('Insufficient Stock'))
|
||||||
|
|
||||||
|
@ -888,12 +888,12 @@ def get_price_list_currency(price_list):
|
|||||||
def get_price_list_uom_dependant(price_list):
|
def get_price_list_uom_dependant(price_list):
|
||||||
if price_list:
|
if price_list:
|
||||||
result = frappe.db.get_value("Price List", {"name": price_list,
|
result = frappe.db.get_value("Price List", {"name": price_list,
|
||||||
"enabled": 1}, ["name", "price_not_uom_dependant"], as_dict=True)
|
"enabled": 1}, ["name", "price_not_uom_dependent"], as_dict=True)
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
throw(_("Price List {0} is disabled or does not exist").format(price_list))
|
throw(_("Price List {0} is disabled or does not exist").format(price_list))
|
||||||
|
|
||||||
return not result.price_not_uom_dependant
|
return not result.price_not_uom_dependent
|
||||||
|
|
||||||
|
|
||||||
def get_price_list_currency_and_exchange_rate(args):
|
def get_price_list_currency_and_exchange_rate(args):
|
||||||
|
@ -60,7 +60,7 @@ frappe.pages['stock-balance'].on_page_load = function(wrapper) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
page.sort_selector.wrapper.css({'margin-right': '15px', 'margin-top': '4px'});
|
// page.sort_selector.wrapper.css({'margin-right': '15px', 'margin-top': '4px'});
|
||||||
|
|
||||||
frappe.require('assets/js/item-dashboard.min.js', function() {
|
frappe.require('assets/js/item-dashboard.min.js', function() {
|
||||||
page.item_dashboard = new erpnext.stock.ItemDashboard({
|
page.item_dashboard = new erpnext.stock.ItemDashboard({
|
||||||
|
@ -56,7 +56,7 @@ def get_columns():
|
|||||||
{"label": _("Voucher Type"), "fieldname": "voucher_type", "width": 110},
|
{"label": _("Voucher Type"), "fieldname": "voucher_type", "width": 110},
|
||||||
{"label": _("Voucher #"), "fieldname": "voucher_no", "fieldtype": "Dynamic Link", "options": "voucher_type", "width": 100},
|
{"label": _("Voucher #"), "fieldname": "voucher_no", "fieldtype": "Dynamic Link", "options": "voucher_type", "width": 100},
|
||||||
{"label": _("Batch"), "fieldname": "batch_no", "fieldtype": "Link", "options": "Batch", "width": 100},
|
{"label": _("Batch"), "fieldname": "batch_no", "fieldtype": "Link", "options": "Batch", "width": 100},
|
||||||
{"label": _("Serial #"), "fieldname": "serial_no", "fieldtype": "Link", "options": "Serial No", "width": 100},
|
{"label": _("Serial #"), "fieldname": "serial_no", "width": 100},
|
||||||
{"label": _("Project"), "fieldname": "project", "fieldtype": "Link", "options": "Project", "width": 100},
|
{"label": _("Project"), "fieldname": "project", "fieldtype": "Link", "options": "Project", "width": 100},
|
||||||
{"label": _("Company"), "fieldname": "company", "fieldtype": "Link", "options": "Company", "width": 110}
|
{"label": _("Company"), "fieldname": "company", "fieldtype": "Link", "options": "Company", "width": 110}
|
||||||
]
|
]
|
||||||
|
@ -1,13 +1,43 @@
|
|||||||
frappe.ui.form.on("Issue", {
|
frappe.ui.form.on("Issue", {
|
||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
frm.email_field = "raised_by";
|
frm.email_field = "raised_by";
|
||||||
|
|
||||||
if (frm.doc.service_level_agreement) {
|
if (frm.doc.service_level_agreement) {
|
||||||
set_time_to_resolve_and_response(frm);
|
frappe.call({
|
||||||
|
method: "erpnext.support.doctype.service_level_agreement.service_level_agreement.get_service_level_agreement_filters",
|
||||||
|
args: {
|
||||||
|
name: frm.doc.service_level_agreement,
|
||||||
|
customer: frm.doc.customer
|
||||||
|
},
|
||||||
|
callback: function (r) {
|
||||||
|
if (r && r.message) {
|
||||||
|
frm.set_query('priority', function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
"name": ["in", r.message.priority],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
frm.set_query('service_level_agreement', function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
"name": ["in", r.message.service_level_agreements],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function (frm) {
|
refresh: function (frm) {
|
||||||
if (frm.doc.status !== "Closed") {
|
|
||||||
|
if (frm.doc.status !== "Closed" && frm.doc.agreement_fulfilled === "Ongoing") {
|
||||||
|
if (frm.doc.service_level_agreement) {
|
||||||
|
set_time_to_resolve_and_response(frm);
|
||||||
|
}
|
||||||
|
|
||||||
frm.add_custom_button(__("Close"), function () {
|
frm.add_custom_button(__("Close"), function () {
|
||||||
frm.set_value("status", "Closed");
|
frm.set_value("status", "Closed");
|
||||||
frm.save();
|
frm.save();
|
||||||
@ -20,6 +50,22 @@ frappe.ui.form.on("Issue", {
|
|||||||
});
|
});
|
||||||
}, __("Make"));
|
}, __("Make"));
|
||||||
} else {
|
} else {
|
||||||
|
if (frm.doc.service_level_agreement) {
|
||||||
|
frm.dashboard.clear_headline();
|
||||||
|
|
||||||
|
let agreement_fulfilled = (frm.doc.agreement_fulfilled == "Fulfilled") ?
|
||||||
|
{"indicator": "green", "msg": "Service Level Agreement has been fulfilled"} :
|
||||||
|
{"indicator": "red", "msg": "Service Level Agreement Failed"};
|
||||||
|
|
||||||
|
frm.dashboard.set_headline_alert(
|
||||||
|
'<div class="row">' +
|
||||||
|
'<div class="col-xs-12">' +
|
||||||
|
'<span class="indicator whitespace-nowrap '+ agreement_fulfilled.indicator +'"><span class="hidden-xs">'+ agreement_fulfilled.msg +'</span></span> ' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
frm.add_custom_button(__("Reopen"), function () {
|
frm.add_custom_button(__("Reopen"), function () {
|
||||||
frm.set_value("status", "Open");
|
frm.set_value("status", "Open");
|
||||||
frm.save();
|
frm.save();
|
||||||
@ -27,6 +73,27 @@ frappe.ui.form.on("Issue", {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
priority: function(frm) {
|
||||||
|
if (frm.doc.service_level_agreement) {
|
||||||
|
frm.call('change_service_level_agreement_and_priority', {
|
||||||
|
"priority": frm.doc.priority,
|
||||||
|
"service_level_agreement": frm.doc.service_level_agreement
|
||||||
|
}).then(() => {
|
||||||
|
frappe.msgprint(__("Issue Priority changed to {0}.", [frm.doc.priority]));
|
||||||
|
frm.refresh();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
service_level_agreement: function(frm) {
|
||||||
|
frm.call('change_service_level_agreement_and_priority', {
|
||||||
|
"service_level_agreement": frm.doc.service_level_agreement
|
||||||
|
}).then(() => {
|
||||||
|
frappe.msgprint(__("Service Level Agreement changed to {0}.", [frm.doc.service_level_agreement]));
|
||||||
|
frm.refresh();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
timeline_refresh: function(frm) {
|
timeline_refresh: function(frm) {
|
||||||
// create button for "Help Article"
|
// create button for "Help Article"
|
||||||
if(frappe.model.can_create('Help Article')) {
|
if(frappe.model.can_create('Help Article')) {
|
||||||
@ -81,36 +148,26 @@ frappe.ui.form.on("Issue", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function set_time_to_resolve_and_response(frm) {
|
function set_time_to_resolve_and_response(frm) {
|
||||||
|
frm.dashboard.clear_headline();
|
||||||
|
|
||||||
const customer = frm.fields_dict['customer'].$wrapper;
|
var time_to_respond = get_time_left(frm.doc.response_by, frm.doc.agreement_fulfilled);
|
||||||
const email_account = frm.fields_dict['email_account'].$wrapper;
|
var time_to_resolve = get_time_left(frm.doc.resolution_by, frm.doc.agreement_fulfilled);
|
||||||
|
|
||||||
const time_to_respond = $(get_time_left_element(__('Time To Respond'), frm.doc.response_by));
|
frm.dashboard.set_headline_alert(
|
||||||
const time_to_resolve = $(get_time_left_element(__('Time To Resolve'), frm.doc.resolution_by));
|
'<div class="row">' +
|
||||||
|
'<div class="col-xs-6">' +
|
||||||
time_to_respond.insertAfter(customer);
|
'<span class="indicator whitespace-nowrap '+ time_to_respond.indicator +'"><span class="hidden-xs">Time to Respond: '+ time_to_respond.diff_display +'</span></span> ' +
|
||||||
time_to_resolve.insertAfter(email_account);
|
'</div>' +
|
||||||
|
'<div class="col-xs-6">' +
|
||||||
|
'<span class="indicator whitespace-nowrap '+ time_to_resolve.indicator +'"><span class="hidden-xs">Time to Resolve: '+ time_to_resolve.diff_display +'</span></span> ' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_time_left_element(label, timestamp) {
|
function get_time_left(timestamp, agreement_fulfilled) {
|
||||||
$('.'+ frappe.scrub(label) +'').remove();
|
|
||||||
return `
|
|
||||||
<div class="frappe-control input-max-width `+ frappe.scrub(label) +`" data-field_name="`+ frappe.scrub(label) +`">
|
|
||||||
<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());
|
const diff = moment(timestamp).diff(moment());
|
||||||
return diff >= 44500 ? moment.duration(diff).humanize() : 0;
|
const diff_display = diff >= 44500 ? moment.duration(diff).humanize() : moment(0, 'seconds').format('HH:mm');
|
||||||
|
let indicator = (diff_display == '00:00' && agreement_fulfilled != "Fulfilled") ? "red" : "green";
|
||||||
|
return {"diff_display": diff_display, "indicator": indicator};
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@ from frappe.utils import now, time_diff_in_hours, now_datetime, getdate, get_wee
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
from frappe.utils.user import is_website_user
|
from frappe.utils.user import is_website_user
|
||||||
from ..service_level_agreement.service_level_agreement import get_active_service_level_agreement_for
|
from erpnext.support.doctype.service_level_agreement.service_level_agreement import get_active_service_level_agreement_for
|
||||||
from erpnext.crm.doctype.opportunity.opportunity import assign_to_user
|
from erpnext.crm.doctype.opportunity.opportunity import assign_to_user
|
||||||
from frappe.email.inbox import link_communication_to_document
|
from frappe.email.inbox import link_communication_to_document
|
||||||
|
|
||||||
@ -63,22 +63,39 @@ class Issue(Document):
|
|||||||
def update_status(self):
|
def update_status(self):
|
||||||
status = frappe.db.get_value("Issue", self.name, "status")
|
status = frappe.db.get_value("Issue", self.name, "status")
|
||||||
if self.status!="Open" and status =="Open" and not self.first_responded_on:
|
if self.status!="Open" and status =="Open" and not self.first_responded_on:
|
||||||
self.first_responded_on = now()
|
self.first_responded_on = frappe.flags.current_time or now_datetime()
|
||||||
|
|
||||||
if self.status=="Closed" and status !="Closed":
|
if self.status=="Closed" and status !="Closed":
|
||||||
self.resolution_date = now()
|
self.resolution_date = frappe.flags.current_time or now_datetime()
|
||||||
self.update_agreement_status()
|
if frappe.db.get_value("Issue", self.name, "agreement_fulfilled") == "Ongoing":
|
||||||
|
set_service_level_agreement_variance(issue=self.name)
|
||||||
|
self.update_agreement_status()
|
||||||
|
|
||||||
if self.status=="Open" and status !="Open":
|
if self.status=="Open" and status !="Open":
|
||||||
# if no date, it should be set as None and not a blank string "", as per mysql strict config
|
# if no date, it should be set as None and not a blank string "", as per mysql strict config
|
||||||
self.resolution_date = None
|
self.resolution_date = None
|
||||||
|
|
||||||
def update_agreement_status(self):
|
def update_agreement_status(self):
|
||||||
current_time = frappe.flags.current_time or now_datetime()
|
if self.service_level_agreement and self.agreement_fulfilled == "Ongoing":
|
||||||
if self.service_level_agreement:
|
if frappe.db.get_value("Issue", self.name, "response_by_variance") < 0 or \
|
||||||
if (round(time_diff_in_hours(self.response_by, current_time), 2) < 0
|
frappe.db.get_value("Issue", self.name, "resolution_by_variance") < 0:
|
||||||
or round(time_diff_in_hours(self.resolution_by, current_time), 2) < 0):
|
|
||||||
self.agreement_status = "Failed"
|
self.agreement_fulfilled = "Failed"
|
||||||
else:
|
else:
|
||||||
self.agreement_status = "Fulfilled"
|
self.agreement_fulfilled = "Fulfilled"
|
||||||
|
|
||||||
|
def update_agreement_fulfilled_on_custom_status(self):
|
||||||
|
"""
|
||||||
|
Update Agreement Fulfilled status using Custom Scripts for Custom Issue Status
|
||||||
|
"""
|
||||||
|
if not self.first_responded_on: # first_responded_on set when first reply is sent to customer
|
||||||
|
self.response_by_variance = round(time_diff_in_hours(self.response_by, now_datetime()), 2)
|
||||||
|
|
||||||
|
if not self.resolution_date: # resolution_date set when issue has been closed
|
||||||
|
self.resolution_by_variance = round(time_diff_in_hours(self.resolution_by, now_datetime()), 2)
|
||||||
|
|
||||||
|
self.agreement_fulfilled = "Fulfilled" if self.response_by_variance > 0 and self.resolution_by_variance > 0 else "Failed"
|
||||||
|
self.save(ignore_permissions=True)
|
||||||
|
|
||||||
def create_communication(self):
|
def create_communication(self):
|
||||||
communication = frappe.new_doc("Communication")
|
communication = frappe.new_doc("Communication")
|
||||||
@ -124,23 +141,41 @@ class Issue(Document):
|
|||||||
def before_insert(self):
|
def before_insert(self):
|
||||||
self.set_response_and_resolution_time()
|
self.set_response_and_resolution_time()
|
||||||
|
|
||||||
def set_response_and_resolution_time(self):
|
def set_response_and_resolution_time(self, priority=None, service_level_agreement=None):
|
||||||
service_level_agreement = get_active_service_level_agreement_for(self.customer)
|
service_level_agreement = get_active_service_level_agreement_for(priority=priority,
|
||||||
if service_level_agreement:
|
customer=self.customer, service_level_agreement=service_level_agreement)
|
||||||
self.service_level_agreement = service_level_agreement.name
|
|
||||||
self.priority = service_level_agreement.priority
|
|
||||||
|
|
||||||
if not self.service_level_agreement: return
|
if not service_level_agreement:
|
||||||
|
if frappe.db.get_value("Issue", self.name, "service_level_agreement"):
|
||||||
|
frappe.throw(_("Couldn't Set Service Level Agreement {0}.".format(self.service_level_agreement)))
|
||||||
|
return
|
||||||
|
|
||||||
service_level = frappe.get_doc("Service Level", service_level_agreement.service_level)
|
if (service_level_agreement.customer and self.customer) and not (service_level_agreement.customer == self.customer):
|
||||||
|
frappe.throw(_("This Service Level Agreement is specific to Customer {0}".format(service_level_agreement.customer)))
|
||||||
|
|
||||||
|
self.service_level_agreement = service_level_agreement.name
|
||||||
|
self.priority = service_level_agreement.default_priority if not priority else priority
|
||||||
|
|
||||||
|
service_level_agreement = frappe.get_doc("Service Level Agreement", service_level_agreement.name)
|
||||||
|
priority = service_level_agreement.get_service_level_agreement_priority(self.priority)
|
||||||
|
priority.update({
|
||||||
|
"support_and_resolution": service_level_agreement.support_and_resolution,
|
||||||
|
"holiday_list": service_level_agreement.holiday_list
|
||||||
|
})
|
||||||
|
|
||||||
if not self.creation:
|
if not self.creation:
|
||||||
self.creation = now_datetime()
|
self.creation = now_datetime()
|
||||||
|
|
||||||
start_date_time = get_datetime(self.creation)
|
start_date_time = get_datetime(self.creation)
|
||||||
|
self.response_by = get_expected_time_for(parameter='response', service_level=priority, start_date_time=start_date_time)
|
||||||
|
self.resolution_by = get_expected_time_for(parameter='resolution', service_level=priority, start_date_time=start_date_time)
|
||||||
|
|
||||||
self.response_by = get_expected_time_for('response', service_level, start_date_time)
|
self.response_by_variance = round(time_diff_in_hours(self.response_by, now_datetime()))
|
||||||
self.resolution_by = get_expected_time_for('resolution', service_level, start_date_time)
|
self.resolution_by_variance = round(time_diff_in_hours(self.resolution_by, now_datetime()))
|
||||||
|
|
||||||
|
def change_service_level_agreement_and_priority(self, priority=None, service_level_agreement=None):
|
||||||
|
self.set_response_and_resolution_time(priority=priority, service_level_agreement=service_level_agreement)
|
||||||
|
self.save(ignore_permissions=True)
|
||||||
|
|
||||||
def get_expected_time_for(parameter, service_level, start_date_time):
|
def get_expected_time_for(parameter, service_level, start_date_time):
|
||||||
current_date_time = start_date_time
|
current_date_time = start_date_time
|
||||||
@ -150,11 +185,11 @@ def get_expected_time_for(parameter, service_level, start_date_time):
|
|||||||
|
|
||||||
# lets assume response time is in days by default
|
# lets assume response time is in days by default
|
||||||
if parameter == 'response':
|
if parameter == 'response':
|
||||||
allotted_days = service_level.response_time
|
allotted_days = service_level.get("response_time")
|
||||||
time_period = service_level.response_time_period
|
time_period = service_level.get("response_time_period")
|
||||||
elif parameter == 'resolution':
|
elif parameter == 'resolution':
|
||||||
allotted_days = service_level.resolution_time
|
allotted_days = service_level.get("resolution_time")
|
||||||
time_period = service_level.resolution_time_period
|
time_period = service_level.get("resolution_time_period")
|
||||||
else:
|
else:
|
||||||
frappe.throw(_("{0} parameter is invalid".format(parameter)))
|
frappe.throw(_("{0} parameter is invalid".format(parameter)))
|
||||||
|
|
||||||
@ -168,20 +203,22 @@ def get_expected_time_for(parameter, service_level, start_date_time):
|
|||||||
expected_time_is_set = 1 if allotted_days == 0 and time_period in ['Day', 'Week'] else 0
|
expected_time_is_set = 1 if allotted_days == 0 and time_period in ['Day', 'Week'] else 0
|
||||||
|
|
||||||
support_days = {}
|
support_days = {}
|
||||||
for service in service_level.support_and_resolution:
|
for service in service_level.get("support_and_resolution"):
|
||||||
support_days[service.workday] = frappe._dict({
|
support_days[service.workday] = frappe._dict({
|
||||||
'start_time': service.start_time,
|
'start_time': service.start_time,
|
||||||
'end_time': service.end_time,
|
'end_time': service.end_time,
|
||||||
})
|
})
|
||||||
|
|
||||||
holidays = get_holidays(service_level.holiday_list)
|
holidays = get_holidays(service_level.get("holiday_list"))
|
||||||
weekdays = get_weekdays()
|
weekdays = get_weekdays()
|
||||||
|
|
||||||
while not expected_time_is_set:
|
while not expected_time_is_set:
|
||||||
current_weekday = weekdays[current_date_time.weekday()]
|
current_weekday = weekdays[current_date_time.weekday()]
|
||||||
|
|
||||||
if not is_holiday(current_date_time, holidays) and current_weekday in support_days:
|
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
|
end_time = support_days[current_weekday].end_time
|
||||||
time_left_today = time_diff_in_hours(end_time, start_time)
|
time_left_today = time_diff_in_hours(end_time, start_time)
|
||||||
|
|
||||||
@ -207,6 +244,28 @@ def get_expected_time_for(parameter, service_level, start_date_time):
|
|||||||
|
|
||||||
return current_date_time
|
return current_date_time
|
||||||
|
|
||||||
|
def set_service_level_agreement_variance(issue=None):
|
||||||
|
current_time = frappe.flags.current_time or now_datetime()
|
||||||
|
|
||||||
|
filters = {"status": "Open", "agreement_fulfilled": "Ongoing"}
|
||||||
|
if issue:
|
||||||
|
filters = {"name": issue}
|
||||||
|
|
||||||
|
for issue in frappe.get_list("Issue", filters=filters):
|
||||||
|
doc = frappe.get_doc("Issue", issue.name)
|
||||||
|
|
||||||
|
if not doc.first_responded_on: # first_responded_on set when first reply is sent to customer
|
||||||
|
variance = round(time_diff_in_hours(doc.response_by, current_time), 2)
|
||||||
|
frappe.db.set_value("Issue", doc.name, "response_by_variance", variance)
|
||||||
|
if variance < 0:
|
||||||
|
frappe.db.set_value("Issue", doc.name, "agreement_fulfilled", "Failed")
|
||||||
|
|
||||||
|
if not doc.resolution_date: # resolution_date set when issue has been closed
|
||||||
|
variance = round(time_diff_in_hours(doc.resolution_by, current_time), 2)
|
||||||
|
frappe.db.set_value("Issue", doc.name, "resolution_by_variance", variance)
|
||||||
|
if variance < 0:
|
||||||
|
frappe.db.set_value("Issue", doc.name, "agreement_fulfilled", "Failed")
|
||||||
|
|
||||||
def get_list_context(context=None):
|
def get_list_context(context=None):
|
||||||
return {
|
return {
|
||||||
"title": _("Issues"),
|
"title": _("Issues"),
|
||||||
@ -244,14 +303,12 @@ def set_multiple_status(names, status):
|
|||||||
for name in names:
|
for name in names:
|
||||||
set_status(name, status)
|
set_status(name, status)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def set_status(name, status):
|
def set_status(name, status):
|
||||||
st = frappe.get_doc("Issue", name)
|
st = frappe.get_doc("Issue", name)
|
||||||
st.status = status
|
st.status = status
|
||||||
st.save()
|
st.save()
|
||||||
|
|
||||||
|
|
||||||
def auto_close_tickets():
|
def auto_close_tickets():
|
||||||
"""Auto-close replied support tickets after 7 days"""
|
"""Auto-close replied support tickets after 7 days"""
|
||||||
auto_close_after_days = frappe.db.get_value("Support Settings", "Support Settings", "close_issue_after_days") or 7
|
auto_close_after_days = frappe.db.get_value("Support Settings", "Support Settings", "close_issue_after_days") or 7
|
||||||
@ -291,6 +348,7 @@ def make_task(source_name, target_doc=None):
|
|||||||
"doctype": "Task"
|
"doctype": "Task"
|
||||||
}
|
}
|
||||||
}, target_doc)
|
}, target_doc)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_issue_from_communication(communication, ignore_communication_links=False):
|
def make_issue_from_communication(communication, ignore_communication_links=False):
|
||||||
""" raise a issue from email """
|
""" raise a issue from email """
|
||||||
@ -307,3 +365,10 @@ def make_issue_from_communication(communication, ignore_communication_links=Fals
|
|||||||
link_communication_to_document(doc, "Issue", issue.name, ignore_communication_links)
|
link_communication_to_document(doc, "Issue", issue.name, ignore_communication_links)
|
||||||
|
|
||||||
return issue.name
|
return issue.name
|
||||||
|
|
||||||
|
def get_time_in_timedelta(time):
|
||||||
|
"""
|
||||||
|
Converts datetime.time(10, 36, 55, 961454) to datetime.timedelta(seconds=38215)
|
||||||
|
"""
|
||||||
|
import datetime
|
||||||
|
return datetime.timedelta(hours=time.hour, minutes=time.minute, seconds=time.second)
|
@ -4,8 +4,8 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
import unittest
|
import unittest
|
||||||
from erpnext.support.doctype.service_level_agreement.test_service_level_agreement import make_service_level_agreement
|
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
|
import datetime
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from frappe.desk.form import assign_to
|
from frappe.desk.form import assign_to
|
||||||
@ -18,56 +18,104 @@ class TestIssue(unittest.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
def test_response_time_and_resolution_time_based_on_different_sla(self):
|
def test_response_time_and_resolution_time_based_on_different_sla(self):
|
||||||
make_service_level_agreement()
|
create_service_level_agreements_for_issues()
|
||||||
|
|
||||||
creation = "2019-03-04 12:00:00"
|
creation = datetime.datetime(2019, 3, 4, 12, 0)
|
||||||
|
|
||||||
# make issue with customer specific SLA
|
# make issue with customer specific SLA
|
||||||
issue = make_issue(creation, '_Test Customer')
|
customer = create_customer("_Test Customer", "__Test SLA Customer Group", "__Test SLA Territory")
|
||||||
|
issue = make_issue(creation, "_Test Customer", 1)
|
||||||
|
|
||||||
self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 7, 18, 0))
|
self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0))
|
||||||
self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 9, 18, 0))
|
self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0))
|
||||||
|
|
||||||
|
# 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", 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
|
||||||
|
customer = create_customer("___Test Customer", "__Test SLA Customer Group", "_Test SLA Territory")
|
||||||
|
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
|
# make issue with default SLA
|
||||||
issue = make_issue(creation)
|
issue = make_issue(creation=creation, index=4)
|
||||||
|
|
||||||
self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 16, 0))
|
self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 16, 0))
|
||||||
self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 18, 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 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
|
# make issue with default SLA next day
|
||||||
issue = make_issue(creation)
|
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.response_by, datetime.datetime(2019, 3, 4, 18, 0))
|
||||||
self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 6, 12, 0))
|
self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 6, 12, 0))
|
||||||
|
|
||||||
frappe.flags.current_time = datetime.datetime(2019, 3, 3, 12, 0)
|
frappe.flags.current_time = datetime.datetime(2019, 3, 4, 15, 0)
|
||||||
|
|
||||||
issue.status = 'Closed'
|
issue.status = 'Closed'
|
||||||
issue.save()
|
issue.save()
|
||||||
|
|
||||||
self.assertEqual(issue.agreement_status, 'Fulfilled')
|
self.assertEqual(issue.agreement_fulfilled, 'Fulfilled')
|
||||||
|
|
||||||
issue.status = 'Open'
|
def make_issue(creation=None, customer=None, index=0):
|
||||||
issue.save()
|
|
||||||
|
|
||||||
frappe.flags.current_time = datetime.datetime(2019, 3, 5, 12, 0)
|
|
||||||
|
|
||||||
issue.status = 'Closed'
|
|
||||||
issue.save()
|
|
||||||
|
|
||||||
self.assertEqual(issue.agreement_status, 'Failed')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def make_issue(creation=None, customer=None):
|
|
||||||
|
|
||||||
issue = frappe.get_doc({
|
issue = frappe.get_doc({
|
||||||
"doctype": "Issue",
|
"doctype": "Issue",
|
||||||
"subject": "Issue 1",
|
"subject": "Service Level Agreement Issue {0}".format(index),
|
||||||
"customer": customer,
|
"customer": customer,
|
||||||
"raised_by": "test@example.com",
|
"raised_by": "test@example.com",
|
||||||
|
"description": "Service Level Agreement Issue",
|
||||||
"creation": creation
|
"creation": creation
|
||||||
}).insert()
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
return issue
|
return issue
|
||||||
|
|
||||||
|
def create_customer(name, customer_group, territory):
|
||||||
|
|
||||||
|
create_customer_group(customer_group)
|
||||||
|
create_territory(territory)
|
||||||
|
|
||||||
|
if not frappe.db.exists("Customer", {"customer_name": name}):
|
||||||
|
frappe.get_doc({
|
||||||
|
"doctype": "Customer",
|
||||||
|
"customer_name": name,
|
||||||
|
"customer_group": customer_group,
|
||||||
|
"territory": territory
|
||||||
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
def create_customer_group(customer_group):
|
||||||
|
|
||||||
|
if not frappe.db.exists("Customer Group", {"customer_group_name": customer_group}):
|
||||||
|
frappe.get_doc({
|
||||||
|
"doctype": "Customer Group",
|
||||||
|
"customer_group_name": customer_group
|
||||||
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
def create_territory(territory):
|
||||||
|
|
||||||
|
if not frappe.db.exists("Territory", {"territory_name": territory}):
|
||||||
|
frappe.get_doc({
|
||||||
|
"doctype": "Territory",
|
||||||
|
"territory_name": territory,
|
||||||
|
}).insert(ignore_permissions=True)
|
||||||
|
0
erpnext/support/doctype/issue_priority/__init__.py
Normal file
0
erpnext/support/doctype/issue_priority/__init__.py
Normal file
8
erpnext/support/doctype/issue_priority/issue_priority.js
Normal file
8
erpnext/support/doctype/issue_priority/issue_priority.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on('Issue Priority', {
|
||||||
|
// refresh: function(frm) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
});
|
39
erpnext/support/doctype/issue_priority/issue_priority.json
Normal file
39
erpnext/support/doctype/issue_priority/issue_priority.json
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"autoname": "Prompt",
|
||||||
|
"creation": "2019-05-20 15:14:21.604447",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"description"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "description",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Description"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"modified": "2019-05-20 17:06:38.095647",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Support",
|
||||||
|
"name": "Issue Priority",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "System Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"quick_entry": 1,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "ASC",
|
||||||
|
"track_changes": 1
|
||||||
|
}
|
14
erpnext/support/doctype/issue_priority/issue_priority.py
Normal file
14
erpnext/support/doctype/issue_priority/issue_priority.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# -*- 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 import _
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class IssuePriority(Document):
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
if frappe.db.exists("Issue Priority", {"name": self.name}):
|
||||||
|
frappe.throw(_("Issue Priority Already Exists"))
|
@ -0,0 +1,28 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class TestIssuePriority(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_priorities(self):
|
||||||
|
make_priorities()
|
||||||
|
priorities = frappe.get_list("Issue Priority")
|
||||||
|
|
||||||
|
for priority in priorities:
|
||||||
|
self.assertIn(priority.name, ["Low", "Medium", "High"])
|
||||||
|
|
||||||
|
def make_priorities():
|
||||||
|
insert_priority("Low")
|
||||||
|
insert_priority("Medium")
|
||||||
|
insert_priority("High")
|
||||||
|
|
||||||
|
def insert_priority(name):
|
||||||
|
if not frappe.db.exists("Issue Priority", name):
|
||||||
|
frappe.get_doc({
|
||||||
|
"doctype": "Issue Priority",
|
||||||
|
"name": name
|
||||||
|
}).insert(ignore_permissions=True)
|
@ -1,115 +1,56 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_import": 1,
|
||||||
"allow_guest_to_view": 0,
|
"allow_rename": 1,
|
||||||
"allow_import": 1,
|
"autoname": "Prompt",
|
||||||
"allow_rename": 0,
|
"creation": "2017-10-06 12:53:34.714153",
|
||||||
"autoname": "Prompt",
|
"doctype": "DocType",
|
||||||
"beta": 0,
|
"document_type": "Setup",
|
||||||
"creation": "2017-10-06 12:53:34.714153",
|
"editable_grid": 1,
|
||||||
"custom": 0,
|
"engine": "InnoDB",
|
||||||
"docstatus": 0,
|
"field_order": [
|
||||||
"doctype": "DocType",
|
"description"
|
||||||
"document_type": "Setup",
|
],
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "description",
|
||||||
"allow_on_submit": 0,
|
"fieldtype": "Small Text",
|
||||||
"bold": 0,
|
"label": "Description"
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "description",
|
|
||||||
"fieldtype": "Small Text",
|
|
||||||
"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": "Description",
|
|
||||||
"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,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"modified": "2019-06-26 16:56:39.863392",
|
||||||
"hide_heading": 0,
|
"modified_by": "Administrator",
|
||||||
"hide_toolbar": 0,
|
"module": "Support",
|
||||||
"idx": 0,
|
"name": "Issue Type",
|
||||||
"image_view": 0,
|
"name_case": "Title Case",
|
||||||
"in_create": 0,
|
"owner": "Administrator",
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 0,
|
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2017-11-15 17:27:19.796807",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Support",
|
|
||||||
"name": "Issue Type",
|
|
||||||
"name_case": "Title Case",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"create": 1,
|
||||||
"apply_user_permissions": 0,
|
"delete": 1,
|
||||||
"cancel": 0,
|
"email": 1,
|
||||||
"create": 1,
|
"export": 1,
|
||||||
"delete": 1,
|
"print": 1,
|
||||||
"email": 1,
|
"read": 1,
|
||||||
"export": 1,
|
"report": 1,
|
||||||
"if_owner": 0,
|
"role": "System Manager",
|
||||||
"import": 0,
|
"share": 1,
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "System Manager",
|
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"create": 1,
|
||||||
"apply_user_permissions": 0,
|
"delete": 1,
|
||||||
"cancel": 0,
|
"email": 1,
|
||||||
"create": 1,
|
"export": 1,
|
||||||
"delete": 1,
|
"print": 1,
|
||||||
"email": 1,
|
"read": 1,
|
||||||
"export": 1,
|
"report": 1,
|
||||||
"if_owner": 0,
|
"role": "Support Team",
|
||||||
"import": 0,
|
"share": 1,
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "Support Team",
|
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"read_only": 0,
|
"sort_field": "modified",
|
||||||
"read_only_onload": 0,
|
"sort_order": "DESC",
|
||||||
"search_fields": "",
|
"track_changes": 1
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"title_field": "",
|
|
||||||
"track_changes": 1,
|
|
||||||
"track_seen": 0
|
|
||||||
}
|
}
|
@ -1,203 +1,53 @@
|
|||||||
{
|
{
|
||||||
"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",
|
"creation": "2019-03-04 12:55:36.403035",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"workday",
|
||||||
|
"section_break_2",
|
||||||
|
"start_time",
|
||||||
|
"column_break_3",
|
||||||
|
"end_time"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "",
|
|
||||||
"fieldname": "workday",
|
"fieldname": "workday",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Workday",
|
"label": "Workday",
|
||||||
"length": 0,
|
"options": "Monday\nTuesday\nWednesday\nThursday\nFriday\nSaturday\nSunday"
|
||||||
"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",
|
"fieldname": "section_break_2",
|
||||||
"fieldtype": "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,
|
|
||||||
"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",
|
"fieldname": "start_time",
|
||||||
"fieldtype": "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_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
"label": "Start Time"
|
||||||
"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",
|
"fieldname": "column_break_3",
|
||||||
"fieldtype": "Column Break",
|
"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",
|
"fieldname": "end_time",
|
||||||
"fieldtype": "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_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
"label": "End Time"
|
||||||
"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,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"modified": "2019-05-05 19:15:08.999579",
|
||||||
"modified": "2019-03-04 12:55:36.403035",
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Support",
|
"module": "Support",
|
||||||
"name": "Service Day",
|
"name": "Service Day",
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1,
|
"track_changes": 1
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
@ -1,488 +1,111 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"autoname": "field:service_level",
|
"autoname": "field:service_level",
|
||||||
"beta": 0,
|
|
||||||
"creation": "2018-11-19 12:44:30.407502",
|
"creation": "2018-11-19 12:44:30.407502",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"service_level",
|
||||||
|
"employee_group",
|
||||||
|
"column_break_2",
|
||||||
|
"holiday_list",
|
||||||
|
"default_priority",
|
||||||
|
"response_and_resoution_time",
|
||||||
|
"priorities",
|
||||||
|
"section_break_01",
|
||||||
|
"support_and_resolution"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "service_level",
|
"fieldname": "service_level",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Level",
|
"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,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 1
|
"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",
|
"fieldname": "column_break_2",
|
||||||
"fieldtype": "Column Break",
|
"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",
|
"fieldname": "holiday_list",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Holiday List (ignored during SLA calculation)",
|
"label": "Holiday List (ignored during SLA calculation)",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Holiday List",
|
"options": "Holiday List",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"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",
|
"fieldname": "employee_group",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Employee Group",
|
"label": "Employee Group",
|
||||||
"length": 0,
|
"options": "Employee Group"
|
||||||
"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",
|
"fieldname": "response_and_resoution_time",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"label": "Response and Resoution Time"
|
||||||
"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",
|
"fieldname": "section_break_01",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"label": "Support Hours"
|
||||||
"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",
|
"fieldname": "support_and_resolution",
|
||||||
"fieldtype": "Table",
|
"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",
|
"label": "Support and Resolution",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Service Day",
|
"options": "Service Day",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"precision": "",
|
},
|
||||||
"print_hide": 0,
|
{
|
||||||
"print_hide_if_no_value": 0,
|
"fieldname": "priorities",
|
||||||
"read_only": 0,
|
"fieldtype": "Table",
|
||||||
"remember_last_selected_value": 0,
|
"label": "Priorities",
|
||||||
"report_hide": 0,
|
"options": "Service Level Priority",
|
||||||
"reqd": 1,
|
"reqd": 1
|
||||||
"search_index": 0,
|
},
|
||||||
"set_only_once": 0,
|
{
|
||||||
"translatable": 0,
|
"fieldname": "default_priority",
|
||||||
"unique": 0
|
"fieldtype": "Link",
|
||||||
|
"label": "Default Priority",
|
||||||
|
"options": "Issue Priority",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"modified": "2019-06-06 12:58:03.464056",
|
||||||
"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",
|
"modified_by": "Administrator",
|
||||||
"module": "Support",
|
"module": "Support",
|
||||||
"name": "Service Level",
|
"name": "Service Level",
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "All",
|
||||||
|
"share": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC"
|
||||||
"track_changes": 0,
|
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
@ -12,35 +12,84 @@ from frappe.utils import get_weekdays
|
|||||||
class ServiceLevel(Document):
|
class ServiceLevel(Document):
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
week = get_weekdays()
|
self.check_priorities()
|
||||||
indexes = []
|
self.check_support_and_resolution()
|
||||||
|
|
||||||
self.check_response_and_resolution_time()
|
def check_priorities(self):
|
||||||
|
default_priority = []
|
||||||
|
priorities = []
|
||||||
|
|
||||||
|
for priority in self.priorities:
|
||||||
|
# Check if response and resolution time is set for every priority
|
||||||
|
if not (priority.response_time or priority.resolution_time):
|
||||||
|
frappe.throw(_("Set Response Time and Resolution for Priority {0} at index {1}.".format(priority.priority, priority.idx)))
|
||||||
|
|
||||||
|
priorities.append(priority.priority)
|
||||||
|
|
||||||
|
if priority.default_priority:
|
||||||
|
default_priority.append(priority.default_priority)
|
||||||
|
|
||||||
|
if priority.response_time_period == "Hour":
|
||||||
|
response = priority.response_time * 0.0416667
|
||||||
|
elif priority.response_time_period == "Day":
|
||||||
|
response = priority.response_time
|
||||||
|
elif priority.response_time_period == "Week":
|
||||||
|
response = priority.response_time * 7
|
||||||
|
|
||||||
|
if priority.resolution_time_period == "Hour":
|
||||||
|
resolution = priority.resolution_time * 0.0416667
|
||||||
|
elif priority.resolution_time_period == "Day":
|
||||||
|
resolution = priority.resolution_time
|
||||||
|
elif priority.resolution_time_period == "Week":
|
||||||
|
resolution = priority.resolution_time * 7
|
||||||
|
|
||||||
|
if response > resolution:
|
||||||
|
frappe.throw(_("Response Time for {0} at index {1} can't be greater than Resolution Time.".format(priority.priority, priority.idx)))
|
||||||
|
|
||||||
|
# Check if repeated priority
|
||||||
|
if not len(set(priorities)) == len(priorities):
|
||||||
|
repeated_priority = get_repeated(priorities)
|
||||||
|
frappe.throw(_("Priority {0} has been repeated.".format(repeated_priority)))
|
||||||
|
|
||||||
|
# Check if repeated default priority
|
||||||
|
if not len(set(default_priority)) == len(default_priority):
|
||||||
|
frappe.throw(_("Select only one Priority as Default."))
|
||||||
|
|
||||||
|
# set default priority from priorities
|
||||||
|
try:
|
||||||
|
self.default_priority = next(d.priority for d in self.priorities if d.default_priority)
|
||||||
|
except Exception:
|
||||||
|
frappe.throw(_("Select a Default Priority."))
|
||||||
|
|
||||||
|
def check_support_and_resolution(self):
|
||||||
|
week = get_weekdays()
|
||||||
|
support_days = []
|
||||||
|
|
||||||
for support_and_resolution in self.support_and_resolution:
|
for support_and_resolution in self.support_and_resolution:
|
||||||
indexes.append(week.index(support_and_resolution.workday))
|
# Check if start and end time is set for every support day
|
||||||
|
if not (support_and_resolution.start_time or support_and_resolution.end_time):
|
||||||
|
frappe.throw(_("Set Start Time and End Time for \
|
||||||
|
Support Day {0} at index {1}.".format(support_and_resolution.workday, support_and_resolution.idx)))
|
||||||
|
|
||||||
|
support_days.append(support_and_resolution.workday)
|
||||||
support_and_resolution.idx = week.index(support_and_resolution.workday) + 1
|
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 support_and_resolution.start_time >= support_and_resolution.end_time:
|
||||||
if self.response_time_period == "Hour":
|
frappe.throw(_("Start Time can't be greater than or equal to End Time \
|
||||||
response = self.response_time * 0.0416667
|
for {0}.".format(support_and_resolution.workday)))
|
||||||
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":
|
# Check for repeated workday
|
||||||
resolution = self.resolution_time * 0.0416667
|
if not len(set(support_days)) == len(support_days):
|
||||||
elif self.resolution_time_period == "Day":
|
repeated_days = get_repeated(support_days)
|
||||||
resolution = self.resolution_time
|
frappe.throw(_("Workday {0} has been repeated.".format(repeated_days)))
|
||||||
elif self.resolution_time_period == "Week":
|
|
||||||
resolution = self.resolution_time * 7
|
|
||||||
|
|
||||||
if response > resolution:
|
def get_repeated(values):
|
||||||
frappe.throw(_("Response Time can't be greater than Resolution Time"))
|
unique_list = []
|
||||||
|
diff = []
|
||||||
|
for value in values:
|
||||||
|
if value not in unique_list:
|
||||||
|
unique_list.append(str(value))
|
||||||
|
else:
|
||||||
|
if value not in diff:
|
||||||
|
diff.append(str(value))
|
||||||
|
return " ".join(diff)
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'service_level',
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'label': _('Service Level Agreement'),
|
||||||
|
'items': ['Service Level Agreement']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -3,31 +3,65 @@
|
|||||||
# See license.txt
|
# See license.txt
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from erpnext.hr.doctype.employee_group.test_employee_group import make_employee_group
|
from erpnext.hr.doctype.employee_group.test_employee_group import make_employee_group
|
||||||
from frappe.utils import now_datetime
|
from erpnext.support.doctype.issue_priority.test_issue_priority import make_priorities
|
||||||
import datetime
|
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
class TestServiceLevel(unittest.TestCase):
|
class TestServiceLevel(unittest.TestCase):
|
||||||
pass
|
|
||||||
|
|
||||||
def make_service_level():
|
def test_service_level(self):
|
||||||
employee_group = make_employee_group()
|
employee_group = make_employee_group()
|
||||||
make_holiday_list()
|
make_holiday_list()
|
||||||
|
make_priorities()
|
||||||
|
|
||||||
# Default Service Level Agreement
|
# Default Service Level
|
||||||
default_service_level = frappe.get_doc({
|
test_make_service_level = create_service_level("__Test Service Level", "__Test Holiday List", employee_group, 4, 6)
|
||||||
|
get_make_service_level = get_service_level("__Test Service Level")
|
||||||
|
|
||||||
|
self.assertEqual(test_make_service_level.name, get_make_service_level.name)
|
||||||
|
self.assertEqual(test_make_service_level.holiday_list, get_make_service_level.holiday_list)
|
||||||
|
self.assertEqual(test_make_service_level.employee_group, get_make_service_level.employee_group)
|
||||||
|
|
||||||
|
# Service Level
|
||||||
|
test_make_service_level = create_service_level("_Test Service Level", "__Test Holiday List", employee_group, 2, 3)
|
||||||
|
get_make_service_level = get_service_level("_Test Service Level")
|
||||||
|
|
||||||
|
self.assertEqual(test_make_service_level.name, get_make_service_level.name)
|
||||||
|
self.assertEqual(test_make_service_level.holiday_list, get_make_service_level.holiday_list)
|
||||||
|
self.assertEqual(test_make_service_level.employee_group, get_make_service_level.employee_group)
|
||||||
|
|
||||||
|
|
||||||
|
def create_service_level(service_level, holiday_list, employee_group, response_time, resolution_time):
|
||||||
|
sl = frappe.get_doc({
|
||||||
"doctype": "Service Level",
|
"doctype": "Service Level",
|
||||||
"service_level": "__Test Service Level",
|
"service_level": service_level,
|
||||||
"holiday_list": "__Test Holiday List",
|
"holiday_list": holiday_list,
|
||||||
"priority": "Medium",
|
|
||||||
"employee_group": employee_group,
|
"employee_group": employee_group,
|
||||||
"response_time": 4,
|
"priorities": [
|
||||||
"response_time_period": "Hour",
|
{
|
||||||
"resolution_time": 6,
|
"priority": "Low",
|
||||||
"resolution_time_period": "Hour",
|
"response_time": response_time,
|
||||||
|
"response_time_period": "Hour",
|
||||||
|
"resolution_time": resolution_time,
|
||||||
|
"resolution_time_period": "Hour",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"priority": "Medium",
|
||||||
|
"response_time": response_time,
|
||||||
|
"default_priority": 1,
|
||||||
|
"response_time_period": "Hour",
|
||||||
|
"resolution_time": resolution_time,
|
||||||
|
"resolution_time_period": "Hour",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"priority": "High",
|
||||||
|
"response_time": response_time,
|
||||||
|
"response_time_period": "Hour",
|
||||||
|
"resolution_time": resolution_time,
|
||||||
|
"resolution_time_period": "Hour",
|
||||||
|
}
|
||||||
|
],
|
||||||
"support_and_resolution": [
|
"support_and_resolution": [
|
||||||
{
|
{
|
||||||
"workday": "Monday",
|
"workday": "Monday",
|
||||||
@ -67,73 +101,21 @@ def make_service_level():
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
default_service_level_exists = frappe.db.exists("Service Level", "__Test Service Level")
|
sl_exists = frappe.db.exists("Service Level", {"service_level": service_level})
|
||||||
if not default_service_level_exists:
|
|
||||||
default_service_level.insert()
|
|
||||||
|
|
||||||
service_level = frappe.get_doc({
|
if not sl_exists:
|
||||||
"doctype": "Service Level",
|
sl.insert()
|
||||||
"service_level": "_Test Service Level",
|
return sl
|
||||||
"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:
|
else:
|
||||||
return service_level_exist
|
return frappe.get_doc("Service Level", {"service_level": service_level})
|
||||||
|
|
||||||
def get_service_level():
|
def get_service_level(service_level):
|
||||||
service_level = frappe.db.exists("Service Level", "_Test Service Level")
|
return frappe.get_doc("Service Level", service_level)
|
||||||
return service_level
|
|
||||||
|
|
||||||
def make_holiday_list():
|
def make_holiday_list():
|
||||||
holiday_list = frappe.db.exists("Holiday List", "__Test Holiday List")
|
holiday_list = frappe.db.exists("Holiday List", "__Test Holiday List")
|
||||||
if not holiday_list:
|
if not holiday_list:
|
||||||
now = datetime.datetime.now()
|
now = frappe.utils.now_datetime()
|
||||||
holiday_list = frappe.get_doc({
|
holiday_list = frappe.get_doc({
|
||||||
"doctype": "Holiday List",
|
"doctype": "Holiday List",
|
||||||
"holiday_list_name": "__Test Holiday List",
|
"holiday_list_name": "__Test Holiday List",
|
||||||
@ -153,4 +135,15 @@ def make_holiday_list():
|
|||||||
"holiday_date": "2019-02-11"
|
"holiday_date": "2019-02-11"
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
|
def create_service_level_for_sla():
|
||||||
|
employee_group = make_employee_group()
|
||||||
|
make_holiday_list()
|
||||||
|
make_priorities()
|
||||||
|
|
||||||
|
# Default Service Level
|
||||||
|
create_service_level("__Test Service Level", "__Test Holiday List", employee_group, 4, 6)
|
||||||
|
|
||||||
|
# Service Level
|
||||||
|
create_service_level("_Test Service Level", "__Test Holiday List", employee_group, 2, 3)
|
||||||
|
@ -11,11 +11,19 @@ frappe.ui.form.on('Service Level Agreement', {
|
|||||||
name: frm.doc.service_level
|
name: frm.doc.service_level
|
||||||
},
|
},
|
||||||
callback: function(data){
|
callback: function(data){
|
||||||
for (var i = 0; i < data.message.support_and_resolution.length; i++){
|
let count = Math.max(data.message.priorities.length, data.message.support_and_resolution.length);
|
||||||
frm.add_child("support_and_resolution", data.message.support_and_resolution[i]);
|
let i = 0;
|
||||||
|
while (i < count){
|
||||||
|
if (data.message.priorities[i]) {
|
||||||
|
frm.add_child("priorities", data.message.priorities[i]);
|
||||||
|
}
|
||||||
|
if (data.message.support_and_resolution[i]) {
|
||||||
|
frm.add_child("support_and_resolution", data.message.support_and_resolution[i]);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
frm.refresh();
|
frm.refresh();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,764 +1,188 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"autoname": "format:SLA-{service_level}-{####}",
|
||||||
"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",
|
"creation": "2018-12-26 21:08:15.448812",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"service_level",
|
||||||
|
"default_service_level_agreement",
|
||||||
|
"holiday_list",
|
||||||
|
"column_break_2",
|
||||||
|
"employee_group",
|
||||||
|
"default_priority",
|
||||||
|
"entity_section",
|
||||||
|
"entity_type",
|
||||||
|
"column_break_10",
|
||||||
|
"entity",
|
||||||
|
"agreement_details_section",
|
||||||
|
"start_date",
|
||||||
|
"active",
|
||||||
|
"column_break_7",
|
||||||
|
"end_date",
|
||||||
|
"response_and_resolution_time_section",
|
||||||
|
"priorities",
|
||||||
|
"support_and_resolution_section_break",
|
||||||
|
"support_and_resolution"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"default": "0",
|
||||||
"allow_in_quick_entry": 0,
|
"depends_on": "eval: !doc.customer;",
|
||||||
"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",
|
"fieldname": "default_service_level_agreement",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"label": "Default Service Level Agreement"
|
||||||
"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",
|
"fieldname": "service_level",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 1,
|
||||||
"label": "Service Level",
|
"label": "Service Level",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Service Level",
|
"options": "Service Level",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"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_from": "service_level.holiday_list",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "holiday_list",
|
"fieldname": "holiday_list",
|
||||||
"fieldtype": "Link",
|
"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",
|
"label": "Holiday List",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Holiday List",
|
"options": "Holiday List",
|
||||||
"permlevel": 0,
|
"read_only": 1
|
||||||
"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",
|
"fieldname": "column_break_2",
|
||||||
"fieldtype": "Column Break",
|
"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_from": "service_level.employee_group",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "employee_group",
|
"fieldname": "employee_group",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"in_list_view": 1,
|
||||||
"ignore_user_permissions": 0,
|
"in_standard_filter": 1,
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Employee Group",
|
"label": "Employee Group",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Employee Group",
|
"options": "Employee Group",
|
||||||
"permlevel": 0,
|
"read_only": 1
|
||||||
"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",
|
"fieldname": "agreement_details_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"label": "Agreement Details"
|
||||||
"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",
|
"depends_on": "eval: !doc.default_service_level_agreement",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "start_date",
|
"fieldname": "start_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
"label": "Start Date"
|
||||||
"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",
|
"depends_on": "eval: !doc.default_contract",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "column_break_7",
|
"fieldname": "column_break_7",
|
||||||
"fieldtype": "Column Break",
|
"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",
|
"depends_on": "eval: !doc.default_service_level_agreement",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "end_date",
|
"fieldname": "end_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
"label": "End Date"
|
||||||
"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,
|
"collapsible": 1,
|
||||||
"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",
|
"fieldname": "response_and_resolution_time_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"label": "Response and Resolution Time"
|
||||||
"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,
|
"collapsible": 1,
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "support_and_resolution_section_break",
|
"fieldname": "support_and_resolution_section_break",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"label": "Support Hours"
|
||||||
"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",
|
"fieldname": "support_and_resolution",
|
||||||
"fieldtype": "Table",
|
"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",
|
"label": "Support and Resolution",
|
||||||
"length": 0,
|
"options": "Service Day"
|
||||||
"no_copy": 0,
|
},
|
||||||
"options": "Service Day",
|
{
|
||||||
"permlevel": 0,
|
"fieldname": "priorities",
|
||||||
"precision": "",
|
"fieldtype": "Table",
|
||||||
"print_hide": 0,
|
"label": "Priorities",
|
||||||
"print_hide_if_no_value": 0,
|
"options": "Service Level Priority"
|
||||||
"read_only": 0,
|
},
|
||||||
"remember_last_selected_value": 0,
|
{
|
||||||
"report_hide": 0,
|
"fetch_from": "service_level.default_priority",
|
||||||
"reqd": 0,
|
"fieldname": "default_priority",
|
||||||
"search_index": 0,
|
"fieldtype": "Link",
|
||||||
"set_only_once": 0,
|
"label": "Default Priority",
|
||||||
"translatable": 0,
|
"options": "Issue Priority",
|
||||||
"unique": 0
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "1",
|
||||||
|
"fieldname": "active",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Active",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_10",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "entity",
|
||||||
|
"fieldtype": "Dynamic Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "Entity",
|
||||||
|
"options": "entity_type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval: !doc.default_service_level_agreement",
|
||||||
|
"fieldname": "entity_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Entity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "entity_type",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "Entity Type",
|
||||||
|
"options": "\nCustomer\nCustomer Group\nTerritory"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"modified": "2019-06-20 18:04:14.293378",
|
||||||
"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",
|
"modified_by": "Administrator",
|
||||||
"module": "Support",
|
"module": "Support",
|
||||||
"name": "Service Level Agreement",
|
"name": "Service Level Agreement",
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "All",
|
"role": "All",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1,
|
"track_changes": 1
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
@ -9,37 +9,88 @@ from frappe import _
|
|||||||
|
|
||||||
class ServiceLevelAgreement(Document):
|
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):
|
def validate(self):
|
||||||
if not self.default_service_level_agreement:
|
if self.default_service_level_agreement:
|
||||||
if not (self.start_date and self.end_date):
|
if frappe.db.exists("Service Level Agreement", {"default_service_level_agreement": "1", "name": ["!=", self.name]}):
|
||||||
frappe.throw(_("Enter Start and End Date for the Agreement."))
|
frappe.throw(_("A Default Service Level Agreement already exists."))
|
||||||
if self.start_date >= self.end_date:
|
else:
|
||||||
frappe.throw(_("Start Date of Agreement can't be greater than or equal to End Date."))
|
if self.start_date and self.end_date:
|
||||||
|
if self.start_date >= self.end_date:
|
||||||
|
frappe.throw(_("Start Date of Agreement can't be greater than or equal to End Date."))
|
||||||
|
|
||||||
|
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})
|
||||||
|
|
||||||
|
return frappe._dict({
|
||||||
|
"priority": priority.priority,
|
||||||
|
"response_time": priority.response_time,
|
||||||
|
"response_time_period": priority.response_time_period,
|
||||||
|
"resolution_time": priority.resolution_time,
|
||||||
|
"resolution_time_period": priority.resolution_time_period
|
||||||
|
})
|
||||||
|
|
||||||
def check_agreement_status():
|
def check_agreement_status():
|
||||||
service_level_agreements = frappe.get_list("Service Level Agreement", filters=[
|
service_level_agreements = frappe.get_list("Service Level Agreement", filters=[
|
||||||
{"agreement_status": "Active"},
|
{"active": 1},
|
||||||
{"default_service_level_agreement": 0}
|
{"default_service_level_agreement": 0}
|
||||||
])
|
], fields=["name"])
|
||||||
service_level_agreements.reverse()
|
|
||||||
for service_level_agreement in service_level_agreements:
|
for service_level_agreement in service_level_agreements:
|
||||||
service_level_agreement = frappe.get_doc("Service Level Agreement", service_level_agreement)
|
doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name)
|
||||||
if service_level_agreement.end_date < frappe.utils.getdate():
|
if doc.end_date and doc.end_date < frappe.utils.getdate():
|
||||||
service_level_agreement.agreement_status = "Expired"
|
frappe.db.set_value("Service Level Agreement", service_level_agreement.name, "active", 0)
|
||||||
service_level_agreement.save()
|
|
||||||
|
|
||||||
def get_active_service_level_agreement_for(customer):
|
def get_active_service_level_agreement_for(priority, customer=None, service_level_agreement=None):
|
||||||
agreement = frappe.get_list("Service Level Agreement",
|
filters = [
|
||||||
filters=[{"agreement_status": "Active"}],
|
["Service Level Agreement", "active", "=", 1],
|
||||||
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
|
if priority:
|
||||||
|
filters.append(["Service Level Priority", "priority", "=", priority])
|
||||||
|
|
||||||
|
or_filters = [
|
||||||
|
["Service Level Agreement", "entity", "in", [customer, get_customer_group(customer), get_customer_territory(customer)]]
|
||||||
|
]
|
||||||
|
if service_level_agreement:
|
||||||
|
or_filters = [
|
||||||
|
["Service Level Agreement", "name", "=", service_level_agreement],
|
||||||
|
]
|
||||||
|
|
||||||
|
or_filters.append(["Service Level Agreement", "default_service_level_agreement", "=", 1])
|
||||||
|
|
||||||
|
agreement = frappe.get_list("Service Level Agreement", filters=filters, or_filters=or_filters,
|
||||||
|
fields=["name", "default_priority"])
|
||||||
|
|
||||||
|
return agreement[0] if agreement else None
|
||||||
|
|
||||||
|
def get_customer_group(customer):
|
||||||
|
if customer:
|
||||||
|
return frappe.db.get_value("Customer", customer, "customer_group")
|
||||||
|
|
||||||
|
def get_customer_territory(customer):
|
||||||
|
if customer:
|
||||||
|
return frappe.db.get_value("Customer", customer, "territory")
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_service_level_agreement_filters(name, customer=None):
|
||||||
|
if not customer:
|
||||||
|
or_filters = [
|
||||||
|
["Service Level Agreement", "default_service_level_agreement", "=", 1]
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
or_filters = [
|
||||||
|
["Service Level Agreement", "entity", "in", [customer, get_customer_group(customer), get_customer_territory(customer), "IS NULL"]],
|
||||||
|
["Service Level Agreement", "default_service_level_agreement", "=", 1]
|
||||||
|
]
|
||||||
|
|
||||||
|
return {
|
||||||
|
"priority": [priority.priority for priority in frappe.get_list("Service Level Priority", filters={"parent": name}, fields=["priority"])],
|
||||||
|
"service_level_agreements": [d.name for d in frappe.get_list("Service Level Agreement", or_filters=or_filters)]
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'service_level_agreement',
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'label': _('Issue'),
|
||||||
|
'items': ['Issue']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -5,29 +5,107 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
import unittest
|
import unittest
|
||||||
from erpnext.support.doctype.service_level.test_service_level import make_service_level
|
from erpnext.support.doctype.service_level.test_service_level import create_service_level_for_sla
|
||||||
|
|
||||||
class TestServiceLevelAgreement(unittest.TestCase):
|
class TestServiceLevelAgreement(unittest.TestCase):
|
||||||
pass
|
|
||||||
|
|
||||||
def make_service_level_agreement():
|
def test_service_level_agreement(self):
|
||||||
make_service_level()
|
create_service_level_for_sla()
|
||||||
|
|
||||||
# Default Service Level Agreement
|
# Default Service Level Agreement
|
||||||
default_service_level_agreement = frappe.get_doc({
|
create_default_service_level_agreement = create_service_level_agreement(default_service_level_agreement=1,
|
||||||
|
service_level="__Test Service Level", holiday_list="__Test Holiday List", employee_group="_Test Employee Group",
|
||||||
|
entity_type=None, entity=None, response_time=4, resolution_time=6)
|
||||||
|
get_default_service_level_agreement = get_service_level_agreement(default_service_level_agreement=1)
|
||||||
|
|
||||||
|
self.assertEqual(create_default_service_level_agreement.name, get_default_service_level_agreement.name)
|
||||||
|
self.assertEqual(create_default_service_level_agreement.entity_type, get_default_service_level_agreement.entity_type)
|
||||||
|
self.assertEqual(create_default_service_level_agreement.entity, get_default_service_level_agreement.entity)
|
||||||
|
self.assertEqual(create_default_service_level_agreement.default_service_level_agreement, get_default_service_level_agreement.default_service_level_agreement)
|
||||||
|
|
||||||
|
# Service Level Agreement for Customer
|
||||||
|
customer = create_customer()
|
||||||
|
create_customer_service_level_agreement = create_service_level_agreement(default_service_level_agreement=0,
|
||||||
|
service_level="_Test Service Level", holiday_list="__Test Holiday List", employee_group="_Test Employee Group",
|
||||||
|
entity_type="Customer", entity=customer, response_time=2, resolution_time=3)
|
||||||
|
get_customer_service_level_agreement = get_service_level_agreement(entity_type="Customer", entity=customer)
|
||||||
|
|
||||||
|
self.assertEqual(create_customer_service_level_agreement.name, get_customer_service_level_agreement.name)
|
||||||
|
self.assertEqual(create_customer_service_level_agreement.entity_type, get_customer_service_level_agreement.entity_type)
|
||||||
|
self.assertEqual(create_customer_service_level_agreement.entity, get_customer_service_level_agreement.entity)
|
||||||
|
self.assertEqual(create_customer_service_level_agreement.default_service_level_agreement, get_customer_service_level_agreement.default_service_level_agreement)
|
||||||
|
|
||||||
|
# Service Level Agreement for Customer Group
|
||||||
|
customer_group = create_customer_group()
|
||||||
|
create_customer_group_service_level_agreement = create_service_level_agreement(default_service_level_agreement=0,
|
||||||
|
service_level="_Test Service Level", holiday_list="__Test Holiday List", employee_group="_Test Employee Group",
|
||||||
|
entity_type="Customer Group", entity=customer_group, response_time=2, resolution_time=3)
|
||||||
|
get_customer_group_service_level_agreement = get_service_level_agreement(entity_type="Customer Group", entity=customer_group)
|
||||||
|
|
||||||
|
self.assertEqual(create_customer_group_service_level_agreement.name, get_customer_group_service_level_agreement.name)
|
||||||
|
self.assertEqual(create_customer_group_service_level_agreement.entity_type, get_customer_group_service_level_agreement.entity_type)
|
||||||
|
self.assertEqual(create_customer_group_service_level_agreement.entity, get_customer_group_service_level_agreement.entity)
|
||||||
|
self.assertEqual(create_customer_group_service_level_agreement.default_service_level_agreement, get_customer_group_service_level_agreement.default_service_level_agreement)
|
||||||
|
|
||||||
|
# Service Level Agreement for Territory
|
||||||
|
territory = create_territory()
|
||||||
|
create_territory_service_level_agreement = create_service_level_agreement(default_service_level_agreement=0,
|
||||||
|
service_level="_Test Service Level", holiday_list="__Test Holiday List", employee_group="_Test Employee Group",
|
||||||
|
entity_type="Territory", entity=territory, response_time=2, resolution_time=3)
|
||||||
|
get_territory_service_level_agreement = get_service_level_agreement(entity_type="Territory", entity=territory)
|
||||||
|
|
||||||
|
self.assertEqual(create_territory_service_level_agreement.name, get_territory_service_level_agreement.name)
|
||||||
|
self.assertEqual(create_territory_service_level_agreement.entity_type, get_territory_service_level_agreement.entity_type)
|
||||||
|
self.assertEqual(create_territory_service_level_agreement.entity, get_territory_service_level_agreement.entity)
|
||||||
|
self.assertEqual(create_territory_service_level_agreement.default_service_level_agreement, get_territory_service_level_agreement.default_service_level_agreement)
|
||||||
|
|
||||||
|
|
||||||
|
def get_service_level_agreement(default_service_level_agreement=None, entity_type=None, entity=None):
|
||||||
|
if default_service_level_agreement:
|
||||||
|
filters = {"default_service_level_agreement": default_service_level_agreement}
|
||||||
|
else:
|
||||||
|
filters = {"entity_type": entity_type, "entity": entity}
|
||||||
|
|
||||||
|
service_level_agreement = frappe.get_doc("Service Level Agreement", filters)
|
||||||
|
return service_level_agreement
|
||||||
|
|
||||||
|
def create_service_level_agreement(default_service_level_agreement, service_level, holiday_list, employee_group,
|
||||||
|
response_time, entity_type, entity, resolution_time):
|
||||||
|
|
||||||
|
service_level_agreement = frappe.get_doc({
|
||||||
"doctype": "Service Level Agreement",
|
"doctype": "Service Level Agreement",
|
||||||
"name": "__Test Service Level Agreement",
|
"default_service_level_agreement": default_service_level_agreement,
|
||||||
"default_service_level_agreement": 1,
|
"service_level": service_level,
|
||||||
"service_level": "__Test Service Level",
|
"holiday_list": holiday_list,
|
||||||
"holiday_list": "__Test Holiday List",
|
"employee_group": employee_group,
|
||||||
"priority": "Medium",
|
"entity_type": entity_type,
|
||||||
"employee_group": "_Test Employee Group",
|
"entity": entity,
|
||||||
"start_date": frappe.utils.getdate(),
|
"start_date": frappe.utils.getdate(),
|
||||||
"end_date": frappe.utils.add_to_date(frappe.utils.getdate(), days=100),
|
"end_date": frappe.utils.add_to_date(frappe.utils.getdate(), days=100),
|
||||||
"response_time": 4,
|
"priorities": [
|
||||||
"response_time_period": "Hour",
|
{
|
||||||
"resolution_time": 6,
|
"priority": "Low",
|
||||||
"resolution_time_period": "Hour",
|
"response_time": response_time,
|
||||||
|
"response_time_period": "Hour",
|
||||||
|
"resolution_time": resolution_time,
|
||||||
|
"resolution_time_period": "Hour",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"priority": "Medium",
|
||||||
|
"response_time": response_time,
|
||||||
|
"default_priority": 1,
|
||||||
|
"response_time_period": "Hour",
|
||||||
|
"resolution_time": resolution_time,
|
||||||
|
"resolution_time_period": "Hour",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"priority": "High",
|
||||||
|
"response_time": response_time,
|
||||||
|
"response_time_period": "Hour",
|
||||||
|
"resolution_time": resolution_time,
|
||||||
|
"resolution_time_period": "Hour",
|
||||||
|
}
|
||||||
|
],
|
||||||
"support_and_resolution": [
|
"support_and_resolution": [
|
||||||
{
|
{
|
||||||
"workday": "Monday",
|
"workday": "Monday",
|
||||||
@ -67,11 +145,26 @@ def make_service_level_agreement():
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
default_service_level_agreement_exists = frappe.db.exists("Service Level Agreement", "__Test Service Level Agreement")
|
filters = {
|
||||||
if not default_service_level_agreement_exists:
|
"default_service_level_agreement": service_level_agreement.default_service_level_agreement,
|
||||||
default_service_level_agreement.insert()
|
"service_level": service_level_agreement.service_level
|
||||||
|
}
|
||||||
|
|
||||||
|
if not default_service_level_agreement:
|
||||||
|
filters.update({
|
||||||
|
"entity_type": entity_type,
|
||||||
|
"entity": entity
|
||||||
|
})
|
||||||
|
|
||||||
|
service_level_agreement_exists = frappe.db.exists("Service Level Agreement", filters)
|
||||||
|
|
||||||
|
if not service_level_agreement_exists:
|
||||||
|
service_level_agreement.insert(ignore_permissions=True)
|
||||||
|
return service_level_agreement
|
||||||
|
else:
|
||||||
|
return frappe.get_doc("Service Level Agreement", service_level_agreement_exists)
|
||||||
|
|
||||||
|
def create_customer():
|
||||||
customer = frappe.get_doc({
|
customer = frappe.get_doc({
|
||||||
"doctype": "Customer",
|
"doctype": "Customer",
|
||||||
"customer_name": "_Test Customer",
|
"customer_name": "_Test Customer",
|
||||||
@ -80,70 +173,53 @@ def make_service_level_agreement():
|
|||||||
"territory": "Rest Of The World"
|
"territory": "Rest Of The World"
|
||||||
})
|
})
|
||||||
if not frappe.db.exists("Customer", "_Test Customer"):
|
if not frappe.db.exists("Customer", "_Test Customer"):
|
||||||
customer.insert()
|
customer.insert(ignore_permissions=True)
|
||||||
|
return customer.name
|
||||||
else:
|
else:
|
||||||
customer = frappe.get_doc("Customer", "_Test Customer")
|
return frappe.db.exists("Customer", "_Test Customer")
|
||||||
|
|
||||||
service_level_agreement = frappe.get_doc({
|
def create_customer_group():
|
||||||
"doctype": "Service Level Agreement",
|
customer_group = frappe.get_doc({
|
||||||
"name": "_Test Service Level Agreement",
|
"doctype": "Customer Group",
|
||||||
"customer": customer.customer_name,
|
"customer_group_name": "_Test SLA Customer Group"
|
||||||
"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 frappe.db.exists("Customer Group", {"customer_group_name": "_Test SLA Customer Group"}):
|
||||||
if not service_level_agreement_exists:
|
customer_group.insert()
|
||||||
service_level_agreement.insert()
|
return customer_group.name
|
||||||
return service_level_agreement.name
|
|
||||||
else:
|
else:
|
||||||
return service_level_agreement_exists
|
return frappe.db.exists("Customer Group", {"customer_group_name": "_Test SLA Customer Group"})
|
||||||
|
|
||||||
def get_service_level_agreement():
|
def create_territory():
|
||||||
service_level_agreement = frappe.db.exists("Service Level Agreement", "_Test Service Level Agreement")
|
territory = frappe.get_doc({
|
||||||
return service_level_agreement
|
"doctype": "Territory",
|
||||||
|
"territory_name": "_Test SLA Territory",
|
||||||
|
})
|
||||||
|
|
||||||
|
if not frappe.db.exists("Territory", {"territory_name": "_Test SLA Territory"}):
|
||||||
|
territory.insert()
|
||||||
|
return territory.name
|
||||||
|
else:
|
||||||
|
return frappe.db.exists("Territory", {"territory_name": "_Test SLA Territory"})
|
||||||
|
|
||||||
|
def create_service_level_agreements_for_issues():
|
||||||
|
create_service_level_for_sla()
|
||||||
|
|
||||||
|
create_service_level_agreement(default_service_level_agreement=1,
|
||||||
|
service_level="__Test Service Level", holiday_list="__Test Holiday List", employee_group="_Test Employee Group",
|
||||||
|
entity_type=None, entity=None, response_time=4, resolution_time=6)
|
||||||
|
|
||||||
|
create_customer()
|
||||||
|
create_service_level_agreement(default_service_level_agreement=0,
|
||||||
|
service_level="_Test Service Level", holiday_list="__Test Holiday List", employee_group="_Test Employee Group",
|
||||||
|
entity_type="Customer", entity="_Test Customer", response_time=2, resolution_time=3)
|
||||||
|
|
||||||
|
create_customer_group()
|
||||||
|
create_service_level_agreement(default_service_level_agreement=0,
|
||||||
|
service_level="_Test Service Level", holiday_list="__Test Holiday List", employee_group="_Test Employee Group",
|
||||||
|
entity_type="Customer Group", entity="_Test SLA Customer Group", response_time=2, resolution_time=3)
|
||||||
|
|
||||||
|
create_territory()
|
||||||
|
create_service_level_agreement(default_service_level_agreement=0,
|
||||||
|
service_level="_Test Service Level", holiday_list="__Test Holiday List", employee_group="_Test Employee Group",
|
||||||
|
entity_type="Territory", entity="_Test SLA Territory", response_time=2, resolution_time=3)
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
{
|
||||||
|
"creation": "2019-05-04 05:54:03.658991",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"priority",
|
||||||
|
"cb_01",
|
||||||
|
"default_priority",
|
||||||
|
"sb_00",
|
||||||
|
"response_time",
|
||||||
|
"response_time_period",
|
||||||
|
"cb_00",
|
||||||
|
"resolution_time",
|
||||||
|
"resolution_time_period"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"columns": 2,
|
||||||
|
"fieldname": "priority",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Priority",
|
||||||
|
"options": "Issue Priority"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "sb_00",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": 1,
|
||||||
|
"fieldname": "response_time",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Response Time"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": 1,
|
||||||
|
"fieldname": "resolution_time",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Resolution Time"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "cb_00",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": 2,
|
||||||
|
"fieldname": "response_time_period",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Response Time Period",
|
||||||
|
"options": "Hour\nDay\nWeek"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": 2,
|
||||||
|
"fieldname": "resolution_time_period",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Resolution Time Period",
|
||||||
|
"options": "Hour\nDay\nWeek"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "cb_01",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "default_priority",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Default Priority"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"istable": 1,
|
||||||
|
"modified": "2019-05-21 06:54:42.674377",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Support",
|
||||||
|
"name": "Service Level Priority",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"quick_entry": 1,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"track_changes": 1
|
||||||
|
}
|
@ -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 ServiceLevelPriority(Document):
|
||||||
|
pass
|
@ -1,111 +1,128 @@
|
|||||||
{
|
{
|
||||||
"accept_payment": 0,
|
"accept_payment": 0,
|
||||||
"allow_comments": 1,
|
"allow_comments": 1,
|
||||||
"allow_delete": 1,
|
"allow_delete": 1,
|
||||||
"allow_edit": 1,
|
"allow_edit": 1,
|
||||||
"allow_incomplete": 0,
|
"allow_incomplete": 0,
|
||||||
"allow_multiple": 1,
|
"allow_multiple": 1,
|
||||||
"allow_print": 0,
|
"allow_print": 0,
|
||||||
"amount": 0.0,
|
"amount": 0.0,
|
||||||
"amount_based_on_field": 0,
|
"amount_based_on_field": 0,
|
||||||
"breadcrumbs": "[{\"label\":_(\"Issues\"), \"route\":\"issues\"}]",
|
"breadcrumbs": "[{\"label\":_(\"Issues\"), \"route\":\"issues\"}]",
|
||||||
"creation": "2016-06-24 15:50:33.186483",
|
"creation": "2016-06-24 15:50:33.186483",
|
||||||
"doc_type": "Issue",
|
"doc_type": "Issue",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Web Form",
|
"doctype": "Web Form",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"introduction_text": "",
|
"introduction_text": "",
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
"login_required": 1,
|
"login_required": 1,
|
||||||
"max_attachment_size": 0,
|
"max_attachment_size": 0,
|
||||||
"modified": "2018-07-20 13:08:43.797886",
|
"modified": "2019-06-27 22:58:49.609672",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Support",
|
"module": "Support",
|
||||||
"name": "issues",
|
"name": "issues",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"published": 1,
|
"published": 1,
|
||||||
"route": "issues",
|
"route": "issues",
|
||||||
"show_sidebar": 1,
|
"route_to_success_link": 0,
|
||||||
"sidebar_items": [],
|
"show_attachments": 0,
|
||||||
"success_message": "",
|
"show_in_grid": 0,
|
||||||
"success_url": "/issues",
|
"show_sidebar": 1,
|
||||||
"title": "Issue",
|
"sidebar_items": [],
|
||||||
|
"success_message": "",
|
||||||
|
"success_url": "/issues",
|
||||||
|
"title": "Issue",
|
||||||
"web_form_fields": [
|
"web_form_fields": [
|
||||||
{
|
{
|
||||||
"fieldname": "subject",
|
"allow_read_on_all_link_options": 0,
|
||||||
"fieldtype": "Data",
|
"fieldname": "subject",
|
||||||
"hidden": 0,
|
"fieldtype": "Data",
|
||||||
"label": "Subject",
|
"hidden": 0,
|
||||||
"max_length": 0,
|
"label": "Subject",
|
||||||
"max_value": 0,
|
"max_length": 0,
|
||||||
"read_only": 0,
|
"max_value": 0,
|
||||||
"reqd": 1
|
"read_only": 0,
|
||||||
},
|
"reqd": 1,
|
||||||
|
"show_in_filter": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"default": "Open",
|
"allow_read_on_all_link_options": 0,
|
||||||
"fieldname": "status",
|
"default": "Open",
|
||||||
"fieldtype": "Select",
|
"fieldname": "status",
|
||||||
"hidden": 0,
|
"fieldtype": "Select",
|
||||||
"label": "Status",
|
"hidden": 0,
|
||||||
"max_length": 0,
|
"label": "Status",
|
||||||
"max_value": 0,
|
"max_length": 0,
|
||||||
"options": "Open\nReplied\nHold\nClosed",
|
"max_value": 0,
|
||||||
"read_only": 1,
|
"options": "Open\nReplied\nHold\nClosed",
|
||||||
"reqd": 0
|
"read_only": 1,
|
||||||
},
|
"reqd": 0,
|
||||||
|
"show_in_filter": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "customer",
|
"allow_read_on_all_link_options": 0,
|
||||||
"fieldtype": "Data",
|
"fieldname": "customer",
|
||||||
"hidden": 0,
|
"fieldtype": "Data",
|
||||||
"label": "Customer",
|
"hidden": 0,
|
||||||
"max_length": 0,
|
"label": "Customer",
|
||||||
"max_value": 0,
|
"max_length": 0,
|
||||||
"options": "Customer",
|
"max_value": 0,
|
||||||
"read_only": 1,
|
"options": "Customer",
|
||||||
"reqd": 0
|
"read_only": 1,
|
||||||
},
|
"reqd": 0,
|
||||||
|
"show_in_filter": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "description",
|
"allow_read_on_all_link_options": 0,
|
||||||
"fieldtype": "Text",
|
"fieldname": "description",
|
||||||
"hidden": 0,
|
"fieldtype": "Text",
|
||||||
"label": "Description",
|
"hidden": 0,
|
||||||
"max_length": 0,
|
"label": "Description",
|
||||||
"max_value": 0,
|
"max_length": 0,
|
||||||
"read_only": 0,
|
"max_value": 0,
|
||||||
"reqd": 0
|
"read_only": 0,
|
||||||
},
|
"reqd": 0,
|
||||||
|
"show_in_filter": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "attachment",
|
"allow_read_on_all_link_options": 0,
|
||||||
"fieldtype": "Attach",
|
"fieldname": "attachment",
|
||||||
"hidden": 0,
|
"fieldtype": "Attach",
|
||||||
"label": "Attachment",
|
"hidden": 0,
|
||||||
"max_length": 0,
|
"label": "Attachment",
|
||||||
"max_value": 0,
|
"max_length": 0,
|
||||||
"read_only": 0,
|
"max_value": 0,
|
||||||
"reqd": 0
|
"read_only": 0,
|
||||||
},
|
"reqd": 0,
|
||||||
|
"show_in_filter": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"default": "Medium",
|
"allow_read_on_all_link_options": 0,
|
||||||
"fieldname": "priority",
|
"default": "Medium",
|
||||||
"fieldtype": "Select",
|
"fieldname": "priority",
|
||||||
"hidden": 0,
|
"fieldtype": "Link",
|
||||||
"label": "Priority",
|
"hidden": 0,
|
||||||
"max_length": 0,
|
"label": "Priority",
|
||||||
"max_value": 0,
|
"max_length": 0,
|
||||||
"options": "Low\nMedium\nHigh",
|
"max_value": 0,
|
||||||
"read_only": 0,
|
"options": "Issue Priority",
|
||||||
"reqd": 1
|
"read_only": 0,
|
||||||
},
|
"reqd": 1,
|
||||||
|
"show_in_filter": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"default": "1",
|
"allow_read_on_all_link_options": 0,
|
||||||
"fieldname": "via_customer_portal",
|
"default": "1",
|
||||||
"fieldtype": "Check",
|
"fieldname": "via_customer_portal",
|
||||||
"hidden": 1,
|
"fieldtype": "Check",
|
||||||
"label": "Via Customer Portal",
|
"hidden": 1,
|
||||||
"max_length": 0,
|
"label": "Via Customer Portal",
|
||||||
"max_value": 0,
|
"max_length": 0,
|
||||||
"read_only": 1,
|
"max_value": 0,
|
||||||
"reqd": 0
|
"read_only": 1,
|
||||||
|
"reqd": 0,
|
||||||
|
"show_in_filter": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user