From 00a494f07b88afffc74af1b02c887f47280d02e7 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 3 May 2019 12:44:35 +0530 Subject: [PATCH 01/92] fix: change sla on priority --- erpnext/config/hr.py | 5 + erpnext/config/support.py | 5 - erpnext/support/doctype/issue/issue.json | 1565 ++++------------- .../doctype/service_level/service_level.json | 424 +---- .../service_level_agreement.js | 13 +- .../service_level_agreement.json | 669 +------ .../service_level_agreement.py | 3 + 7 files changed, 405 insertions(+), 2279 deletions(-) diff --git a/erpnext/config/hr.py b/erpnext/config/hr.py index 0f009b826f..342cc6ef4f 100644 --- a/erpnext/config/hr.py +++ b/erpnext/config/hr.py @@ -18,6 +18,11 @@ def get_data(): "onboard": 1, "dependencies": ["Employee"] }, + { + "type": "doctype", + "name": "Employee Group", + "dependencies": ["Employee"] + }, { "type": "doctype", "name": "Attendance", diff --git a/erpnext/config/support.py b/erpnext/config/support.py index c19dd423e6..f5d35cc9ee 100644 --- a/erpnext/config/support.py +++ b/erpnext/config/support.py @@ -38,11 +38,6 @@ def get_data(): { "label": _("Service Level Agreement"), "items": [ - { - "type": "doctype", - "name": "Employee Group", - "description": _("Support Team."), - }, { "type": "doctype", "name": "Service Level", diff --git a/erpnext/support/doctype/issue/issue.json b/erpnext/support/doctype/issue/issue.json index 91b718e86f..2e23b09a40 100644 --- a/erpnext/support/doctype/issue/issue.json +++ b/erpnext/support/doctype/issue/issue.json @@ -1,1309 +1,348 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 1, - "autoname": "naming_series:", - "beta": 0, - "creation": "2013-02-01 10:36:25", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Setup", - "editable_grid": 0, - "engine": "InnoDB", + "allow_import": 1, + "allow_rename": 1, + "autoname": "naming_series:", + "creation": "2013-02-01 10:36:25", + "doctype": "DocType", + "document_type": "Setup", + "engine": "InnoDB", + "field_order": [ + "subject_section", + "naming_series", + "subject", + "customer", + "raised_by", + "cb00", + "status", + "service_level_agreement", + "priority", + "issue_type", + "sb_details", + "description", + "service_level_section", + "response_by", + "cb", + "agreement_status", + "resolution_by", + "response", + "mins_to_first_response", + "first_responded_on", + "additional_info", + "lead", + "contact", + "email_account", + "column_break_16", + "customer_name", + "project", + "company", + "section_break_19", + "resolution_details", + "column_break1", + "opening_date", + "opening_time", + "resolution_date", + "content_type", + "attachment", + "via_customer_portal" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "subject_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Subject", - "length": 0, - "no_copy": 0, - "options": "fa fa-flag", - "permlevel": 0, - "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 - }, + "fieldname": "subject_section", + "fieldtype": "Section Break", + "label": "Subject", + "options": "fa fa-flag" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fetch_if_empty": 0, - "fieldname": "naming_series", - "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": "Series", - "length": 0, - "no_copy": 1, - "options": "ISS-.YYYY.-", - "permlevel": 0, - "print_hide": 1, - "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": 1, - "translatable": 0, - "unique": 0 - }, + "fieldname": "naming_series", + "fieldtype": "Select", + "label": "Series", + "no_copy": 1, + "options": "ISS-.YYYY.-", + "print_hide": 1, + "set_only_once": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "subject", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Subject", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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 - }, + "bold": 1, + "fieldname": "subject", + "fieldtype": "Data", + "in_global_search": 1, + "label": "Subject", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "customer", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Customer", - "length": 0, - "no_copy": 0, - "oldfieldname": "customer", - "oldfieldtype": "Link", - "options": "Customer", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "customer", + "fieldtype": "Link", + "in_global_search": 1, + "label": "Customer", + "oldfieldname": "customer", + "oldfieldtype": "Link", + "options": "Customer", + "print_hide": 1, + "search_index": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.__islocal", - "fetch_if_empty": 0, - "fieldname": "raised_by", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Raised By (Email)", - "length": 0, - "no_copy": 0, - "oldfieldname": "raised_by", - "oldfieldtype": "Data", - "options": "Email", - "permlevel": 0, - "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 - }, + "bold": 1, + "depends_on": "eval:doc.__islocal", + "fieldname": "raised_by", + "fieldtype": "Data", + "in_global_search": 1, + "in_list_view": 1, + "label": "Raised By (Email)", + "oldfieldname": "raised_by", + "oldfieldtype": "Data", + "options": "Email" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "cb00", - "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, - "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 - }, + "fieldname": "cb00", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Open", - "fetch_if_empty": 0, - "fieldname": "status", - "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": 1, - "label": "Status", - "length": 0, - "no_copy": 1, - "oldfieldname": "status", - "oldfieldtype": "Select", - "options": "Open\nReplied\nHold\nClosed", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Open", + "fieldname": "status", + "fieldtype": "Select", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Status", + "no_copy": 1, + "oldfieldname": "status", + "oldfieldtype": "Select", + "options": "Open\nReplied\nHold\nClosed", + "search_index": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Medium", - "depends_on": "", - "fetch_if_empty": 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": 0, - "in_standard_filter": 1, - "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 - }, + "default": "Medium", + "fieldname": "priority", + "fieldtype": "Select", + "in_standard_filter": 1, + "label": "Priority", + "options": "Low\nMedium\nHigh", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "issue_type", - "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": "Issue Type", - "length": 0, - "no_copy": 0, - "options": "Issue Type", - "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 - }, + "fieldname": "issue_type", + "fieldtype": "Link", + "label": "Issue Type", + "options": "Issue Type" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "collapsible_depends_on": "eval:doc.status!=\"Closed\"", - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "sb_details", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "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 - }, + "collapsible": 1, + "collapsible_depends_on": "eval:doc.status!=\"Closed\"", + "fieldname": "sb_details", + "fieldtype": "Section Break", + "label": "Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, - "fieldname": "description", - "fieldtype": "Text Editor", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Description", - "length": 0, - "no_copy": 0, - "oldfieldname": "problem_description", - "oldfieldtype": "Text", - "permlevel": 0, - "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 - }, + "bold": 1, + "fieldname": "description", + "fieldtype": "Text Editor", + "in_global_search": 1, + "label": "Description", + "oldfieldname": "problem_description", + "oldfieldtype": "Text" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "depends_on": "eval: doc.service_level_agreement", - "fetch_if_empty": 0, - "fieldname": "service_level_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Service 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": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "collapsible": 1, + "depends_on": "eval: doc.service_level_agreement", + "fieldname": "service_level_section", + "fieldtype": "Section Break", + "label": "Service Level" + }, { - "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_agreement", - "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": "Service Level Agreement", - "length": 0, - "no_copy": 0, - "options": "Service Level Agreement", - "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 - }, + "fieldname": "service_level_agreement", + "fieldtype": "Link", + "label": "Service Level Agreement", + "options": "Service Level Agreement" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "response_by", - "fieldtype": "Datetime", - "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 By", - "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 - }, + "fieldname": "response_by", + "fieldtype": "Datetime", + "label": "Response By", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "cb", - "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, - "label": "", - "length": 0, - "no_copy": 0, - "options": "fa fa-pushpin", - "permlevel": 0, - "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 - }, + "collapsible": 1, + "fieldname": "cb", + "fieldtype": "Column Break", + "options": "fa fa-pushpin", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Ongoing", - "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": "Ongoing\nFulfilled\nFailed", - "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 - }, + "default": "Ongoing", + "fieldname": "agreement_status", + "fieldtype": "Select", + "label": "Agreement Status", + "options": "Ongoing\nFulfilled\nFailed", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "resolution_by", - "fieldtype": "Datetime", - "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 By", - "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 - }, + "fieldname": "resolution_by", + "fieldtype": "Datetime", + "label": "Resolution By", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "response", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Response", - "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 - }, + "collapsible": 1, + "fieldname": "response", + "fieldtype": "Section Break", + "label": "Response" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "mins_to_first_response", - "fieldtype": "Float", - "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": "Mins to First Response", - "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 - }, + "bold": 1, + "fieldname": "mins_to_first_response", + "fieldtype": "Float", + "label": "Mins to First Response", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "first_responded_on", - "fieldtype": "Datetime", - "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": "First Responded On", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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 - }, + "fieldname": "first_responded_on", + "fieldtype": "Datetime", + "label": "First Responded On" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "additional_info", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Reference", - "length": 0, - "no_copy": 0, - "options": "fa fa-pushpin", - "permlevel": 0, - "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 - }, + "collapsible": 1, + "fieldname": "additional_info", + "fieldtype": "Section Break", + "label": "Reference", + "options": "fa fa-pushpin", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "lead", - "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": "Lead", - "length": 0, - "no_copy": 0, - "options": "Lead", - "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 - }, + "fieldname": "lead", + "fieldtype": "Link", + "label": "Lead", + "options": "Lead" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "contact", - "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": "Contact", - "length": 0, - "no_copy": 0, - "options": "Contact", - "permlevel": 0, - "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 - }, + "fieldname": "contact", + "fieldtype": "Link", + "label": "Contact", + "options": "Contact" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "email_account", - "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": "Email Account", - "length": 0, - "no_copy": 0, - "options": "Email Account", - "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 - }, + "fieldname": "email_account", + "fieldtype": "Link", + "label": "Email Account", + "options": "Email Account" + }, { - "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 - }, + "fieldname": "column_break_16", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "customer_name", - "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": "Customer Name", - "length": 0, - "no_copy": 0, - "oldfieldname": "customer_name", - "oldfieldtype": "Data", - "permlevel": 0, - "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 - }, + "bold": 1, + "fieldname": "customer_name", + "fieldtype": "Data", + "label": "Customer Name", + "oldfieldname": "customer_name", + "oldfieldtype": "Data", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "project", - "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": "Project", - "length": 0, - "no_copy": 0, - "options": "Project", - "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 - }, + "fieldname": "project", + "fieldtype": "Link", + "label": "Project", + "options": "Project" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "company", - "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": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "section_break_19", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "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 - }, + "collapsible": 1, + "fieldname": "section_break_19", + "fieldtype": "Section Break", + "label": "Resolution" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:!doc.__islocal", - "fetch_if_empty": 0, - "fieldname": "resolution_details", - "fieldtype": "Text Editor", - "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 Details", - "length": 0, - "no_copy": 1, - "oldfieldname": "resolution_details", - "oldfieldtype": "Text", - "permlevel": 0, - "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 - }, + "depends_on": "eval:!doc.__islocal", + "fieldname": "resolution_details", + "fieldtype": "Text Editor", + "label": "Resolution Details", + "no_copy": 1, + "oldfieldname": "resolution_details", + "oldfieldtype": "Text" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:!doc.__islocal", - "fetch_if_empty": 0, - "fieldname": "column_break1", - "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, - "oldfieldtype": "Column Break", - "permlevel": 0, - "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 - }, + "depends_on": "eval:!doc.__islocal", + "fieldname": "column_break1", + "fieldtype": "Column Break", + "oldfieldtype": "Column Break", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Today", - "fetch_if_empty": 0, - "fieldname": "opening_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Opening Date", - "length": 0, - "no_copy": 1, - "oldfieldname": "opening_date", - "oldfieldtype": "Date", - "permlevel": 0, - "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 - }, + "default": "Today", + "fieldname": "opening_date", + "fieldtype": "Date", + "label": "Opening Date", + "no_copy": 1, + "oldfieldname": "opening_date", + "oldfieldtype": "Date", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "opening_time", - "fieldtype": "Time", - "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": "Opening Time", - "length": 0, - "no_copy": 1, - "oldfieldname": "opening_time", - "oldfieldtype": "Time", - "permlevel": 0, - "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 - }, + "fieldname": "opening_time", + "fieldtype": "Time", + "label": "Opening Time", + "no_copy": 1, + "oldfieldname": "opening_time", + "oldfieldtype": "Time", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:!doc.__islocal", - "fetch_if_empty": 0, - "fieldname": "resolution_date", - "fieldtype": "Datetime", - "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 Date", - "length": 0, - "no_copy": 1, - "oldfieldname": "resolution_date", - "oldfieldtype": "Date", - "permlevel": 0, - "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 - }, + "depends_on": "eval:!doc.__islocal", + "fieldname": "resolution_date", + "fieldtype": "Datetime", + "label": "Resolution Date", + "no_copy": 1, + "oldfieldname": "resolution_date", + "oldfieldtype": "Date", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "content_type", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Content Type", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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 - }, + "fieldname": "content_type", + "fieldtype": "Data", + "hidden": 1, + "label": "Content Type" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "attachment", - "fieldtype": "Attach", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Attachment", - "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 - }, + "fieldname": "attachment", + "fieldtype": "Attach", + "hidden": 1, + "label": "Attachment" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "via_customer_portal", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Via Customer Portal", - "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 + "fieldname": "via_customer_portal", + "fieldtype": "Check", + "label": "Via Customer Portal" } - ], - "has_web_view": 0, - "hide_toolbar": 0, - "icon": "fa fa-ticket", - "idx": 7, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-04-23 18:04:42.039620", + ], + "icon": "fa fa-ticket", + "idx": 7, + "modified": "2019-05-03 11:11:50.495619", "modified_by": "Administrator", - "module": "Support", - "name": "Issue", - "owner": "Administrator", + "module": "Support", + "name": "Issue", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Support Team", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Support Team", + "share": 1, "write": 1 } - ], - "quick_entry": 1, - "read_only": 0, - "search_fields": "status,customer,subject,raised_by", - "show_name_in_global_search": 0, - "sort_order": "ASC", - "timeline_field": "customer", - "title_field": "subject", - "track_changes": 0, - "track_seen": 1, - "track_views": 0 + ], + "quick_entry": 1, + "search_fields": "status,customer,subject,raised_by", + "sort_order": "ASC", + "timeline_field": "customer", + "title_field": "subject", + "track_seen": 1 } \ No newline at end of file diff --git a/erpnext/support/doctype/service_level/service_level.json b/erpnext/support/doctype/service_level/service_level.json index 2dd335e2cc..9dc1a8d373 100644 --- a/erpnext/support/doctype/service_level/service_level.json +++ b/erpnext/support/doctype/service_level/service_level.json @@ -1,488 +1,118 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, "autoname": "field:service_level", - "beta": 0, "creation": "2018-11-19 12:44:30.407502", - "custom": 0, - "docstatus": 0, "doctype": "DocType", - "document_type": "", "editable_grid": 1, "engine": "InnoDB", + "field_order": [ + "service_level", + "employee_group", + "column_break_2", + "holiday_list", + "response_and_resoution_time", + "response_time", + "resolution_time", + "column_break_9", + "response_time_period", + "resolution_time_period", + "section_break_01", + "support_and_resolution" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "service_level", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, "label": "Level", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, "unique": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "priority", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Priority", - "length": 0, - "no_copy": 0, - "options": "Low\nMedium\nHigh", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "column_break_2", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "holiday_list", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, "label": "Holiday List (ignored during SLA calculation)", - "length": 0, - "no_copy": 0, "options": "Holiday List", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "employee_group", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, "label": "Employee Group", - "length": 0, - "no_copy": 0, - "options": "Employee Group", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Employee Group" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "response_and_resoution_time", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Response and Resoution Time", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Response and Resoution Time" }, { - "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 + "reqd": 1 }, { - "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 + "reqd": 1 }, { - "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 + "fieldtype": "Column Break" }, { - "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 + "reqd": 1 }, { - "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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", "fieldname": "section_break_01", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Support and Resolution", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Support and Resolution" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "support_and_resolution", "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Support and Resolution", - "length": 0, - "no_copy": 0, "options": "Service Day", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 } ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-03-04 12:55:53.215841", + "modified": "2019-05-03 01:09:43.571945", "modified_by": "Administrator", "module": "Support", "name": "Service Level", - "name_case": "", "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, "create": 1, "delete": 1, "email": 1, "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "System Manager", - "set_user_permissions": 0, "share": 1, - "submit": 0, "write": 1 } ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 + "sort_order": "DESC" } \ No newline at end of file diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js index 884e3eb52f..66ec2f3ef2 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js @@ -17,5 +17,16 @@ frappe.ui.form.on('Service Level Agreement', { frm.refresh(); } }); - } + }, + + customer: function(frm) { + frm.doc.service_level_agreement_name = null; + frm.doc.service_level_agreement_name = frm.doc.priority + ': ' + frm.doc.customer; + }, + + default_service_level_agreement: function(frm) { + frm.doc.service_level_agreement_name = null; + frm.doc.service_level_agreement_name = frm.doc.priority + ': Default Service Level Agreement'; + }, + }); diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index 27d7ad5ae2..67400a1288 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -1,764 +1,207 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "Prompt", - "beta": 0, + "autoname": "field:service_level_agreement_name", "creation": "2018-12-26 21:08:15.448812", - "custom": 0, - "docstatus": 0, "doctype": "DocType", - "document_type": "", "editable_grid": 1, "engine": "InnoDB", + "field_order": [ + "service_level_agreement_name", + "customer", + "default_service_level_agreement", + "holiday_list", + "column_break_2", + "service_level", + "priority", + "employee_group", + "agreement_details_section", + "start_date", + "agreement_status", + "column_break_7", + "end_date", + "response_and_resolution_time_section", + "response_time", + "resolution_time", + "column_break_16", + "response_time_period", + "resolution_time_period", + "support_and_resolution_section_break", + "support_and_resolution" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", "depends_on": "eval: !doc.default_service_level_agreement", - "fetch_if_empty": 0, "fieldname": "customer", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Customer", - "length": 0, - "no_copy": 0, "options": "Customer", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "set_only_once": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval: !doc.customer", - "fetch_if_empty": 0, "fieldname": "default_service_level_agreement", "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Default Service Level Agreement", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "set_only_once": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "service_level", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, "label": "Service Level", - "length": 0, - "no_copy": 0, "options": "Service Level", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "set_only_once": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fetch_from": "service_level.holiday_list", - "fetch_if_empty": 0, "fieldname": "holiday_list", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Holiday List", - "length": 0, - "no_copy": 0, "options": "Holiday List", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "column_break_2", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldtype": "Column Break" }, { - "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, + "fieldtype": "Select", "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 + "options": "Low\nMedium\nHigh", + "reqd": 1, + "set_only_once": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fetch_from": "service_level.employee_group", - "fetch_if_empty": 0, "fieldname": "employee_group", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Employee Group", - "length": 0, - "no_copy": 0, "options": "Employee Group", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "collapsible_depends_on": "", - "columns": 0, "depends_on": "eval: !doc.default_service_level_agreement", - "fetch_if_empty": 0, "fieldname": "agreement_details_section", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Agreement Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Agreement Details" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval: !doc.default_service_level_agreement", - "fetch_if_empty": 0, "fieldname": "start_date", "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Start Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Start Date" }, { - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval: !doc.default_contract", - "fetch_if_empty": 0, "fieldname": "column_break_7", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval: !doc.default_service_level_agreement", - "fetch_if_empty": 0, "fieldname": "end_date", "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "End Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "End Date" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "response_and_resolution_time_section", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Response and Resolution Time", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Response and Resolution Time" }, { - "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 + "read_only": 1 }, { - "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 + "read_only": 1 }, { - "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 + "fieldtype": "Column Break" }, { - "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 + "read_only": 1 }, { - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, "collapsible": 1, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "support_and_resolution_section_break", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Support and Resolution", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Support and Resolution" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "support_and_resolution", "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Support and Resolution", - "length": 0, - "no_copy": 0, "options": "Service Day", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 + }, + { + "fieldname": "service_level_agreement_name", + "fieldtype": "Data", + "label": "Service Level Agreement Name", + "read_only": 1, + "unique": 1 } ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-03-17 22:36:53.576464", + "modified": "2019-05-03 01:50:47.135540", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", - "name_case": "", "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, "create": 1, "delete": 1, "email": 1, "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "System Manager", - "set_user_permissions": 0, "share": 1, - "submit": 0, "write": 1 }, { - "amend": 0, - "cancel": 0, "create": 1, "delete": 1, "email": 1, "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "All", - "set_user_permissions": 0, "share": 1, - "submit": 0, "write": 1 } ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index 911d06905b..a4db83563a 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -16,6 +16,9 @@ class ServiceLevelAgreement(Document): frappe.throw(_("A Default Service Level Agreement already exists.")) def validate(self): + if not frm.doc.customer and not frm.doc.default_service_level_agreement: + frappe.throw(_("Select a Customer or set as Default Service Level Agreement.")) + if not self.default_service_level_agreement: if not (self.start_date and self.end_date): frappe.throw(_("Enter Start and End Date for the Agreement.")) From 898ab61dd4f9f1f60a7dc10275471ed7799a79cf Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sat, 4 May 2019 23:16:02 +0530 Subject: [PATCH 02/92] fix: Child table for priority --- erpnext/support/doctype/issue/issue.json | 10 +-- erpnext/support/doctype/issue/issue.py | 35 ++++---- .../doctype/service_level/service_level.json | 45 +++-------- .../doctype/service_level/service_level.py | 79 ++++++++++++++----- .../service_level_agreement.js | 30 +++++-- .../service_level_agreement.json | 48 ++--------- .../service_level_agreement.py | 43 ++++++---- .../service_level_priority/__init__.py | 0 .../service_level_priority.json | 74 +++++++++++++++++ .../service_level_priority.py | 10 +++ 10 files changed, 233 insertions(+), 141 deletions(-) create mode 100644 erpnext/support/doctype/service_level_priority/__init__.py create mode 100644 erpnext/support/doctype/service_level_priority/service_level_priority.json create mode 100644 erpnext/support/doctype/service_level_priority/service_level_priority.py diff --git a/erpnext/support/doctype/issue/issue.json b/erpnext/support/doctype/issue/issue.json index 2e23b09a40..9639702e24 100644 --- a/erpnext/support/doctype/issue/issue.json +++ b/erpnext/support/doctype/issue/issue.json @@ -14,12 +14,12 @@ "raised_by", "cb00", "status", - "service_level_agreement", "priority", "issue_type", "sb_details", "description", "service_level_section", + "service_level_agreement", "response_by", "cb", "agreement_status", @@ -115,8 +115,7 @@ "fieldtype": "Select", "in_standard_filter": 1, "label": "Priority", - "options": "Low\nMedium\nHigh", - "reqd": 1 + "options": "Low\nMedium\nHigh" }, { "fieldname": "issue_type", @@ -151,7 +150,8 @@ "fieldname": "service_level_agreement", "fieldtype": "Link", "label": "Service Level Agreement", - "options": "Service Level Agreement" + "options": "Service Level Agreement", + "read_only": 1 }, { "fieldname": "response_by", @@ -321,7 +321,7 @@ ], "icon": "fa fa-ticket", "idx": 7, - "modified": "2019-05-03 11:11:50.495619", + "modified": "2019-05-03 14:36:19.117560", "modified_by": "Administrator", "module": "Support", "name": "Issue", diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index d626def665..0ff37d7e31 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -126,25 +126,29 @@ class Issue(Document): return replicated_issue.name def before_insert(self): - self.set_response_and_resolution_time() + self.set_response_and_resolution_time(priority=self.priority) - def set_response_and_resolution_time(self): - service_level_agreement = get_active_service_level_agreement_for(self.customer) + def set_response_and_resolution_time(self, priority=None): + service_level_agreement = get_active_service_level_agreement_for(self.customer, priority) if service_level_agreement: self.service_level_agreement = service_level_agreement.name - self.priority = service_level_agreement.priority - - if not self.service_level_agreement: return + else: + return service_level = frappe.get_doc("Service Level", service_level_agreement.service_level) + priority = service_level.get_service_level_priority(priority) + priority.update({ + "support_and_resolution": service_level.support_and_resolution, + "holiday_list": service_level.holiday_list + }) if not self.creation: self.creation = now_datetime() start_date_time = get_datetime(self.creation) - self.response_by = get_expected_time_for('response', service_level, start_date_time) - self.resolution_by = get_expected_time_for('resolution', service_level, start_date_time) + 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) def get_expected_time_for(parameter, service_level, start_date_time): current_date_time = start_date_time @@ -154,11 +158,11 @@ def get_expected_time_for(parameter, service_level, start_date_time): # lets assume response time is in days by default if parameter == 'response': - allotted_days = service_level.response_time - time_period = service_level.response_time_period + allotted_days = service_level.get("response_time") + time_period = service_level.get("response_time_period") elif parameter == 'resolution': - allotted_days = service_level.resolution_time - time_period = service_level.resolution_time_period + allotted_days = service_level.get("resolution_time") + time_period = service_level.get("resolution_time_period") else: frappe.throw(_("{0} parameter is invalid".format(parameter))) @@ -172,13 +176,13 @@ 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 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({ 'start_time': service.start_time, 'end_time': service.end_time, }) - holidays = get_holidays(service_level.holiday_list) + holidays = get_holidays(service_level.get("holiday_list")) weekdays = get_weekdays() while not expected_time_is_set: @@ -248,14 +252,12 @@ def set_multiple_status(names, status): for name in names: set_status(name, status) - @frappe.whitelist() def set_status(name, status): st = frappe.get_doc("Issue", name) st.status = status st.save() - def auto_close_tickets(): """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 @@ -295,6 +297,7 @@ def make_task(source_name, target_doc=None): "doctype": "Task" } }, target_doc) + @frappe.whitelist() def make_issue_from_communication(communication, ignore_communication_links=False): """ raise a issue from email """ diff --git a/erpnext/support/doctype/service_level/service_level.json b/erpnext/support/doctype/service_level/service_level.json index 9dc1a8d373..fb4e74780d 100644 --- a/erpnext/support/doctype/service_level/service_level.json +++ b/erpnext/support/doctype/service_level/service_level.json @@ -10,11 +10,7 @@ "column_break_2", "holiday_list", "response_and_resoution_time", - "response_time", - "resolution_time", - "column_break_9", - "response_time_period", - "resolution_time_period", + "priority", "section_break_01", "support_and_resolution" ], @@ -51,36 +47,6 @@ "fieldtype": "Section Break", "label": "Response and Resoution Time" }, - { - "fieldname": "response_time", - "fieldtype": "Int", - "label": "Response Time", - "reqd": 1 - }, - { - "fieldname": "resolution_time", - "fieldtype": "Int", - "label": "Resolution Time", - "reqd": 1 - }, - { - "fieldname": "column_break_9", - "fieldtype": "Column Break" - }, - { - "fieldname": "response_time_period", - "fieldtype": "Select", - "label": "Response Time Period", - "options": "Hour\nDay\nWeek", - "reqd": 1 - }, - { - "fieldname": "resolution_time_period", - "fieldtype": "Select", - "label": "Resolution Time Period", - "options": "Hour\nDay\nWeek", - "reqd": 1 - }, { "fieldname": "section_break_01", "fieldtype": "Section Break", @@ -92,9 +58,16 @@ "label": "Support and Resolution", "options": "Service Day", "reqd": 1 + }, + { + "fieldname": "priority", + "fieldtype": "Table", + "label": "Priority", + "options": "Service Level Priority", + "reqd": 1 } ], - "modified": "2019-05-03 01:09:43.571945", + "modified": "2019-05-04 13:08:33.381734", "modified_by": "Administrator", "module": "Support", "name": "Service Level", diff --git a/erpnext/support/doctype/service_level/service_level.py b/erpnext/support/doctype/service_level/service_level.py index 4b41e53560..5389afb3e6 100644 --- a/erpnext/support/doctype/service_level/service_level.py +++ b/erpnext/support/doctype/service_level/service_level.py @@ -12,35 +12,78 @@ from frappe.utils import get_weekdays class ServiceLevel(Document): def validate(self): + self.check_priorities() + self.check_support_and_resolution() + + def check_priorities(self): + priorities = [] + for priority in self.priority: + priorities.append(priority.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))) + + 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))) + + if not len(set(priorities)) == len(priorities): + repeated_priority = get_repeated(priorities) + frappe.throw(_("Priority {0} has been repeated twice.".format(repeated_priority))) + + # Check if values for all the priority options is set + priority_count = ([field.options for field in frappe.get_meta("Service Level Priority").fields if field.fieldname=='priority'][0]).split("\n") + if not len(set(priorities)) == len(priority_count): + frappe.throw(_("Set values for all the Priorities.")) + + def check_support_and_resolution(self): week = get_weekdays() indexes = [] - - self.check_response_and_resolution_time() + support_days = [] for support_and_resolution in self.support_and_resolution: indexes.append(week.index(support_and_resolution.workday)) + support_days.append(support_and_resolution.workday) support_and_resolution.idx = week.index(support_and_resolution.workday) + 1 start_time, end_time = (datetime.strptime(support_and_resolution.start_time, '%H:%M:%S').time(), datetime.strptime(support_and_resolution.end_time, '%H:%M:%S').time()) if start_time > end_time: frappe.throw(_("Start Time can't be greater than End Time for {0}.".format(support_and_resolution.workday))) + if not len(set(indexes)) == len(indexes): - frappe.throw(_("Workday has been repeated twice")) + repeated_days = get_repeated(support_days) + frappe.throw(_("Workday {0} has been repeated twice".format(repeated_days))) - def check_response_and_resolution_time(self): - if self.response_time_period == "Hour": - response = self.response_time * 0.0416667 - elif self.response_time_period == "Day": - response = self.response_time - elif self.response_time_period == "Week": - response = self.response_time * 7 + def get_service_level_priority(self, priority): + priority = frappe.get_doc("Service Level Priority", {"priority": priority, "parent": self.name}) - if self.resolution_time_period == "Hour": - resolution = self.resolution_time * 0.0416667 - elif self.resolution_time_period == "Day": - resolution = self.resolution_time - elif self.resolution_time_period == "Week": - resolution = self.resolution_time * 7 + return frappe._dict({ + "priority": priority.priority, + "response_time": priority.response_time, + "response_time_period": priority.response_time_period, + "resolution_time": priority.resolution_time, + "response_time_period": priority.resolution_time_period + }) - if response > resolution: - frappe.throw(_("Response Time can't be greater than Resolution Time")) \ No newline at end of file +def get_repeated(values): + unique_list = [] + diff = [] + for value in values: + if value not in unique_list: + unique_list.append(value) + else: + diff.append(value) + return " ".join(diff) diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js index 66ec2f3ef2..92d7abdc63 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js @@ -11,7 +11,11 @@ frappe.ui.form.on('Service Level Agreement', { name: frm.doc.service_level }, callback: function(data){ - for (var i = 0; i < data.message.support_and_resolution.length; i++){ + console.log(data); + for (var i in data.message.priority){ + frm.add_child("priority", data.message.priority[i]); + } + for (var i in data.message.support_and_resolution){ frm.add_child("support_and_resolution", data.message.support_and_resolution[i]); } frm.refresh(); @@ -19,14 +23,24 @@ frappe.ui.form.on('Service Level Agreement', { }); }, - customer: function(frm) { + validate: function(frm) { frm.doc.service_level_agreement_name = null; - frm.doc.service_level_agreement_name = frm.doc.priority + ': ' + frm.doc.customer; - }, - - default_service_level_agreement: function(frm) { - frm.doc.service_level_agreement_name = null; - frm.doc.service_level_agreement_name = frm.doc.priority + ': Default Service Level Agreement'; + var sla_name = 'Default Service Level Agreement'; + if (frm.doc.customer){ + sla_name = frm.doc.customer; + } + frm.doc.service_level_agreement_name = sla_name; }, + priority: function(frm) { + if (!frm.doc.__is_local) { + frappe.call({ + "method": "erpnext.support.service_level_agreement.service_level_agreement.get_active_service_level_agreement_for", + "args": { + "customer": frm.doc.customer, + "priority": frm.doc.priority + } + }) + } + } }); diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index 67400a1288..30a8bfdbba 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -11,7 +11,6 @@ "holiday_list", "column_break_2", "service_level", - "priority", "employee_group", "agreement_details_section", "start_date", @@ -19,11 +18,7 @@ "column_break_7", "end_date", "response_and_resolution_time_section", - "response_time", - "resolution_time", - "column_break_16", - "response_time_period", - "resolution_time_period", + "priority", "support_and_resolution_section_break", "support_and_resolution" ], @@ -66,11 +61,9 @@ }, { "fieldname": "priority", - "fieldtype": "Select", + "fieldtype": "Table", "label": "Priority", - "options": "Low\nMedium\nHigh", - "reqd": 1, - "set_only_once": 1 + "options": "Service Level Priority" }, { "fetch_from": "service_level.employee_group", @@ -113,42 +106,11 @@ "label": "End Date" }, { + "collapsible": 1, "fieldname": "response_and_resolution_time_section", "fieldtype": "Section Break", "label": "Response and Resolution Time" }, - { - "fetch_from": "service_level.response_time", - "fieldname": "response_time", - "fieldtype": "Int", - "label": "Response Time", - "read_only": 1 - }, - { - "fetch_from": "service_level.resolution_time", - "fieldname": "resolution_time", - "fieldtype": "Int", - "label": "Resolution Time", - "read_only": 1 - }, - { - "fieldname": "column_break_16", - "fieldtype": "Column Break" - }, - { - "fetch_from": "service_level.response_time_period", - "fieldname": "response_time_period", - "fieldtype": "Data", - "label": "Response Time Period", - "read_only": 1 - }, - { - "fetch_from": "service_level.resolution_time_period", - "fieldname": "resolution_time_period", - "fieldtype": "Data", - "label": "Resolution Time Period", - "read_only": 1 - }, { "collapsible": 1, "fieldname": "support_and_resolution_section_break", @@ -170,7 +132,7 @@ "unique": 1 } ], - "modified": "2019-05-03 01:50:47.135540", + "modified": "2019-05-04 13:11:21.373147", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index a4db83563a..e879b4ae68 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -9,21 +9,20 @@ from frappe import _ class ServiceLevelAgreement(Document): - def before_insert(self): - if self.default_service_level_agreement: - doc = frappe.get_list("Service Level Agreement", filters=[{"default_service_level_agreement": "1"}]) - if doc: - frappe.throw(_("A Default Service Level Agreement already exists.")) - def validate(self): - if not frm.doc.customer and not frm.doc.default_service_level_agreement: + if not (self.customer or self.default_service_level_agreement): frappe.throw(_("Select a Customer or set as Default Service Level Agreement.")) - if not self.default_service_level_agreement: + if self.default_service_level_agreement: + if frappe.db.exists("Service Level Agreement", {"default_service_level_agreement": "1"}): + frappe.throw(_("A Default Service Level Agreement already exists.")) + else: if not (self.start_date and self.end_date): frappe.throw(_("Enter Start and End Date for the Agreement.")) if self.start_date >= self.end_date: frappe.throw(_("Start Date of Agreement can't be greater than or equal to End Date.")) + if self.end_date < frappe.utils.getdate(): + frappe.throw(_("End Date of Agreement can't be less than today.")) def check_agreement_status(): service_level_agreements = frappe.get_list("Service Level Agreement", filters=[ @@ -37,12 +36,26 @@ def check_agreement_status(): service_level_agreement.agreement_status = "Expired" service_level_agreement.save() -def get_active_service_level_agreement_for(customer): - agreement = frappe.get_list("Service Level Agreement", - filters=[{"agreement_status": "Active"}], - or_filters=[{'customer': customer},{"default_service_level_agreement": "1"}], - fields=["name", "service_level", "holiday_list", "priority"], - order_by='customer DESC', - limit=1) +@frappe.whitelist() +def get_active_service_level_agreement_for(customer, priority): + + agreement = frappe.db.sql(""" + select `tabService Level Agreement`.name, `tabService Level Agreement`.service_level, + `tabService Level Agreement`.holiday_list + from `tabService Level Agreement` + inner join `tabService Level Priority` + on `tabService Level Agreement`.name=`tabService Level Priority`.parent where + ( + `tabService Level Agreement`.customer='{0}' and + `tabService Level Agreement`.agreement_status='Active' and + `tabService Level Priority`.priority='{1}' + ) or + ( + `tabService Level Agreement`.default_service_level_agreement='1' + ) + limit 1 + """.format(customer, priority), as_dict=True, debug=True) + + print(agreement) return agreement[0] if agreement else None \ No newline at end of file diff --git a/erpnext/support/doctype/service_level_priority/__init__.py b/erpnext/support/doctype/service_level_priority/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/support/doctype/service_level_priority/service_level_priority.json b/erpnext/support/doctype/service_level_priority/service_level_priority.json new file mode 100644 index 0000000000..6693649c25 --- /dev/null +++ b/erpnext/support/doctype/service_level_priority/service_level_priority.json @@ -0,0 +1,74 @@ +{ + "creation": "2019-05-04 05:54:03.658991", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "priority", + "sb_00", + "response_time", + "response_time_period", + "cb_00", + "resolution_time", + "resolution_time_period" + ], + "fields": [ + { + "columns": 2, + "fieldname": "priority", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Priority", + "options": "Low\nMedium\nHigh" + }, + { + "fieldname": "sb_00", + "fieldtype": "Section Break" + }, + { + "columns": 2, + "fieldname": "response_time", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Response Time" + }, + { + "columns": 2, + "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" + } + ], + "istable": 1, + "modified": "2019-05-04 06:04:32.956731", + "modified_by": "Administrator", + "module": "Support", + "name": "Service Level Priority", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "ASC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/support/doctype/service_level_priority/service_level_priority.py b/erpnext/support/doctype/service_level_priority/service_level_priority.py new file mode 100644 index 0000000000..0c0fe4a066 --- /dev/null +++ b/erpnext/support/doctype/service_level_priority/service_level_priority.py @@ -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 From b3070ca7653a9b349350dbbd4923acec5e630cf9 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 5 May 2019 12:19:08 +0530 Subject: [PATCH 03/92] fix: display sla indicators at the top --- erpnext/support/doctype/issue/issue.js | 63 ++++++++++--------- erpnext/support/doctype/issue/issue.py | 5 ++ .../service_level_agreement.json | 7 ++- 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index 97b34e9401..d31ae4a4c4 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -1,12 +1,13 @@ frappe.ui.form.on("Issue", { onload: function(frm) { frm.email_field = "raised_by"; - if (frm.doc.service_level_agreement) { - set_time_to_resolve_and_response(frm); - } }, refresh: function (frm) { + if (frm.doc.service_level_agreement) { + set_time_to_resolve_and_response(frm); + } + if (frm.doc.status !== "Closed") { frm.add_custom_button(__("Close"), function () { frm.set_value("status", "Closed"); @@ -27,6 +28,16 @@ frappe.ui.form.on("Issue", { } }, + priority: function(frm) { + if (frm.doc.service_level_agreement) { + frm.call('change_sla_priority', { + "priority": frm.doc.priority + }).then(() => { + frm.refresh() + }); + } + }, + timeline_refresh: function(frm) { // create button for "Help Article" if(frappe.model.can_create('Help Article')) { @@ -81,36 +92,30 @@ frappe.ui.form.on("Issue", { }); function set_time_to_resolve_and_response(frm) { + frm.dashboard.clear_headline(); - const customer = frm.fields_dict['customer'].$wrapper; - const email_account = frm.fields_dict['email_account'].$wrapper; + var time_to_respond = get_time_left(frm.doc.response_by); + var time_to_resolve = get_time_left(frm.doc.resolution_by); - const time_to_respond = $(get_time_left_element(__('Time To Respond'), frm.doc.response_by)); - const time_to_resolve = $(get_time_left_element(__('Time To Resolve'), frm.doc.resolution_by)); - - time_to_respond.insertAfter(customer); - time_to_resolve.insertAfter(email_account); -} - -function get_time_left_element(label, timestamp) { - $('.'+ frappe.scrub(label) +'').remove(); - return ` -
-
-
- -
-
- -
-
-
- `; + frm.dashboard.set_headline_alert( + '
' + + '
' + + ' ' + + '
' + + '
' + + ' ' + + '
' + + '
' + ); } function get_time_left(timestamp) { 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'); + var indicator = "green"; + if (diff_display == '00:00') { + indicator = "red"; + } + return {"diff_display": diff_display, + "indicator": indicator}; } diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 0ff37d7e31..66eb55ab63 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -150,6 +150,11 @@ class Issue(Document): 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) + @frappe.whitelist() + def change_sla_priority(self, priority): + self.set_response_and_resolution_time(priority=priority) + self.save(ignore_permissions=True) + def get_expected_time_for(parameter, service_level, start_date_time): current_date_time = start_date_time expected_time = current_date_time diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index 30a8bfdbba..b81d4f4386 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -27,6 +27,7 @@ "depends_on": "eval: !doc.default_service_level_agreement", "fieldname": "customer", "fieldtype": "Link", + "in_list_view": 1, "label": "Customer", "options": "Customer", "set_only_once": 1 @@ -35,6 +36,7 @@ "depends_on": "eval: !doc.customer", "fieldname": "default_service_level_agreement", "fieldtype": "Check", + "in_list_view": 1, "label": "Default Service Level Agreement", "set_only_once": 1 }, @@ -121,8 +123,7 @@ "fieldname": "support_and_resolution", "fieldtype": "Table", "label": "Support and Resolution", - "options": "Service Day", - "read_only": 1 + "options": "Service Day" }, { "fieldname": "service_level_agreement_name", @@ -132,7 +133,7 @@ "unique": 1 } ], - "modified": "2019-05-04 13:11:21.373147", + "modified": "2019-05-05 12:17:02.793287", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", From ec54e3d8314c633dbc21416b75e3ddf124fc1542 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 5 May 2019 12:31:04 +0530 Subject: [PATCH 04/92] patch: migrate to new sla structure --- .../v12_0/move_parameters_to_priority.py | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 erpnext/patches/v12_0/move_parameters_to_priority.py diff --git a/erpnext/patches/v12_0/move_parameters_to_priority.py b/erpnext/patches/v12_0/move_parameters_to_priority.py new file mode 100644 index 0000000000..395d225a21 --- /dev/null +++ b/erpnext/patches/v12_0/move_parameters_to_priority.py @@ -0,0 +1,62 @@ +# Copyright (c) 2017, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + service_levels = frappe.get_list("Service Level") + for service_level in service_levels: + doc = frappe.get_doc("Service Level", service_level.name) + doc.append("priority", + { + "priority": "Low", + "response_time": doc.response_time, + "response_time_period": doc.resolution_time_period, + "resolution_time": doc.resolution_time, + "resolution_time_period": doc.resolution_time_period, + }, + { + "priority": "Medium", + "response_time": doc.response_time, + "response_time_period": doc.resolution_time_period, + "resolution_time": doc.resolution_time, + "resolution_time_period": doc.resolution_time_period, + }, + { + "priority": "High", + "response_time": doc.response_time, + "response_time_period": doc.resolution_time_period, + "resolution_time": doc.resolution_time, + "resolution_time_period": doc.resolution_time_period, + } + ) + doc.save(ignore_permissions=True) + + service_level_agreements = frappe.get_list("Service Level Agreement") + for service_level_agreement in service_level_agreements: + doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name) + doc.append("priority", + { + "priority": "Low", + "response_time": doc.response_time, + "response_time_period": doc.resolution_time_period, + "resolution_time": doc.resolution_time, + "resolution_time_period": doc.resolution_time_period, + }, + { + "priority": "Medium", + "response_time": doc.response_time, + "response_time_period": doc.resolution_time_period, + "resolution_time": doc.resolution_time, + "resolution_time_period": doc.resolution_time_period, + }, + { + "priority": "High", + "response_time": doc.response_time, + "response_time_period": doc.resolution_time_period, + "resolution_time": doc.resolution_time, + "resolution_time_period": doc.resolution_time_period, + } + ) + doc.save(ignore_permissions=True) \ No newline at end of file From 917e53419106b358e48e45f461fec46ae47e108a Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 5 May 2019 14:43:11 +0530 Subject: [PATCH 05/92] patch: fix to migrate to new sla structure --- erpnext/patches.txt | 1 + .../v12_0/move_parameters_to_priority.py | 82 +++++++------------ 2 files changed, 30 insertions(+), 53 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 01270e4779..9c74f27ec7 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -601,3 +601,4 @@ erpnext.patches.v11_1.set_salary_details_submittable erpnext.patches.v11_1.rename_depends_on_lwp execute:frappe.delete_doc("Report", "Inactive Items") erpnext.patches.v11_1.delete_scheduling_tool +erpnext.patches.v12_0.move_parameters_to_priority \ No newline at end of file diff --git a/erpnext/patches/v12_0/move_parameters_to_priority.py b/erpnext/patches/v12_0/move_parameters_to_priority.py index 395d225a21..bdecb31e42 100644 --- a/erpnext/patches/v12_0/move_parameters_to_priority.py +++ b/erpnext/patches/v12_0/move_parameters_to_priority.py @@ -5,58 +5,34 @@ from __future__ import unicode_literals import frappe def execute(): - service_levels = frappe.get_list("Service Level") - for service_level in service_levels: - doc = frappe.get_doc("Service Level", service_level.name) - doc.append("priority", - { - "priority": "Low", - "response_time": doc.response_time, - "response_time_period": doc.resolution_time_period, - "resolution_time": doc.resolution_time, - "resolution_time_period": doc.resolution_time_period, - }, - { - "priority": "Medium", - "response_time": doc.response_time, - "response_time_period": doc.resolution_time_period, - "resolution_time": doc.resolution_time, - "resolution_time_period": doc.resolution_time_period, - }, - { - "priority": "High", - "response_time": doc.response_time, - "response_time_period": doc.resolution_time_period, - "resolution_time": doc.resolution_time, - "resolution_time_period": doc.resolution_time_period, - } - ) - doc.save(ignore_permissions=True) + priorities = ["Low", "Medium", "High"] - service_level_agreements = frappe.get_list("Service Level Agreement") + service_levels = frappe.get_list("Service Level", + fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]) + for service_level in service_levels: + for value in priorities: + doc = frappe.get_doc({ + "doctype": "Service Level Priority", + "parent": service_level.name, + "parenttype": "Service Level", + "priority": value, + "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, + }).insert(ignore_permissions=True) + + service_level_agreements = frappe.get_list("Service Level Agreement", + fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]) for service_level_agreement in service_level_agreements: - doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name) - doc.append("priority", - { - "priority": "Low", - "response_time": doc.response_time, - "response_time_period": doc.resolution_time_period, - "resolution_time": doc.resolution_time, - "resolution_time_period": doc.resolution_time_period, - }, - { - "priority": "Medium", - "response_time": doc.response_time, - "response_time_period": doc.resolution_time_period, - "resolution_time": doc.resolution_time, - "resolution_time_period": doc.resolution_time_period, - }, - { - "priority": "High", - "response_time": doc.response_time, - "response_time_period": doc.resolution_time_period, - "resolution_time": doc.resolution_time, - "resolution_time_period": doc.resolution_time_period, - } - ) - doc.save(ignore_permissions=True) \ No newline at end of file + for value in priorities: + doc = frappe.get_doc({ + "doctype": "Service Level Priority", + "parent": service_level_agreement.name, + "parenttype": "Service Level Agreement", + "priority": value, + "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, + }).insert(ignore_permissions=True) \ No newline at end of file From 134ad616043aec932c17867c0e3bb566e9e9865b Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 5 May 2019 16:26:11 +0530 Subject: [PATCH 06/92] fix: patch fixes --- erpnext/patches.txt | 1 + erpnext/patches/v12_0/move_parameters_to_priority.py | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 9c74f27ec7..0cf630c4e8 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -601,4 +601,5 @@ erpnext.patches.v11_1.set_salary_details_submittable erpnext.patches.v11_1.rename_depends_on_lwp execute:frappe.delete_doc("Report", "Inactive Items") erpnext.patches.v11_1.delete_scheduling_tool +execute:frappe.reload_doc('support', 'doctype', 'service_level_priority') erpnext.patches.v12_0.move_parameters_to_priority \ No newline at end of file diff --git a/erpnext/patches/v12_0/move_parameters_to_priority.py b/erpnext/patches/v12_0/move_parameters_to_priority.py index bdecb31e42..9d031c379b 100644 --- a/erpnext/patches/v12_0/move_parameters_to_priority.py +++ b/erpnext/patches/v12_0/move_parameters_to_priority.py @@ -10,12 +10,13 @@ def execute(): service_levels = frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]) for service_level in service_levels: - for value in priorities: + for idx, value in enumerate(priorities): doc = frappe.get_doc({ "doctype": "Service Level Priority", "parent": service_level.name, "parenttype": "Service Level", "priority": value, + "idx": idx, "response_time": service_level.response_time, "response_time_period": service_level.response_time_period, "resolution_time": service_level.resolution_time, @@ -25,12 +26,13 @@ def execute(): service_level_agreements = frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]) for service_level_agreement in service_level_agreements: - for value in priorities: + for idx, value in enumerate(priorities): doc = frappe.get_doc({ "doctype": "Service Level Priority", "parent": service_level_agreement.name, "parenttype": "Service Level Agreement", "priority": value, + "idx": idx, "response_time": service_level_agreement.response_time, "response_time_period": service_level_agreement.response_time_period, "resolution_time": service_level_agreement.resolution_time, From fbb7ea485643457178ec8a838b2ba3bc5b713c15 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 5 May 2019 17:21:38 +0530 Subject: [PATCH 07/92] fix: patch fix --- .../v12_0/move_parameters_to_priority.py | 82 ++++++++++++------- 1 file changed, 54 insertions(+), 28 deletions(-) diff --git a/erpnext/patches/v12_0/move_parameters_to_priority.py b/erpnext/patches/v12_0/move_parameters_to_priority.py index 9d031c379b..a08ab6dcc9 100644 --- a/erpnext/patches/v12_0/move_parameters_to_priority.py +++ b/erpnext/patches/v12_0/move_parameters_to_priority.py @@ -7,34 +7,60 @@ import frappe def execute(): priorities = ["Low", "Medium", "High"] - service_levels = frappe.get_list("Service Level", - fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]) + service_levels = frappe.get_list("Service Level") for service_level in service_levels: - for idx, value in enumerate(priorities): - doc = frappe.get_doc({ - "doctype": "Service Level Priority", - "parent": service_level.name, - "parenttype": "Service Level", - "priority": value, - "idx": idx, - "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, - }).insert(ignore_permissions=True) + doc = frappe.get_doc("Service Level", service_level) + doc.update({ + "priority": [ + { + "priority": "Low", + "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, + }, + { + "priority": "Medium", + "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, + }, + { + "priority": "High", + "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, + } + ] + }) - service_level_agreements = frappe.get_list("Service Level Agreement", - fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]) + service_level_agreements = frappe.get_list("Service Level Agreement") for service_level_agreement in service_level_agreements: - for idx, value in enumerate(priorities): - doc = frappe.get_doc({ - "doctype": "Service Level Priority", - "parent": service_level_agreement.name, - "parenttype": "Service Level Agreement", - "priority": value, - "idx": idx, - "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, - }).insert(ignore_permissions=True) \ No newline at end of file + doc = frappe.get_doc("Service Level Agreement", service_level_agreement) + doc.update({ + "priority": [ + { + "priority": "Low", + "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, + }, + { + "priority": "Medium", + "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, + }, + { + "priority": "High", + "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, + }, + ] + }) From f8b9c849a1067f420094206bacc7d0602272e321 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 5 May 2019 22:51:18 +0530 Subject: [PATCH 08/92] fix: test cases for sla --- .../v12_0/move_parameters_to_priority.py | 4 +- erpnext/support/doctype/issue/test_issue.py | 2 +- .../doctype/service_day/service_day.json | 178 ++---------------- .../doctype/service_level/service_level.json | 8 +- .../doctype/service_level/service_level.py | 34 ++-- .../service_level/test_service_level.py | 56 +++++- .../service_level_agreement.js | 21 +-- .../service_level_agreement.json | 22 +-- .../service_level_agreement.py | 6 +- .../test_service_level_agreement.py | 69 +++++-- .../service_level_priority.json | 2 +- 11 files changed, 160 insertions(+), 242 deletions(-) diff --git a/erpnext/patches/v12_0/move_parameters_to_priority.py b/erpnext/patches/v12_0/move_parameters_to_priority.py index a08ab6dcc9..71f341daed 100644 --- a/erpnext/patches/v12_0/move_parameters_to_priority.py +++ b/erpnext/patches/v12_0/move_parameters_to_priority.py @@ -11,7 +11,7 @@ def execute(): for service_level in service_levels: doc = frappe.get_doc("Service Level", service_level) doc.update({ - "priority": [ + "priorities": [ { "priority": "Low", "response_time": service_level.response_time, @@ -40,7 +40,7 @@ def execute(): for service_level_agreement in service_level_agreements: doc = frappe.get_doc("Service Level Agreement", service_level_agreement) doc.update({ - "priority": [ + "priorities": [ { "priority": "Low", "response_time": service_level_agreement.response_time, diff --git a/erpnext/support/doctype/issue/test_issue.py b/erpnext/support/doctype/issue/test_issue.py index 48ba1f6d3f..5266678fc0 100644 --- a/erpnext/support/doctype/issue/test_issue.py +++ b/erpnext/support/doctype/issue/test_issue.py @@ -68,6 +68,6 @@ def make_issue(creation=None, customer=None): "customer": customer, "raised_by": "test@example.com", "creation": creation - }).insert() + }).insert(ignore_permissions=True) return issue \ No newline at end of file diff --git a/erpnext/support/doctype/service_day/service_day.json b/erpnext/support/doctype/service_day/service_day.json index 8ed006dc40..68614b1807 100644 --- a/erpnext/support/doctype/service_day/service_day.json +++ b/erpnext/support/doctype/service_day/service_day.json @@ -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", - "custom": 0, - "docstatus": 0, "doctype": "DocType", - "document_type": "", "editable_grid": 1, "engine": "InnoDB", + "field_order": [ + "workday", + "section_break_2", + "start_time", + "column_break_3", + "end_time" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", "fieldname": "workday", "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, "label": "Workday", - "length": 0, - "no_copy": 0, - "options": "Monday\nTuesday\nWednesday\nThursday\nFriday\nSaturday\nSunday", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Monday\nTuesday\nWednesday\nThursday\nFriday\nSaturday\nSunday" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "section_break_2", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldtype": "Section Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "start_time", "fieldtype": "Time", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, - "label": "Start Time", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Start Time" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "column_break_3", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "end_time", "fieldtype": "Time", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, - "in_standard_filter": 0, - "label": "End Time", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "End Time" } ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, "istable": 1, - "max_attachments": 0, - "modified": "2019-03-04 12:55:36.403035", + "modified": "2019-05-05 19:15:08.999579", "modified_by": "Administrator", "module": "Support", "name": "Service Day", - "name_case": "", "owner": "Administrator", "permissions": [], "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/support/doctype/service_level/service_level.json b/erpnext/support/doctype/service_level/service_level.json index fb4e74780d..6718514712 100644 --- a/erpnext/support/doctype/service_level/service_level.json +++ b/erpnext/support/doctype/service_level/service_level.json @@ -10,7 +10,7 @@ "column_break_2", "holiday_list", "response_and_resoution_time", - "priority", + "priorities", "section_break_01", "support_and_resolution" ], @@ -60,14 +60,14 @@ "reqd": 1 }, { - "fieldname": "priority", + "fieldname": "priorities", "fieldtype": "Table", - "label": "Priority", + "label": "Priorities", "options": "Service Level Priority", "reqd": 1 } ], - "modified": "2019-05-04 13:08:33.381734", + "modified": "2019-05-05 19:29:56.975951", "modified_by": "Administrator", "module": "Support", "name": "Service Level", diff --git a/erpnext/support/doctype/service_level/service_level.py b/erpnext/support/doctype/service_level/service_level.py index 5389afb3e6..f48d927778 100644 --- a/erpnext/support/doctype/service_level/service_level.py +++ b/erpnext/support/doctype/service_level/service_level.py @@ -17,12 +17,14 @@ class ServiceLevel(Document): def check_priorities(self): priorities = [] - for priority in self.priority: - priorities.append(priority.priority) + 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.response_time_period == "Hour": response = priority.response_time * 0.0416667 elif priority.response_time_period == "Day": @@ -40,32 +42,39 @@ class ServiceLevel(Document): 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 twice.".format(repeated_priority))) + frappe.throw(_("Priority {0} has been repeated.".format(repeated_priority))) # Check if values for all the priority options is set priority_count = ([field.options for field in frappe.get_meta("Service Level Priority").fields if field.fieldname=='priority'][0]).split("\n") if not len(set(priorities)) == len(priority_count): - frappe.throw(_("Set values for all the Priorities.")) + frappe.throw(_("Set values for all the Priorities {0}.".format(" ".join(priority_count)))) def check_support_and_resolution(self): week = get_weekdays() - indexes = [] support_days = [] 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 + 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 start_time >= end_time: + frappe.throw(_("Start Time can't be greater than or equal to End Time \ + for {0}.".format(support_and_resolution.workday))) - if not len(set(indexes)) == len(indexes): + # Check for repeated workday + if not len(set(support_days)) == len(support_days): repeated_days = get_repeated(support_days) - frappe.throw(_("Workday {0} has been repeated twice".format(repeated_days))) + frappe.throw(_("Workday {0} has been repeated.".format(repeated_days))) def get_service_level_priority(self, priority): priority = frappe.get_doc("Service Level Priority", {"priority": priority, "parent": self.name}) @@ -75,7 +84,7 @@ class ServiceLevel(Document): "response_time": priority.response_time, "response_time_period": priority.response_time_period, "resolution_time": priority.resolution_time, - "response_time_period": priority.resolution_time_period + "resolution_time_period": priority.resolution_time_period }) def get_repeated(values): @@ -85,5 +94,6 @@ def get_repeated(values): if value not in unique_list: unique_list.append(value) else: - diff.append(value) + if value not in diff: + diff.append(value) return " ".join(diff) diff --git a/erpnext/support/doctype/service_level/test_service_level.py b/erpnext/support/doctype/service_level/test_service_level.py index 3843e31c0f..ba958f781c 100644 --- a/erpnext/support/doctype/service_level/test_service_level.py +++ b/erpnext/support/doctype/service_level/test_service_level.py @@ -22,12 +22,30 @@ def make_service_level(): "doctype": "Service Level", "service_level": "__Test Service Level", "holiday_list": "__Test Holiday List", - "priority": "Medium", "employee_group": employee_group, - "response_time": 4, - "response_time_period": "Hour", - "resolution_time": 6, - "resolution_time_period": "Hour", + "priorities": [ + { + "priority": "Low", + "response_time": 4, + "response_time_period": "Hour", + "resolution_time": 6, + "resolution_time_period": "Hour", + }, + { + "priority": "Medium", + "response_time": 4, + "response_time_period": "Hour", + "resolution_time": 6, + "resolution_time_period": "Hour", + }, + { + "priority": "High", + "response_time": 4, + "response_time_period": "Hour", + "resolution_time": 6, + "resolution_time_period": "Hour", + } + ], "support_and_resolution": [ { "workday": "Monday", @@ -75,12 +93,30 @@ def make_service_level(): "doctype": "Service Level", "service_level": "_Test Service Level", "holiday_list": "__Test Holiday List", - "priority": "Medium", "employee_group": employee_group, - "response_time": 2, - "response_time_period": "Day", - "resolution_time": 3, - "resolution_time_period": "Day", + "priorities": [ + { + "priority": "Low", + "response_time": 2, + "response_time_period": "Day", + "resolution_time": 3, + "resolution_time_period": "Day", + }, + { + "priority": "Medium", + "response_time": 2, + "response_time_period": "Day", + "resolution_time": 3, + "resolution_time_period": "Day", + }, + { + "priority": "High", + "response_time": 2, + "response_time_period": "Day", + "resolution_time": 3, + "resolution_time_period": "Day", + } + ], "support_and_resolution": [ { "workday": "Monday", diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js index 92d7abdc63..2da4b0387d 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js @@ -11,9 +11,8 @@ frappe.ui.form.on('Service Level Agreement', { name: frm.doc.service_level }, callback: function(data){ - console.log(data); - for (var i in data.message.priority){ - frm.add_child("priority", data.message.priority[i]); + for (var i in data.message.priorities){ + frm.add_child("priorities", data.message.priorities[i]); } for (var i in data.message.support_and_resolution){ frm.add_child("support_and_resolution", data.message.support_and_resolution[i]); @@ -24,23 +23,11 @@ frappe.ui.form.on('Service Level Agreement', { }, validate: function(frm) { - frm.doc.service_level_agreement_name = null; + frm.doc.sla_name = null; var sla_name = 'Default Service Level Agreement'; if (frm.doc.customer){ sla_name = frm.doc.customer; } - frm.doc.service_level_agreement_name = sla_name; + frm.doc.sla_name = sla_name; }, - - priority: function(frm) { - if (!frm.doc.__is_local) { - frappe.call({ - "method": "erpnext.support.service_level_agreement.service_level_agreement.get_active_service_level_agreement_for", - "args": { - "customer": frm.doc.customer, - "priority": frm.doc.priority - } - }) - } - } }); diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index b81d4f4386..b206fb33e4 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -1,11 +1,11 @@ { - "autoname": "field:service_level_agreement_name", + "autoname": "field:sla_name", "creation": "2018-12-26 21:08:15.448812", "doctype": "DocType", "editable_grid": 1, "engine": "InnoDB", "field_order": [ - "service_level_agreement_name", + "sla_name", "customer", "default_service_level_agreement", "holiday_list", @@ -18,7 +18,7 @@ "column_break_7", "end_date", "response_and_resolution_time_section", - "priority", + "priorities", "support_and_resolution_section_break", "support_and_resolution" ], @@ -61,12 +61,6 @@ "fieldname": "column_break_2", "fieldtype": "Column Break" }, - { - "fieldname": "priority", - "fieldtype": "Table", - "label": "Priority", - "options": "Service Level Priority" - }, { "fetch_from": "service_level.employee_group", "fieldname": "employee_group", @@ -126,14 +120,20 @@ "options": "Service Day" }, { - "fieldname": "service_level_agreement_name", + "fieldname": "priorities", + "fieldtype": "Table", + "label": "Priorities", + "options": "Service Level Priority" + }, + { + "fieldname": "sla_name", "fieldtype": "Data", "label": "Service Level Agreement Name", "read_only": 1, "unique": 1 } ], - "modified": "2019-05-05 12:17:02.793287", + "modified": "2019-05-05 20:24:57.557178", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index e879b4ae68..4fca708993 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -19,8 +19,10 @@ class ServiceLevelAgreement(Document): else: if not (self.start_date and self.end_date): frappe.throw(_("Enter Start and End Date for the Agreement.")) + if self.start_date >= self.end_date: frappe.throw(_("Start Date of Agreement can't be greater than or equal to End Date.")) + if self.end_date < frappe.utils.getdate(): frappe.throw(_("End Date of Agreement can't be less than today.")) @@ -54,8 +56,6 @@ def get_active_service_level_agreement_for(customer, priority): `tabService Level Agreement`.default_service_level_agreement='1' ) limit 1 - """.format(customer, priority), as_dict=True, debug=True) - - print(agreement) + """.format(customer, priority), as_dict=True) return agreement[0] if agreement else None \ No newline at end of file diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py index e5737e0303..b9d25e46f0 100644 --- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py @@ -16,18 +16,36 @@ def make_service_level_agreement(): # Default Service Level Agreement default_service_level_agreement = frappe.get_doc({ "doctype": "Service Level Agreement", - "name": "__Test Service Level Agreement", + "sla_name": "Default Service Level Agreement", "default_service_level_agreement": 1, "service_level": "__Test Service Level", "holiday_list": "__Test Holiday List", - "priority": "Medium", "employee_group": "_Test Employee Group", "start_date": frappe.utils.getdate(), "end_date": frappe.utils.add_to_date(frappe.utils.getdate(), days=100), - "response_time": 4, - "response_time_period": "Hour", - "resolution_time": 6, - "resolution_time_period": "Hour", + "priorities": [ + { + "priority": "Low", + "response_time": 4, + "response_time_period": "Hour", + "resolution_time": 6, + "resolution_time_period": "Hour", + }, + { + "priority": "Medium", + "response_time": 4, + "response_time_period": "Hour", + "resolution_time": 6, + "resolution_time_period": "Hour", + }, + { + "priority": "High", + "response_time": 4, + "response_time_period": "Hour", + "resolution_time": 6, + "resolution_time_period": "Hour", + } + ], "support_and_resolution": [ { "workday": "Monday", @@ -67,10 +85,9 @@ def make_service_level_agreement(): ] }) - default_service_level_agreement_exists = frappe.db.exists("Service Level Agreement", "__Test Service Level Agreement") + default_service_level_agreement_exists = frappe.db.exists("Service Level Agreement", "Default Service Level Agreement") if not default_service_level_agreement_exists: - default_service_level_agreement.insert() - + default_service_level_agreement.insert(ignore_permissions=True) customer = frappe.get_doc({ "doctype": "Customer", @@ -80,24 +97,42 @@ def make_service_level_agreement(): "territory": "Rest Of The World" }) if not frappe.db.exists("Customer", "_Test Customer"): - customer.insert() + customer.insert(ignore_permissions=True) else: customer = frappe.get_doc("Customer", "_Test Customer") service_level_agreement = frappe.get_doc({ "doctype": "Service Level Agreement", - "name": "_Test Service Level Agreement", + "sla_name": "_Test Service Level Agreement", "customer": customer.customer_name, "service_level": "_Test Service Level", "holiday_list": "__Test Holiday List", - "priority": "Medium", "employee_group": "_Test Employee Group", "start_date": frappe.utils.getdate(), "end_date": frappe.utils.add_to_date(frappe.utils.getdate(), days=100), - "response_time": 2, - "response_time_period": "Day", - "resolution_time": 3, - "resolution_time_period": "Day", + "priorities": [ + { + "priority": "Low", + "response_time": 2, + "response_time_period": "Day", + "resolution_time": 3, + "resolution_time_period": "Day", + }, + { + "priority": "Medium", + "response_time": 2, + "response_time_period": "Day", + "resolution_time": 3, + "resolution_time_period": "Day", + }, + { + "priority": "High", + "response_time": 2, + "response_time_period": "Day", + "resolution_time": 3, + "resolution_time_period": "Day", + } + ], "support_and_resolution": [ { "workday": "Monday", @@ -139,7 +174,7 @@ def make_service_level_agreement(): service_level_agreement_exists = frappe.db.exists("Service Level Agreement", "_Test Service Level Agreement") if not service_level_agreement_exists: - service_level_agreement.insert() + service_level_agreement.insert(ignore_permissions=True) return service_level_agreement.name else: return service_level_agreement_exists diff --git a/erpnext/support/doctype/service_level_priority/service_level_priority.json b/erpnext/support/doctype/service_level_priority/service_level_priority.json index 6693649c25..39cac9fdab 100644 --- a/erpnext/support/doctype/service_level_priority/service_level_priority.json +++ b/erpnext/support/doctype/service_level_priority/service_level_priority.json @@ -69,6 +69,6 @@ "permissions": [], "quick_entry": 1, "sort_field": "modified", - "sort_order": "ASC", + "sort_order": "DESC", "track_changes": 1 } \ No newline at end of file From 9faaa17d9d155bd257a8654289c8283ff499f807 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 5 May 2019 23:55:17 +0530 Subject: [PATCH 09/92] patch: fixes --- erpnext/patches.txt | 2 + .../v12_0/move_parameters_to_priority.py | 48 +++++++++---------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 0cf630c4e8..7acfe4c936 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -602,4 +602,6 @@ erpnext.patches.v11_1.rename_depends_on_lwp execute:frappe.delete_doc("Report", "Inactive Items") erpnext.patches.v11_1.delete_scheduling_tool execute:frappe.reload_doc('support', 'doctype', 'service_level_priority') +execute:frappe.reload_doc('support', 'doctype', 'service_level') +execute:frappe.reload_doc('support', 'doctype', 'service_level_agreement') erpnext.patches.v12_0.move_parameters_to_priority \ No newline at end of file diff --git a/erpnext/patches/v12_0/move_parameters_to_priority.py b/erpnext/patches/v12_0/move_parameters_to_priority.py index 71f341daed..c62c1c30ec 100644 --- a/erpnext/patches/v12_0/move_parameters_to_priority.py +++ b/erpnext/patches/v12_0/move_parameters_to_priority.py @@ -14,24 +14,24 @@ def execute(): "priorities": [ { "priority": "Low", - "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, + "response_time": doc.response_time, + "response_time_period": doc.response_time_period, + "resolution_time": doc.resolution_time, + "resolution_time_period": doc.resolution_time_period, }, { "priority": "Medium", - "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, + "response_time": doc.response_time, + "response_time_period": doc.response_time_period, + "resolution_time": doc.resolution_time, + "resolution_time_period": doc.resolution_time_period, }, { "priority": "High", - "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, + "response_time": doc.response_time, + "response_time_period": doc.response_time_period, + "resolution_time": doc.resolution_time, + "resolution_time_period": doc.resolution_time_period, } ] }) @@ -43,24 +43,24 @@ def execute(): "priorities": [ { "priority": "Low", - "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, + "response_time": doc.response_time, + "response_time_period": doc.response_time_period, + "resolution_time": doc.resolution_time, + "resolution_time_period": doc.resolution_time_period, }, { "priority": "Medium", - "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, + "response_time": doc.response_time, + "response_time_period": doc.response_time_period, + "resolution_time": doc.resolution_time, + "resolution_time_period": doc.resolution_time_period, }, { "priority": "High", - "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, + "response_time": doc.response_time, + "response_time_period": doc.response_time_period, + "resolution_time": doc.resolution_time, + "resolution_time_period": doc.resolution_time_period, }, ] }) From 785f98efd9acbfe173816fc21e831836af71229c Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 6 May 2019 00:43:38 +0530 Subject: [PATCH 10/92] minor: change autoname for sla --- .../service_level_agreement/service_level_agreement.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index b206fb33e4..84dbddea6f 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -1,5 +1,5 @@ { - "autoname": "field:sla_name", + "autoname": "format:SLA-{sla_name}", "creation": "2018-12-26 21:08:15.448812", "doctype": "DocType", "editable_grid": 1, @@ -133,7 +133,7 @@ "unique": 1 } ], - "modified": "2019-05-05 20:24:57.557178", + "modified": "2019-05-06 00:31:06.167762", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", From aa0eaab3df03abe958e53a1a351c2a528c042bd9 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 6 May 2019 01:35:11 +0530 Subject: [PATCH 11/92] fix: codacy --- erpnext/support/doctype/issue/issue.js | 5 ++- .../service_level_agreement.js | 15 +++++--- .../service_level_agreement.py | 34 ++++++++++--------- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index d31ae4a4c4..a19b372726 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -33,7 +33,7 @@ frappe.ui.form.on("Issue", { frm.call('change_sla_priority', { "priority": frm.doc.priority }).then(() => { - frm.refresh() + frm.refresh(); }); } }, @@ -116,6 +116,5 @@ function get_time_left(timestamp) { if (diff_display == '00:00') { indicator = "red"; } - return {"diff_display": diff_display, - "indicator": indicator}; + return {"diff_display": diff_display, "indicator": indicator}; } diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js index 2da4b0387d..4f334f212c 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js @@ -11,11 +11,16 @@ frappe.ui.form.on('Service Level Agreement', { name: frm.doc.service_level }, callback: function(data){ - for (var i in data.message.priorities){ - frm.add_child("priorities", data.message.priorities[i]); - } - for (var i in data.message.support_and_resolution){ - frm.add_child("support_and_resolution", data.message.support_and_resolution[i]); + let count = Math.max(data.message.priorities.length, data.message.support_and_resolution.length); + 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(); } diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index 4fca708993..ea869ee7c8 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -41,21 +41,23 @@ def check_agreement_status(): @frappe.whitelist() def get_active_service_level_agreement_for(customer, priority): - agreement = frappe.db.sql(""" - select `tabService Level Agreement`.name, `tabService Level Agreement`.service_level, - `tabService Level Agreement`.holiday_list - from `tabService Level Agreement` - inner join `tabService Level Priority` - on `tabService Level Agreement`.name=`tabService Level Priority`.parent where - ( - `tabService Level Agreement`.customer='{0}' and - `tabService Level Agreement`.agreement_status='Active' and - `tabService Level Priority`.priority='{1}' - ) or - ( - `tabService Level Agreement`.default_service_level_agreement='1' - ) - limit 1 - """.format(customer, priority), as_dict=True) + agreement = frappe.db.sql("""select `tabService Level Agreement`.name, `tabService Level Agreement`.service_level, + `tabService Level Agreement`.holiday_list + from `tabService Level Agreement` + inner join `tabService Level Priority` + on `tabService Level Agreement`.name=`tabService Level Priority`.parent where + ( + `tabService Level Agreement`.customer='%(customer)s' and + `tabService Level Agreement`.agreement_status='Active' and + `tabService Level Priority`.priority='%(priority)s' + ) or + ( + `tabService Level Agreement`.default_service_level_agreement='1' + ) + limit 1""", + { + "customer": customer, + "priority": priority + }, as_dict=True) return agreement[0] if agreement else None \ No newline at end of file From c5999154e69d03973b36acea215c0b199398e48a Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 6 May 2019 23:43:16 +0530 Subject: [PATCH 12/92] fix: test cases and use orm --- .../v12_0/move_parameters_to_priority.py | 52 +++++-------------- erpnext/support/doctype/issue/issue.js | 2 +- erpnext/support/doctype/issue/issue.py | 4 +- .../service_level_agreement.json | 4 +- .../service_level_agreement.py | 36 +++++-------- .../test_service_level_agreement.py | 6 +-- 6 files changed, 32 insertions(+), 72 deletions(-) diff --git a/erpnext/patches/v12_0/move_parameters_to_priority.py b/erpnext/patches/v12_0/move_parameters_to_priority.py index c62c1c30ec..310bfe2572 100644 --- a/erpnext/patches/v12_0/move_parameters_to_priority.py +++ b/erpnext/patches/v12_0/move_parameters_to_priority.py @@ -5,62 +5,34 @@ from __future__ import unicode_literals import frappe def execute(): - priorities = ["Low", "Medium", "High"] + priority = ["Low", "Medium", "High"] service_levels = frappe.get_list("Service Level") for service_level in service_levels: doc = frappe.get_doc("Service Level", service_level) - doc.update({ - "priorities": [ + for value in priority: + doc.append("priorities", { - "priority": "Low", - "response_time": doc.response_time, - "response_time_period": doc.response_time_period, - "resolution_time": doc.resolution_time, - "resolution_time_period": doc.resolution_time_period, - }, - { - "priority": "Medium", - "response_time": doc.response_time, - "response_time_period": doc.response_time_period, - "resolution_time": doc.resolution_time, - "resolution_time_period": doc.resolution_time_period, - }, - { - "priority": "High", + "priority": "{0}".format(value), "response_time": doc.response_time, "response_time_period": doc.response_time_period, "resolution_time": doc.resolution_time, "resolution_time_period": doc.resolution_time_period, } - ] - }) + ) + doc.save(ignore_permissions=True) service_level_agreements = frappe.get_list("Service Level Agreement") for service_level_agreement in service_level_agreements: doc = frappe.get_doc("Service Level Agreement", service_level_agreement) - doc.update({ - "priorities": [ + for value in priority: + doc.append("priorities", { - "priority": "Low", + "priority": "{0}".format(value), "response_time": doc.response_time, "response_time_period": doc.response_time_period, "resolution_time": doc.resolution_time, "resolution_time_period": doc.resolution_time_period, - }, - { - "priority": "Medium", - "response_time": doc.response_time, - "response_time_period": doc.response_time_period, - "resolution_time": doc.resolution_time, - "resolution_time_period": doc.resolution_time_period, - }, - { - "priority": "High", - "response_time": doc.response_time, - "response_time_period": doc.response_time_period, - "resolution_time": doc.resolution_time, - "resolution_time_period": doc.resolution_time_period, - }, - ] - }) + } + ) + doc.save(ignore_permissions=True) \ No newline at end of file diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index a19b372726..ab40a5bb16 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -4,7 +4,7 @@ frappe.ui.form.on("Issue", { }, refresh: function (frm) { - if (frm.doc.service_level_agreement) { + if (frm.doc.service_level_agreement && frm.doc.status !== "Closed") { set_time_to_resolve_and_response(frm); } diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 66eb55ab63..7eeb7833db 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -128,8 +128,8 @@ class Issue(Document): def before_insert(self): self.set_response_and_resolution_time(priority=self.priority) - def set_response_and_resolution_time(self, priority=None): - service_level_agreement = get_active_service_level_agreement_for(self.customer, priority) + def set_response_and_resolution_time(self, priority): + service_level_agreement = get_active_service_level_agreement_for(priority=priority, customer=self.customer) if service_level_agreement: self.service_level_agreement = service_level_agreement.name else: diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index 84dbddea6f..b63e2af46e 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -70,7 +70,6 @@ "read_only": 1 }, { - "depends_on": "eval: !doc.default_service_level_agreement", "fieldname": "agreement_details_section", "fieldtype": "Section Break", "label": "Agreement Details" @@ -83,7 +82,6 @@ }, { "default": "Active", - "depends_on": "eval: !doc.default_service_level_agreement", "fieldname": "agreement_status", "fieldtype": "Select", "label": "Agreement Status", @@ -133,7 +131,7 @@ "unique": 1 } ], - "modified": "2019-05-06 00:31:06.167762", + "modified": "2019-05-06 22:00:44.623128", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index ea869ee7c8..00f5cb32c4 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -14,7 +14,7 @@ class ServiceLevelAgreement(Document): frappe.throw(_("Select a Customer or set as Default Service Level Agreement.")) if self.default_service_level_agreement: - if frappe.db.exists("Service Level Agreement", {"default_service_level_agreement": "1"}): + if frappe.db.exists("Service Level Agreement", {"default_service_level_agreement": "1", "name": ["!=", self.name]}): frappe.throw(_("A Default Service Level Agreement already exists.")) else: if not (self.start_date and self.end_date): @@ -31,33 +31,23 @@ def check_agreement_status(): {"agreement_status": "Active"}, {"default_service_level_agreement": 0} ]) - service_level_agreements.reverse() + for service_level_agreement in service_level_agreements: service_level_agreement = frappe.get_doc("Service Level Agreement", service_level_agreement) + if service_level_agreement.end_date < frappe.utils.getdate(): - service_level_agreement.agreement_status = "Expired" - service_level_agreement.save() + frappe.db.set_value("Service Level Agreement", service_level_agreement.name, + "agreement_status", "Expired") @frappe.whitelist() -def get_active_service_level_agreement_for(customer, priority): +def get_active_service_level_agreement_for(priority, customer=None): - agreement = frappe.db.sql("""select `tabService Level Agreement`.name, `tabService Level Agreement`.service_level, - `tabService Level Agreement`.holiday_list - from `tabService Level Agreement` - inner join `tabService Level Priority` - on `tabService Level Agreement`.name=`tabService Level Priority`.parent where - ( - `tabService Level Agreement`.customer='%(customer)s' and - `tabService Level Agreement`.agreement_status='Active' and - `tabService Level Priority`.priority='%(priority)s' - ) or - ( - `tabService Level Agreement`.default_service_level_agreement='1' - ) - limit 1""", - { - "customer": customer, - "priority": priority - }, as_dict=True) + if customer and frappe.db.exists("Service Level Agreement", {"customer": customer}): + or_filter = {"customer": customer} + else: + or_filter = {"default_service_level_agreement": 1} + + agreement = frappe.get_list("Service Level Agreement", filters={"agreement_status": "Active"}, + or_filters=or_filter, fields=["name", "service_level"]) return agreement[0] if agreement else None \ No newline at end of file diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py index b9d25e46f0..b2c0eba000 100644 --- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py @@ -85,7 +85,7 @@ def make_service_level_agreement(): ] }) - default_service_level_agreement_exists = frappe.db.exists("Service Level Agreement", "Default Service Level Agreement") + default_service_level_agreement_exists = frappe.db.exists("Service Level Agreement", "SLA-Default Service Level Agreement") if not default_service_level_agreement_exists: default_service_level_agreement.insert(ignore_permissions=True) @@ -172,7 +172,7 @@ def make_service_level_agreement(): ] }) - service_level_agreement_exists = frappe.db.exists("Service Level Agreement", "_Test Service Level Agreement") + service_level_agreement_exists = frappe.db.exists("Service Level Agreement", "SLA-_Test Service Level Agreement") if not service_level_agreement_exists: service_level_agreement.insert(ignore_permissions=True) return service_level_agreement.name @@ -180,5 +180,5 @@ def make_service_level_agreement(): return service_level_agreement_exists def get_service_level_agreement(): - service_level_agreement = frappe.db.exists("Service Level Agreement", "_Test Service Level Agreement") + service_level_agreement = frappe.db.exists("Service Level Agreement", "SLA-_Test Service Level Agreement") return service_level_agreement \ No newline at end of file From cf37e401f8f690539370d41c213edf0441f1a77e Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 7 May 2019 10:27:01 +0530 Subject: [PATCH 13/92] fix: change agreement status only if ongoing --- erpnext/hooks.py | 3 ++- erpnext/support/doctype/issue/issue.py | 17 ++++++++++++++--- erpnext/support/doctype/issue/test_issue.py | 12 ------------ .../service_level_agreement.py | 4 +--- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 8ae9267b64..5beaea70f9 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -264,7 +264,8 @@ scheduler_events = { "erpnext.projects.doctype.project.project.update_project_sales_billing", "erpnext.projects.doctype.project.project.send_project_status_email_to_users", "erpnext.quality_management.doctype.quality_review.quality_review.review", - "erpnext.support.doctype.service_level_agreement.service_level_agreement.check_agreement_status" + "erpnext.support.doctype.service_level_agreement.service_level_agreement.check_agreement_status", + "erpnext.support.doctype.issue.issue.set_service_level_agreement_status" ], "daily_long": [ "erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms" diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 7eeb7833db..37be95b36d 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -77,9 +77,9 @@ class Issue(Document): def update_agreement_status(self): current_time = frappe.flags.current_time or now_datetime() - if self.service_level_agreement: - if (round(time_diff_in_hours(self.response_by, current_time), 2) < 0 - or round(time_diff_in_hours(self.resolution_by, current_time), 2) < 0): + if self.service_level_agreement and self.agreement_status == "Ongoing": + if (round(time_diff_in_hours(self.response_by, current_time), 2) < 0 or + round(time_diff_in_hours(self.resolution_by, current_time), 2) < 0): self.agreement_status = "Failed" else: self.agreement_status = "Fulfilled" @@ -220,6 +220,17 @@ def get_expected_time_for(parameter, service_level, start_date_time): return current_date_time +def set_service_level_agreement_status(): + issues = frappe.get_list("Issue", filters={"status": "Open", "agreement_status": "Ongoing"}) + for issue in issues: + doc = frappe.get_doc("Issue", issue.name) + if self.service_level_agreement and self.agreement_status == "Ongoing": + if (round(time_diff_in_hours(self.response_by, now_datetime()), 2) < 0 or + round(time_diff_in_hours(self.resolution_by, now_datetime()), 2) < 0): + frappe.db.set_value("Issue", doc.name, "agreement_status", "Failed") + else: + frappe.db.set_value("Issue", doc.name, "agreement_status", "Fulfilled") + def get_list_context(context=None): return { "title": _("Issues"), diff --git a/erpnext/support/doctype/issue/test_issue.py b/erpnext/support/doctype/issue/test_issue.py index 5266678fc0..8bf0f3ad4b 100644 --- a/erpnext/support/doctype/issue/test_issue.py +++ b/erpnext/support/doctype/issue/test_issue.py @@ -48,18 +48,6 @@ class TestIssue(unittest.TestCase): self.assertEqual(issue.agreement_status, 'Fulfilled') - issue.status = 'Open' - 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({ diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index 00f5cb32c4..e0cbc59aac 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -30,11 +30,9 @@ def check_agreement_status(): service_level_agreements = frappe.get_list("Service Level Agreement", filters=[ {"agreement_status": "Active"}, {"default_service_level_agreement": 0} - ]) + ], fields=["name", "end_date"]) for service_level_agreement in service_level_agreements: - service_level_agreement = frappe.get_doc("Service Level Agreement", service_level_agreement) - if service_level_agreement.end_date < frappe.utils.getdate(): frappe.db.set_value("Service Level Agreement", service_level_agreement.name, "agreement_status", "Expired") From 9563835b6161d74f6b250d6ee6b8428d69843bac Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 7 May 2019 10:40:02 +0530 Subject: [PATCH 14/92] fix: miscellaneous fixes --- erpnext/support/doctype/issue/issue.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 37be95b36d..ec8f98191d 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -78,8 +78,9 @@ class Issue(Document): def update_agreement_status(self): current_time = frappe.flags.current_time or now_datetime() if self.service_level_agreement and self.agreement_status == "Ongoing": - if (round(time_diff_in_hours(self.response_by, current_time), 2) < 0 or - round(time_diff_in_hours(self.resolution_by, current_time), 2) < 0): + response_time_diff = round(time_diff_in_hours(self.response_by, current_time), 2) + resolution_time_diff = round(time_diff_in_hours(self.resolution_by, current_time), 2) + if response_time_diff < 0 or resolution_time_diff < 0: self.agreement_status = "Failed" else: self.agreement_status = "Fulfilled" @@ -225,8 +226,9 @@ def set_service_level_agreement_status(): for issue in issues: doc = frappe.get_doc("Issue", issue.name) if self.service_level_agreement and self.agreement_status == "Ongoing": - if (round(time_diff_in_hours(self.response_by, now_datetime()), 2) < 0 or - round(time_diff_in_hours(self.resolution_by, now_datetime()), 2) < 0): + response_time_diff = round(time_diff_in_hours(self.response_by, now_datetime()), 2) + resolution_time_diff = round(time_diff_in_hours(self.resolution_by, now_datetime()), 2) + if response_time_diff < 0 or resolution_time_diff < 0: frappe.db.set_value("Issue", doc.name, "agreement_status", "Failed") else: frappe.db.set_value("Issue", doc.name, "agreement_status", "Fulfilled") From 1bfef6a600c5110e87cd10acf027c4b913d40a50 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 7 May 2019 10:46:52 +0530 Subject: [PATCH 15/92] fix: code fixes --- erpnext/support/doctype/issue/issue.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index ec8f98191d..2b734404cc 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -225,9 +225,9 @@ def set_service_level_agreement_status(): issues = frappe.get_list("Issue", filters={"status": "Open", "agreement_status": "Ongoing"}) for issue in issues: doc = frappe.get_doc("Issue", issue.name) - if self.service_level_agreement and self.agreement_status == "Ongoing": - response_time_diff = round(time_diff_in_hours(self.response_by, now_datetime()), 2) - resolution_time_diff = round(time_diff_in_hours(self.resolution_by, now_datetime()), 2) + if doc.service_level_agreement and doc.agreement_status == "Ongoing": + response_time_diff = round(time_diff_in_hours(doc.response_by, now_datetime()), 2) + resolution_time_diff = round(time_diff_in_hours(doc.resolution_by, now_datetime()), 2) if response_time_diff < 0 or resolution_time_diff < 0: frappe.db.set_value("Issue", doc.name, "agreement_status", "Failed") else: From fc3232a9db03b09b4b622701e33ad866be4e7263 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 7 May 2019 23:42:38 +0530 Subject: [PATCH 16/92] fix: compare timedeltas directly --- erpnext/support/doctype/service_level/service_level.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/erpnext/support/doctype/service_level/service_level.py b/erpnext/support/doctype/service_level/service_level.py index f48d927778..0b903fb052 100644 --- a/erpnext/support/doctype/service_level/service_level.py +++ b/erpnext/support/doctype/service_level/service_level.py @@ -65,9 +65,7 @@ class ServiceLevel(Document): support_days.append(support_and_resolution.workday) support_and_resolution.idx = week.index(support_and_resolution.workday) + 1 - start_time, end_time = (datetime.strptime(support_and_resolution.start_time, '%H:%M:%S').time(), - datetime.strptime(support_and_resolution.end_time, '%H:%M:%S').time()) - if start_time >= end_time: + if support_and_resolution.start_time >= support_and_resolution.end_time: frappe.throw(_("Start Time can't be greater than or equal to End Time \ for {0}.".format(support_and_resolution.workday))) From 5aba75d74daaf3ea62ae9fc0715878d1b6fef68b Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 8 May 2019 00:22:26 +0530 Subject: [PATCH 17/92] fix: show priority change dialog --- erpnext/support/doctype/issue/issue.js | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index ab40a5bb16..2de0451bb3 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -33,6 +33,7 @@ frappe.ui.form.on("Issue", { frm.call('change_sla_priority', { "priority": frm.doc.priority }).then(() => { + frappe.msgprint(__("Issue Priority changed to {0}.", [frm.doc.priority])) frm.refresh(); }); } From 488432c0e8c7bfc913f029535bae05c4f7225748 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 9 May 2019 11:50:09 +0530 Subject: [PATCH 18/92] fix: display sla status --- erpnext/support/doctype/issue/issue.js | 34 ++++++++++++++++++-------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index 2de0451bb3..147505012a 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -4,11 +4,12 @@ frappe.ui.form.on("Issue", { }, refresh: function (frm) { - if (frm.doc.service_level_agreement && frm.doc.status !== "Closed") { - set_time_to_resolve_and_response(frm); - } if (frm.doc.status !== "Closed") { + if (frm.doc.service_level_agreement) { + set_time_to_resolve_and_response(frm); + } + frm.add_custom_button(__("Close"), function () { frm.set_value("status", "Closed"); frm.save(); @@ -21,6 +22,22 @@ frappe.ui.form.on("Issue", { }); }, __("Make")); } else { + if (frm.doc.service_level_agreement) { + frm.dashboard.clear_headline(); + + let agreement_status = (frm.doc.agreement_status == "Fulfilled") ? + {"indicator": "green", "msg": "Service Level Agreement has been fulfilled"} : + {"indicator": "red", "msg": "Service Level Agreement Failed"}; + + frm.dashboard.set_headline_alert( + '
' + + '
' + + ' ' + + '
' + + '
' + ); + } + frm.add_custom_button(__("Reopen"), function () { frm.set_value("status", "Open"); frm.save(); @@ -95,8 +112,8 @@ frappe.ui.form.on("Issue", { function set_time_to_resolve_and_response(frm) { frm.dashboard.clear_headline(); - var time_to_respond = get_time_left(frm.doc.response_by); - var time_to_resolve = get_time_left(frm.doc.resolution_by); + var time_to_respond = get_time_left(frm.doc.response_by, frm.doc.agreement_status); + var time_to_resolve = get_time_left(frm.doc.resolution_by, frm.doc.agreement_status); frm.dashboard.set_headline_alert( '
' + @@ -110,12 +127,9 @@ function set_time_to_resolve_and_response(frm) { ); } -function get_time_left(timestamp) { +function get_time_left(timestamp, agreement_status) { const diff = moment(timestamp).diff(moment()); const diff_display = diff >= 44500 ? moment.duration(diff).humanize() : moment(0, 'seconds').format('HH:mm'); - var indicator = "green"; - if (diff_display == '00:00') { - indicator = "red"; - } + let indicator = (diff_display == '00:00' && agreement_status != "Fulfilled") ? "red" : "green"; return {"diff_display": diff_display, "indicator": indicator}; } From 6e6148be397b1afb8d90adcdbe8ac6f7fc625efd Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 10 May 2019 23:49:42 +0530 Subject: [PATCH 19/92] fix: calculate variance --- erpnext/hooks.py | 3 +- erpnext/support/doctype/issue/issue.js | 14 ++++----- erpnext/support/doctype/issue/issue.json | 36 +++++++++++++++------ erpnext/support/doctype/issue/issue.py | 40 +++++++++++++++++++----- 4 files changed, 67 insertions(+), 26 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 5beaea70f9..f5595974e6 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -242,7 +242,8 @@ scheduler_events = { "erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_mws_settings.schedule_get_order_details", "erpnext.accounts.doctype.gl_entry.gl_entry.rename_gle_sle_docs", "erpnext.projects.doctype.project.project.hourly_reminder", - "erpnext.projects.doctype.project.project.collect_project_status" + "erpnext.projects.doctype.project.project.collect_project_status", + "erpnext.support.doctype.issue.issue.set_service_level_agreement_variance" ], "daily": [ "erpnext.stock.reorder_item.reorder_item", diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index 147505012a..e2e699758a 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -5,7 +5,7 @@ frappe.ui.form.on("Issue", { 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); } @@ -25,14 +25,14 @@ frappe.ui.form.on("Issue", { if (frm.doc.service_level_agreement) { frm.dashboard.clear_headline(); - let agreement_status = (frm.doc.agreement_status == "Fulfilled") ? + 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( '
' + '
' + - ' ' + + ' ' + '
' + '
' ); @@ -112,8 +112,8 @@ frappe.ui.form.on("Issue", { function set_time_to_resolve_and_response(frm) { frm.dashboard.clear_headline(); - var time_to_respond = get_time_left(frm.doc.response_by, frm.doc.agreement_status); - var time_to_resolve = get_time_left(frm.doc.resolution_by, frm.doc.agreement_status); + var time_to_respond = get_time_left(frm.doc.response_by, frm.doc.agreement_fulfilled); + var time_to_resolve = get_time_left(frm.doc.resolution_by, frm.doc.agreement_fulfilled); frm.dashboard.set_headline_alert( '
' + @@ -127,9 +127,9 @@ function set_time_to_resolve_and_response(frm) { ); } -function get_time_left(timestamp, agreement_status) { +function get_time_left(timestamp, agreement_fulfilled) { const diff = moment(timestamp).diff(moment()); const diff_display = diff >= 44500 ? moment.duration(diff).humanize() : moment(0, 'seconds').format('HH:mm'); - let indicator = (diff_display == '00:00' && agreement_status != "Fulfilled") ? "red" : "green"; + let indicator = (diff_display == '00:00' && agreement_fulfilled != "Fulfilled") ? "red" : "green"; return {"diff_display": diff_display, "indicator": indicator}; } diff --git a/erpnext/support/doctype/issue/issue.json b/erpnext/support/doctype/issue/issue.json index 9639702e24..29cad627b4 100644 --- a/erpnext/support/doctype/issue/issue.json +++ b/erpnext/support/doctype/issue/issue.json @@ -21,9 +21,11 @@ "service_level_section", "service_level_agreement", "response_by", + "response_by_variance", "cb", - "agreement_status", + "agreement_fulfilled", "resolution_by", + "resolution_by_variance", "response", "mins_to_first_response", "first_responded_on", @@ -166,14 +168,6 @@ "options": "fa fa-pushpin", "read_only": 1 }, - { - "default": "Ongoing", - "fieldname": "agreement_status", - "fieldtype": "Select", - "label": "Agreement Status", - "options": "Ongoing\nFulfilled\nFailed", - "read_only": 1 - }, { "fieldname": "resolution_by", "fieldtype": "Datetime", @@ -317,11 +311,33 @@ "fieldname": "via_customer_portal", "fieldtype": "Check", "label": "Via Customer Portal" + }, + { + "default": "Ongoing", + "fieldname": "agreement_fulfilled", + "fieldtype": "Select", + "label": "Agreement Fulfilled", + "options": "Ongoing\nFulfilled\nFailed", + "read_only": 1 + }, + { + "description": "in hours", + "fieldname": "response_by_variance", + "fieldtype": "Int", + "label": "Response By Variance", + "read_only": 1 + }, + { + "description": "in hours", + "fieldname": "resolution_by_variance", + "fieldtype": "Int", + "label": "Resolution By Variance", + "read_only": 1 } ], "icon": "fa fa-ticket", "idx": 7, - "modified": "2019-05-03 14:36:19.117560", + "modified": "2019-05-10 22:31:09.391044", "modified_by": "Administrator", "module": "Support", "name": "Issue", diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 2b734404cc..965e53c0a5 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -68,22 +68,27 @@ class Issue(Document): status = frappe.db.get_value("Issue", self.name, "status") if self.status!="Open" and status =="Open" and not self.first_responded_on: self.first_responded_on = now() + if self.status=="Closed" and status !="Closed": self.resolution_date = now() - self.update_agreement_status() + if not frappe.db.get_value("Issue", self.name, "agreement_fulfilled") == "Ongoing": + self.set_service_level_agreement_variance(issue=self.name) + self.update_agreement_status() + 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 self.resolution_date = None def update_agreement_status(self): current_time = frappe.flags.current_time or now_datetime() - if self.service_level_agreement and self.agreement_status == "Ongoing": + if self.service_level_agreement and self.agreement_fulfilled == "Ongoing": response_time_diff = round(time_diff_in_hours(self.response_by, current_time), 2) resolution_time_diff = round(time_diff_in_hours(self.resolution_by, current_time), 2) + if response_time_diff < 0 or resolution_time_diff < 0: - self.agreement_status = "Failed" + self.agreement_fulfilled = "Failed" else: - self.agreement_status = "Fulfilled" + self.agreement_fulfilled = "Fulfilled" def create_communication(self): communication = frappe.new_doc("Communication") @@ -151,6 +156,9 @@ class Issue(Document): 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_variance = round(time_diff_in_hours(self.response_by, now_datetime())) + self.resolution_by_variance = round(time_diff_in_hours(self.resolution_by, now_datetime())) + @frappe.whitelist() def change_sla_priority(self, priority): self.set_response_and_resolution_time(priority=priority) @@ -222,16 +230,32 @@ def get_expected_time_for(parameter, service_level, start_date_time): return current_date_time def set_service_level_agreement_status(): - issues = frappe.get_list("Issue", filters={"status": "Open", "agreement_status": "Ongoing"}) + issues = frappe.get_list("Issue", filters={"status": "Open", "agreement_fulfilled": "Ongoing"}) for issue in issues: doc = frappe.get_doc("Issue", issue.name) - if doc.service_level_agreement and doc.agreement_status == "Ongoing": + if doc.service_level_agreement and doc.agreement_fulfilled == "Ongoing": response_time_diff = round(time_diff_in_hours(doc.response_by, now_datetime()), 2) resolution_time_diff = round(time_diff_in_hours(doc.resolution_by, now_datetime()), 2) if response_time_diff < 0 or resolution_time_diff < 0: - frappe.db.set_value("Issue", doc.name, "agreement_status", "Failed") + frappe.db.set_value("Issue", doc.name, "agreement_fulfilled", "Failed") else: - frappe.db.set_value("Issue", doc.name, "agreement_status", "Fulfilled") + frappe.db.set_value("Issue", doc.name, "agreement_fulfilled", "Fulfilled") + +def set_service_level_agreement_variance(issue=None): + filters = {"status": "Open", "agreement_fulfilled": "Ongoing"} + + if issue: + filters = {"status": issue} + + issues = frappe.get_list("Issue", filters=filters) + for issue in issues: + doc = frappe.get_doc("Issue", issue.name) + if not doc.first_responded_on and not doc.agreement_fulfilled == "Ongoing": + variance = round(time_diff_in_hours(doc.response_by, now_datetime())) + frappe.db.set_value("Issue", doc.name, "response_by_variance", variance) + if not doc.resolution_dateand and not doc.agreement_fulfilled == "Ongoing": + variance = round(time_diff_in_hours(self.resolution_by, now_datetime())) + frappe.db.set_value("Issue", doc.name, "resolution_by_variance", variance) def get_list_context(context=None): return { From a8f96980823e27ad6890cdd6def27c15eec675e8 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sat, 11 May 2019 00:01:43 +0530 Subject: [PATCH 20/92] fix: call the correct function --- erpnext/support/doctype/issue/issue.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 965e53c0a5..b4207269df 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -71,8 +71,8 @@ class Issue(Document): if self.status=="Closed" and status !="Closed": self.resolution_date = now() - if not frappe.db.get_value("Issue", self.name, "agreement_fulfilled") == "Ongoing": - self.set_service_level_agreement_variance(issue=self.name) + 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": From c4fe98391b3b734f3949e92e51af5e2e2ab3579f Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sat, 11 May 2019 09:38:08 +0530 Subject: [PATCH 21/92] fix: set now_datetime --- erpnext/support/doctype/issue/issue.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index b4207269df..b3d91e4a75 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -67,10 +67,10 @@ class Issue(Document): def update_status(self): status = frappe.db.get_value("Issue", self.name, "status") if self.status!="Open" and status =="Open" and not self.first_responded_on: - self.first_responded_on = now() + self.first_responded_on = now_datetime() if self.status=="Closed" and status !="Closed": - self.resolution_date = now() + self.resolution_date = now_datetime() if frappe.db.get_value("Issue", self.name, "agreement_fulfilled") == "Ongoing": set_service_level_agreement_variance(issue=self.name) self.update_agreement_status() From f77fe313e3b90b0a2a40fb516f0334398e00c2a7 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 19 May 2019 11:06:00 +0530 Subject: [PATCH 22/92] feat: change sla on the fly --- erpnext/support/doctype/issue/issue.js | 23 ++++++++++++-- erpnext/support/doctype/issue/issue.json | 13 ++++---- erpnext/support/doctype/issue/issue.py | 31 ++++++++++++------- .../service_level_agreement.js | 9 ------ .../service_level_agreement.json | 23 +++++++++----- .../service_level_agreement.py | 17 +++++----- 6 files changed, 71 insertions(+), 45 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index e2e699758a..9dc3834618 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -47,8 +47,13 @@ frappe.ui.form.on("Issue", { priority: function(frm) { if (frm.doc.service_level_agreement) { - frm.call('change_sla_priority', { - "priority": frm.doc.priority + frappe.show_alert({ + indicator: 'green', + message: __('Changing Priority.') + }); + 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(); @@ -56,6 +61,20 @@ frappe.ui.form.on("Issue", { } }, + service_level_agreement: function(frm) { + frappe.show_alert({ + indicator: 'green', + message: __('Changing 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(__("Service Level Agreement changed to {0}.", [frm.doc.service_level_agreement])) + frm.refresh(); + }); + }, + timeline_refresh: function(frm) { // create button for "Help Article" if(frappe.model.can_create('Help Article')) { diff --git a/erpnext/support/doctype/issue/issue.json b/erpnext/support/doctype/issue/issue.json index 29cad627b4..df8197f30e 100644 --- a/erpnext/support/doctype/issue/issue.json +++ b/erpnext/support/doctype/issue/issue.json @@ -152,8 +152,7 @@ "fieldname": "service_level_agreement", "fieldtype": "Link", "label": "Service Level Agreement", - "options": "Service Level Agreement", - "read_only": 1 + "options": "Service Level Agreement" }, { "fieldname": "response_by", @@ -308,6 +307,7 @@ "label": "Attachment" }, { + "default": "0", "fieldname": "via_customer_portal", "fieldtype": "Check", "label": "Via Customer Portal" @@ -316,28 +316,28 @@ "default": "Ongoing", "fieldname": "agreement_fulfilled", "fieldtype": "Select", - "label": "Agreement Fulfilled", + "label": "Service Level Agreement Fulfilled", "options": "Ongoing\nFulfilled\nFailed", "read_only": 1 }, { "description": "in hours", "fieldname": "response_by_variance", - "fieldtype": "Int", + "fieldtype": "Float", "label": "Response By Variance", "read_only": 1 }, { "description": "in hours", "fieldname": "resolution_by_variance", - "fieldtype": "Int", + "fieldtype": "Float", "label": "Resolution By Variance", "read_only": 1 } ], "icon": "fa fa-ticket", "idx": 7, - "modified": "2019-05-10 22:31:09.391044", + "modified": "2019-05-19 11:02:10.962090", "modified_by": "Administrator", "module": "Support", "name": "Issue", @@ -357,6 +357,7 @@ ], "quick_entry": 1, "search_fields": "status,customer,subject,raised_by", + "sort_field": "modified", "sort_order": "ASC", "timeline_field": "customer", "title_field": "subject", diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index ee4a128513..91333b6370 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -130,13 +130,18 @@ class Issue(Document): def before_insert(self): self.set_response_and_resolution_time(priority=self.priority) - def set_response_and_resolution_time(self, priority): - service_level_agreement = get_active_service_level_agreement_for(priority=priority, customer=self.customer) - if service_level_agreement: - self.service_level_agreement = service_level_agreement.name - else: + def set_response_and_resolution_time(self, priority=None, service_level_agreement=None): + service_level_agreement = get_active_service_level_agreement_for(priority=priority, + customer=self.customer, service_level_agreement=service_level_agreement) + + if not service_level_agreement: return + 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 + service_level = frappe.get_doc("Service Level", service_level_agreement.service_level) priority = service_level.get_service_level_priority(priority) priority.update({ @@ -156,8 +161,8 @@ class Issue(Document): self.resolution_by_variance = round(time_diff_in_hours(self.resolution_by, now_datetime())) @frappe.whitelist() - def change_sla_priority(self, priority): - self.set_response_and_resolution_time(priority=priority) + def change_service_level_agreement_and_priority(self, priority, service_level_agreement): + 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): @@ -241,16 +246,18 @@ def set_service_level_agreement_variance(issue=None): filters = {"status": "Open", "agreement_fulfilled": "Ongoing"} if issue: - filters = {"status": issue} + filters = {"name": issue} issues = frappe.get_list("Issue", filters=filters) for issue in issues: doc = frappe.get_doc("Issue", issue.name) - if not doc.first_responded_on and not doc.agreement_fulfilled == "Ongoing": - variance = round(time_diff_in_hours(doc.response_by, now_datetime())) + if not doc.first_responded_on: + variance = round(time_diff_in_hours(doc.response_by, now_datetime()), 2) + print(variance) frappe.db.set_value("Issue", doc.name, "response_by_variance", variance) - if not doc.resolution_dateand and not doc.agreement_fulfilled == "Ongoing": - variance = round(time_diff_in_hours(self.resolution_by, now_datetime())) + if not doc.resolution_date: + variance = round(time_diff_in_hours(doc.resolution_by, now_datetime()), 2) + print(variance) frappe.db.set_value("Issue", doc.name, "resolution_by_variance", variance) def get_list_context(context=None): diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js index 4f334f212c..1d486f4834 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js @@ -26,13 +26,4 @@ frappe.ui.form.on('Service Level Agreement', { } }); }, - - validate: function(frm) { - frm.doc.sla_name = null; - var sla_name = 'Default Service Level Agreement'; - if (frm.doc.customer){ - sla_name = frm.doc.customer; - } - frm.doc.sla_name = sla_name; - }, }); diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index b63e2af46e..67e82f468b 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -1,11 +1,11 @@ { - "autoname": "format:SLA-{sla_name}", + "autoname": "format:SLA-{service_level_agreement_name}", "creation": "2018-12-26 21:08:15.448812", "doctype": "DocType", "editable_grid": 1, "engine": "InnoDB", "field_order": [ - "sla_name", + "service_level_agreement_name", "customer", "default_service_level_agreement", "holiday_list", @@ -17,6 +17,7 @@ "agreement_status", "column_break_7", "end_date", + "ignore_start_and_end_date", "response_and_resolution_time_section", "priorities", "support_and_resolution_section_break", @@ -33,6 +34,7 @@ "set_only_once": 1 }, { + "default": "0", "depends_on": "eval: !doc.customer", "fieldname": "default_service_level_agreement", "fieldtype": "Check", @@ -75,7 +77,7 @@ "label": "Agreement Details" }, { - "depends_on": "eval: !doc.default_service_level_agreement", + "depends_on": "eval: !doc.default_service_level_agreement && !doc.ignore_start_and_end_date", "fieldname": "start_date", "fieldtype": "Date", "label": "Start Date" @@ -94,7 +96,7 @@ "fieldtype": "Column Break" }, { - "depends_on": "eval: !doc.default_service_level_agreement", + "depends_on": "eval: !doc.default_service_level_agreement && !doc.ignore_start_and_end_date", "fieldname": "end_date", "fieldtype": "Date", "label": "End Date" @@ -124,14 +126,21 @@ "options": "Service Level Priority" }, { - "fieldname": "sla_name", + "fieldname": "service_level_agreement_name", "fieldtype": "Data", "label": "Service Level Agreement Name", - "read_only": 1, + "reqd": 1, "unique": 1 + }, + { + "default": "0", + "fieldname": "ignore_start_and_end_date", + "fieldtype": "Check", + "label": "Ignore Start and End Date", + "set_only_once": 1 } ], - "modified": "2019-05-06 22:00:44.623128", + "modified": "2019-05-19 09:41:55.498800", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index e0cbc59aac..876aaf5bb2 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -10,20 +10,17 @@ from frappe import _ class ServiceLevelAgreement(Document): def validate(self): - if not (self.customer or self.default_service_level_agreement): - frappe.throw(_("Select a Customer or set as Default Service Level Agreement.")) - if self.default_service_level_agreement: if frappe.db.exists("Service Level Agreement", {"default_service_level_agreement": "1", "name": ["!=", self.name]}): frappe.throw(_("A Default Service Level Agreement already exists.")) else: - if not (self.start_date and self.end_date): + if not (self.start_date and self.end_date and self.ignore_start_and_end_date): frappe.throw(_("Enter Start and End Date for the Agreement.")) - if self.start_date >= self.end_date: + if self.start_date >= self.end_date and not self.ignore_start_and_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(): + if self.end_date < frappe.utils.nowdate() and not self.ignore_start_and_end_date: frappe.throw(_("End Date of Agreement can't be less than today.")) def check_agreement_status(): @@ -38,14 +35,16 @@ def check_agreement_status(): "agreement_status", "Expired") @frappe.whitelist() -def get_active_service_level_agreement_for(priority, customer=None): +def get_active_service_level_agreement_for(priority, customer=None, service_level_agreement=None): - if customer and frappe.db.exists("Service Level Agreement", {"customer": customer}): + if customer and frappe.db.exists("Service Level Agreement", {"customer": customer}) and not service_level_agreement: or_filter = {"customer": customer} + elif service_level_agreement: + or_filter = {"name": service_level_agreement} else: or_filter = {"default_service_level_agreement": 1} agreement = frappe.get_list("Service Level Agreement", filters={"agreement_status": "Active"}, - or_filters=or_filter, fields=["name", "service_level"]) + or_filters=or_filter, fields=["name", "service_level", "customer"]) return agreement[0] if agreement else None \ No newline at end of file From 97b05e8b58e43d9f1f87f245c4505bc914d9bf25 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 19 May 2019 11:14:59 +0530 Subject: [PATCH 23/92] test: fixes --- erpnext/support/doctype/issue/test_issue.py | 2 +- .../service_level_agreement/test_service_level_agreement.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/support/doctype/issue/test_issue.py b/erpnext/support/doctype/issue/test_issue.py index 8bf0f3ad4b..565c603928 100644 --- a/erpnext/support/doctype/issue/test_issue.py +++ b/erpnext/support/doctype/issue/test_issue.py @@ -46,7 +46,7 @@ class TestIssue(unittest.TestCase): issue.status = 'Closed' issue.save() - self.assertEqual(issue.agreement_status, 'Fulfilled') + self.assertEqual(issue.agreement_fulfilled, 'Fulfilled') def make_issue(creation=None, customer=None): diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py index b2c0eba000..5ad907a449 100644 --- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py @@ -16,7 +16,7 @@ def make_service_level_agreement(): # Default Service Level Agreement default_service_level_agreement = frappe.get_doc({ "doctype": "Service Level Agreement", - "sla_name": "Default Service Level Agreement", + "service_level_agreement_name": "Default Service Level Agreement", "default_service_level_agreement": 1, "service_level": "__Test Service Level", "holiday_list": "__Test Holiday List", @@ -103,7 +103,7 @@ def make_service_level_agreement(): service_level_agreement = frappe.get_doc({ "doctype": "Service Level Agreement", - "sla_name": "_Test Service Level Agreement", + "service_level_agreement_name": "_Test Service Level Agreement", "customer": customer.customer_name, "service_level": "_Test Service Level", "holiday_list": "__Test Holiday List", From 22d8b3037aea93f0f5ee720f53e489e6e5fbad90 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 19 May 2019 11:56:37 +0530 Subject: [PATCH 24/92] tests: fix issue tests --- erpnext/support/doctype/issue/issue.py | 2 -- .../service_level_agreement/service_level_agreement.py | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 91333b6370..4c64a5abab 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -253,11 +253,9 @@ def set_service_level_agreement_variance(issue=None): doc = frappe.get_doc("Issue", issue.name) if not doc.first_responded_on: variance = round(time_diff_in_hours(doc.response_by, now_datetime()), 2) - print(variance) frappe.db.set_value("Issue", doc.name, "response_by_variance", variance) if not doc.resolution_date: variance = round(time_diff_in_hours(doc.resolution_by, now_datetime()), 2) - print(variance) frappe.db.set_value("Issue", doc.name, "resolution_by_variance", variance) def get_list_context(context=None): diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index 876aaf5bb2..064ac68caa 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -14,13 +14,13 @@ class ServiceLevelAgreement(Document): if frappe.db.exists("Service Level Agreement", {"default_service_level_agreement": "1", "name": ["!=", self.name]}): frappe.throw(_("A Default Service Level Agreement already exists.")) else: - if not (self.start_date and self.end_date and self.ignore_start_and_end_date): + if not (self.start_date and self.end_date) and self.ignore_start_and_end_date: frappe.throw(_("Enter Start and End Date for the Agreement.")) - if self.start_date >= self.end_date and not self.ignore_start_and_end_date: + if self.start_date >= self.end_date and self.ignore_start_and_end_date: frappe.throw(_("Start Date of Agreement can't be greater than or equal to End Date.")) - if self.end_date < frappe.utils.nowdate() and not self.ignore_start_and_end_date: + if self.end_date < frappe.utils.getdate() and self.ignore_start_and_end_date: frappe.throw(_("End Date of Agreement can't be less than today.")) def check_agreement_status(): From 23a574d794d1a4f8973c503873c51362d7c2310c Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 19 May 2019 19:34:45 +0530 Subject: [PATCH 25/92] fix: codacy --- erpnext/support/doctype/issue/issue.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index 9dc3834618..af742acc5f 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -26,10 +26,10 @@ frappe.ui.form.on("Issue", { 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"}; + {"indicator": "green", "msg": "Service Level Agreement has been fulfilled"} : + {"indicator": "red", "msg": "Service Level Agreement Failed"}; - frm.dashboard.set_headline_alert( + frm.dashboard.set_headline_alert( '
' + '
' + ' ' + @@ -55,7 +55,7 @@ frappe.ui.form.on("Issue", { "priority": frm.doc.priority, "service_level_agreement": frm.doc.service_level_agreement }).then(() => { - frappe.msgprint(__("Issue Priority changed to {0}.", [frm.doc.priority])) + frappe.msgprint(__("Issue Priority changed to {0}.", [frm.doc.priority])); frm.refresh(); }); } @@ -70,7 +70,7 @@ frappe.ui.form.on("Issue", { "priority": frm.doc.priority, "service_level_agreement": frm.doc.service_level_agreement }).then(() => { - frappe.msgprint(__("Service Level Agreement changed to {0}.", [frm.doc.service_level_agreement])) + frappe.msgprint(__("Service Level Agreement changed to {0}.", [frm.doc.service_level_agreement])); frm.refresh(); }); }, From 323ea2d33acff1ca138cb2e3889a2b2ea2cd63ee Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 21 May 2019 22:39:42 +0530 Subject: [PATCH 26/92] feat: change SLA as well as priorities --- erpnext/support/doctype/issue/issue.py | 13 +++---- .../doctype/service_level/service_level.json | 22 ++++++++++- .../doctype/service_level/service_level.py | 30 ++++++--------- .../service_level_agreement.json | 22 +++++++++-- .../service_level_agreement.py | 37 ++++++++++++++----- .../service_level_priority.json | 7 ++-- 6 files changed, 90 insertions(+), 41 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index deeb8ae845..c50a288330 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -128,9 +128,7 @@ class Issue(Document): return replicated_issue.name def before_insert(self): - if not self.priority: - self.priority = frappe.db.get_value("Issue Priority", {"default_priority": 1}) - self.set_response_and_resolution_time(priority=self.priority) + self.set_response_and_resolution_time() def set_response_and_resolution_time(self, priority=None, service_level_agreement=None): service_level_agreement = get_active_service_level_agreement_for(priority=priority, @@ -143,12 +141,13 @@ class Issue(Document): 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 = frappe.get_doc("Service Level", service_level_agreement.service_level) - priority = service_level.get_service_level_priority(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.support_and_resolution, - "holiday_list": service_level.holiday_list + "support_and_resolution": service_level_agreement.support_and_resolution, + "holiday_list": service_level_agreement.holiday_list }) if not self.creation: diff --git a/erpnext/support/doctype/service_level/service_level.json b/erpnext/support/doctype/service_level/service_level.json index 6718514712..71e12c04ce 100644 --- a/erpnext/support/doctype/service_level/service_level.json +++ b/erpnext/support/doctype/service_level/service_level.json @@ -9,6 +9,7 @@ "employee_group", "column_break_2", "holiday_list", + "default_priority", "response_and_resoution_time", "priorities", "section_break_01", @@ -65,9 +66,16 @@ "label": "Priorities", "options": "Service Level Priority", "reqd": 1 + }, + { + "fieldname": "default_priority", + "fieldtype": "Link", + "label": "Default Priority", + "options": "Issue Priority", + "read_only": 1 } ], - "modified": "2019-05-05 19:29:56.975951", + "modified": "2019-05-21 20:53:11.731727", "modified_by": "Administrator", "module": "Support", "name": "Service Level", @@ -84,6 +92,18 @@ "role": "System Manager", "share": 1, "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "All", + "share": 1, + "write": 1 } ], "sort_field": "modified", diff --git a/erpnext/support/doctype/service_level/service_level.py b/erpnext/support/doctype/service_level/service_level.py index a968ffeec6..857a21614c 100644 --- a/erpnext/support/doctype/service_level/service_level.py +++ b/erpnext/support/doctype/service_level/service_level.py @@ -12,7 +12,6 @@ from frappe.utils import get_weekdays class ServiceLevel(Document): def validate(self): - self.check_default_priority() self.check_priorities() self.check_support_and_resolution() @@ -26,7 +25,9 @@ class ServiceLevel(Document): frappe.throw(_("Set Response Time and Resolution for Priority {0} at index {1}.".format(priority.priority, priority.idx))) priorities.append(priority.priority) - #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 @@ -50,6 +51,13 @@ class ServiceLevel(Document): 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 + self.default_priority = next(d.priority for d in self.priorities if d.default_priority) + def check_support_and_resolution(self): week = get_weekdays() support_days = [] @@ -72,27 +80,13 @@ class ServiceLevel(Document): repeated_days = get_repeated(support_days) frappe.throw(_("Workday {0} has been repeated.".format(repeated_days))) - def get_service_level_priority(self, priority): - priority = frappe.get_doc("Service Level Priority", {"priority": priority, "parent": self.name}) - - if priority: - 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 - }) - else: - frappe.throw(_("Service Level {0} doesn't have Priority {1}.".format(self.name, priority))) - def get_repeated(values): unique_list = [] diff = [] for value in values: if value not in unique_list: - unique_list.append(value) + unique_list.append(str(value)) else: if value not in diff: - diff.append(value) + diff.append(str(value)) return " ".join(diff) diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index fb7b4ea49b..b3166f0002 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -8,10 +8,12 @@ "service_level_agreement_name", "customer", "default_service_level_agreement", + "ignore_customer_and_default_sla", "holiday_list", "column_break_2", "service_level", "employee_group", + "default_priority", "agreement_details_section", "start_date", "agreement_status", @@ -25,7 +27,7 @@ ], "fields": [ { - "depends_on": "eval: !doc.default_service_level_agreement", + "depends_on": "eval: !doc.default_service_level_agreement;\neval: !doc.ignore_customer_and_default_sla;", "fieldname": "customer", "fieldtype": "Link", "in_list_view": 1, @@ -35,7 +37,7 @@ }, { "default": "0", - "depends_on": "eval: !doc.customer", + "depends_on": "eval: !doc.customer;\neval: !doc.ignore_customer_and_default_sla;", "fieldname": "default_service_level_agreement", "fieldtype": "Check", "in_list_view": 1, @@ -139,9 +141,23 @@ "fieldtype": "Check", "label": "Ignore Start and End Date", "set_only_once": 1 + }, + { + "fetch_from": "service_level.default_priority", + "fieldname": "default_priority", + "fieldtype": "Link", + "label": "Default Priority", + "options": "Issue Priority", + "read_only": 1 + }, + { + "default": "0", + "fieldname": "ignore_customer_and_default_sla", + "fieldtype": "Check", + "label": "Ignore Customer and Default SLA" } ], - "modified": "2019-05-20 15:36:00.326471", + "modified": "2019-05-21 21:53:12.686806", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index 11c510f7f8..61c6cac1f2 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -23,6 +23,17 @@ class ServiceLevelAgreement(Document): if not self.ignore_start_and_end_date and self.end_date < frappe.utils.getdate(): frappe.throw(_("End Date of Agreement can't be less than today.")) + 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(): service_level_agreements = frappe.get_list("Service Level Agreement", filters=[ {"agreement_status": "Active"}, @@ -34,17 +45,25 @@ def check_agreement_status(): frappe.db.set_value("Service Level Agreement", service_level_agreement.name, "agreement_status", "Expired") -@frappe.whitelist() def get_active_service_level_agreement_for(priority, customer=None, service_level_agreement=None): + filters = [ + ["Service Level Agreement", "agreement_status", "=", "Active"] + ] - if customer and frappe.db.exists("Service Level Agreement", {"customer": customer}) and not service_level_agreement: - or_filter = {"customer": customer} - elif service_level_agreement: - or_filter = {"name": service_level_agreement} - else: - or_filter = {"default_service_level_agreement": 1} + if priority: + filters.append(["Service Level Priority", "priority", "=", priority]) - agreement = frappe.get_list("Service Level Agreement", filters={"agreement_status": "Active"}, - or_filters=or_filter, fields=["name", "service_level", "customer"]) + or_filters = [ + ["Service Level Agreement", "customer", "=", 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", "customer"], debug=True) return agreement[0] if agreement else None \ No newline at end of file diff --git a/erpnext/support/doctype/service_level_priority/service_level_priority.json b/erpnext/support/doctype/service_level_priority/service_level_priority.json index fae225c8d6..cd87a1c113 100644 --- a/erpnext/support/doctype/service_level_priority/service_level_priority.json +++ b/erpnext/support/doctype/service_level_priority/service_level_priority.json @@ -28,14 +28,14 @@ "fieldtype": "Section Break" }, { - "columns": 2, + "columns": 1, "fieldname": "response_time", "fieldtype": "Int", "in_list_view": 1, "label": "Response Time" }, { - "columns": 2, + "columns": 1, "fieldname": "resolution_time", "fieldtype": "Int", "in_list_view": 1, @@ -69,11 +69,12 @@ "default": "0", "fieldname": "default_priority", "fieldtype": "Check", + "in_list_view": 1, "label": "Default Priority" } ], "istable": 1, - "modified": "2019-05-20 17:10:43.687547", + "modified": "2019-05-21 06:54:42.674377", "modified_by": "Administrator", "module": "Support", "name": "Service Level Priority", From 6feb12d333341e0b5d659ff8ae71ba217282a867 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 26 May 2019 00:03:40 +0530 Subject: [PATCH 27/92] fix: miscellaneous fixes --- erpnext/support/doctype/issue/issue.py | 4 +++- .../doctype/service_level/service_level.json | 9 ++++++++- .../doctype/service_level/service_level.py | 14 +++++++++++++- .../service_level_agreement.json | 17 +++++++++-------- .../service_level_agreement.py | 4 ++-- 5 files changed, 35 insertions(+), 13 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index c50a288330..b47f7108bc 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -135,9 +135,11 @@ class Issue(Document): customer=self.customer, service_level_agreement=service_level_agreement) 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 - if service_level_agreement.customer and self.customer and not service_level_agreement.customer == self.customer: + 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 diff --git a/erpnext/support/doctype/service_level/service_level.json b/erpnext/support/doctype/service_level/service_level.json index 71e12c04ce..d4ce7d34d6 100644 --- a/erpnext/support/doctype/service_level/service_level.json +++ b/erpnext/support/doctype/service_level/service_level.json @@ -7,6 +7,7 @@ "field_order": [ "service_level", "employee_group", + "priorities_list", "column_break_2", "holiday_list", "default_priority", @@ -73,9 +74,15 @@ "label": "Default Priority", "options": "Issue Priority", "read_only": 1 + }, + { + "fieldname": "priorities_list", + "fieldtype": "Long Text", + "hidden": 1, + "label": "Priorities List" } ], - "modified": "2019-05-21 20:53:11.731727", + "modified": "2019-05-25 20:18:00.240337", "modified_by": "Administrator", "module": "Support", "name": "Service Level", diff --git a/erpnext/support/doctype/service_level/service_level.py b/erpnext/support/doctype/service_level/service_level.py index 857a21614c..80e4e22b90 100644 --- a/erpnext/support/doctype/service_level/service_level.py +++ b/erpnext/support/doctype/service_level/service_level.py @@ -13,6 +13,7 @@ class ServiceLevel(Document): def validate(self): self.check_priorities() + self.set_priorities() self.check_support_and_resolution() def check_priorities(self): @@ -56,7 +57,18 @@ class ServiceLevel(Document): frappe.throw(_("Select only one Priority as Default.")) # set default priority from priorities - self.default_priority = next(d.priority for d in self.priorities if d.default_priority) + 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 set_priorities(self): + priorities = [] + + for priority in self.priorities: + priorities.append(priority.priority) + + self.priorities_list = ",".join(priorities) def check_support_and_resolution(self): week = get_weekdays() diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index b3166f0002..98baa6ece9 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -8,8 +8,8 @@ "service_level_agreement_name", "customer", "default_service_level_agreement", - "ignore_customer_and_default_sla", "holiday_list", + "priorities_list", "column_break_2", "service_level", "employee_group", @@ -27,7 +27,7 @@ ], "fields": [ { - "depends_on": "eval: !doc.default_service_level_agreement;\neval: !doc.ignore_customer_and_default_sla;", + "depends_on": "eval: !doc.default_service_level_agreement;", "fieldname": "customer", "fieldtype": "Link", "in_list_view": 1, @@ -37,7 +37,7 @@ }, { "default": "0", - "depends_on": "eval: !doc.customer;\neval: !doc.ignore_customer_and_default_sla;", + "depends_on": "eval: !doc.customer;", "fieldname": "default_service_level_agreement", "fieldtype": "Check", "in_list_view": 1, @@ -151,13 +151,14 @@ "read_only": 1 }, { - "default": "0", - "fieldname": "ignore_customer_and_default_sla", - "fieldtype": "Check", - "label": "Ignore Customer and Default SLA" + "fetch_from": "service_level.priorities_list", + "fieldname": "priorities_list", + "fieldtype": "Text", + "hidden": 1, + "label": "Priorities List" } ], - "modified": "2019-05-21 21:53:12.686806", + "modified": "2019-05-25 20:20:41.231834", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index 61c6cac1f2..d1d040722f 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -20,7 +20,7 @@ class ServiceLevelAgreement(Document): if not self.ignore_start_and_end_date and self.start_date >= self.end_date: frappe.throw(_("Start Date of Agreement can't be greater than or equal to End Date.")) - if not self.ignore_start_and_end_date and self.end_date < frappe.utils.getdate(): + if not self.ignore_start_and_end_date and self.end_date < frappe.utils.today(): frappe.throw(_("End Date of Agreement can't be less than today.")) def get_service_level_agreement_priority(self, priority): @@ -54,7 +54,7 @@ def get_active_service_level_agreement_for(priority, customer=None, service_leve filters.append(["Service Level Priority", "priority", "=", priority]) or_filters = [ - ["Service Level Agreement", "customer", "=", customer], + ["Service Level Agreement", "customer", "=", customer] ] if service_level_agreement: or_filters = [ From 24f8310ece1d82695208e8282a7fead19a8b0f35 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 28 May 2019 00:01:55 +0530 Subject: [PATCH 28/92] fix: test cases --- .../issue_priority/test_issue_priority.py | 10 +++++----- .../service_level/test_service_level.py | 19 ++++++++++++++----- .../service_level_agreement.py | 4 ++-- .../test_service_level_agreement.py | 17 +++++++++++++---- 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/erpnext/support/doctype/issue_priority/test_issue_priority.py b/erpnext/support/doctype/issue_priority/test_issue_priority.py index c183bbc82c..0d65122c0d 100644 --- a/erpnext/support/doctype/issue_priority/test_issue_priority.py +++ b/erpnext/support/doctype/issue_priority/test_issue_priority.py @@ -15,8 +15,8 @@ def make_priorities(): insert_priority("High") def insert_priority(name): - frappe.get_doc({ - "doctype": "Issue Priority", - "name": name, - "default_priority": 1 if name == "Medium" else 0 - }).insert(ignore_permissions=True) \ No newline at end of file + if not frappe.db.exists("Issue Priority", name): + frappe.get_doc({ + "doctype": "Issue Priority", + "name": name + }).insert(ignore_permissions=True) \ No newline at end of file diff --git a/erpnext/support/doctype/service_level/test_service_level.py b/erpnext/support/doctype/service_level/test_service_level.py index deba197f4e..79f064358d 100644 --- a/erpnext/support/doctype/service_level/test_service_level.py +++ b/erpnext/support/doctype/service_level/test_service_level.py @@ -12,7 +12,14 @@ import frappe import unittest class TestServiceLevel(unittest.TestCase): - pass + + def test_service_level(self): + test_make_service_level = make_service_level() + get_make_service_level = get_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 make_service_level(): employee_group = make_employee_group() @@ -36,6 +43,7 @@ def make_service_level(): { "priority": "Medium", "response_time": 4, + "default_priority": 1, "response_time_period": "Hour", "resolution_time": 6, "resolution_time_period": "Hour", @@ -107,6 +115,7 @@ def make_service_level(): { "priority": "Medium", "response_time": 2, + "default_priority": 1, "response_time_period": "Day", "resolution_time": 3, "resolution_time_period": "Day", @@ -157,16 +166,16 @@ def make_service_level(): } ] }) - service_level_exist = frappe.db.exists("Service Level", "_Test Service Level") + service_level_exist = frappe.get_doc("Service Level", "_Test Service Level") + if not service_level_exist: service_level.insert() - return service_level.service_level + return service_level else: return service_level_exist def get_service_level(): - service_level = frappe.db.exists("Service Level", "_Test Service Level") - return service_level + return frappe.get_doc("Service Level", "_Test Service Level") def make_holiday_list(): holiday_list = frappe.db.exists("Holiday List", "__Test Holiday List") diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index d1d040722f..3368aff613 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -20,7 +20,7 @@ class ServiceLevelAgreement(Document): if not self.ignore_start_and_end_date and self.start_date >= self.end_date: frappe.throw(_("Start Date of Agreement can't be greater than or equal to End Date.")) - if not self.ignore_start_and_end_date and self.end_date < frappe.utils.today(): + if not self.ignore_start_and_end_date and self.end_date < frappe.utils.getdate(): frappe.throw(_("End Date of Agreement can't be less than today.")) def get_service_level_agreement_priority(self, priority): @@ -64,6 +64,6 @@ def get_active_service_level_agreement_for(priority, customer=None, service_leve 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", "customer"], debug=True) + fields=["name", "default_priority", "customer"]) return agreement[0] if agreement else None \ No newline at end of file diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py index 5ad907a449..2411d2163a 100644 --- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py @@ -8,7 +8,14 @@ import unittest from erpnext.support.doctype.service_level.test_service_level import make_service_level class TestServiceLevelAgreement(unittest.TestCase): - pass + + def test_service_level_agreement(self): + test_make_service_level_agreement = make_service_level_agreement() + test_get_service_level_agreement = get_service_level_agreement() + + self.assertEqual(test_make_service_level_agreement.name, test_get_service_level_agreement.name) + self.assertEqual(test_make_service_level_agreement.customer, test_get_service_level_agreement.customer) + self.assertEqual(test_make_service_level_agreement.default_service_level_agreement, test_get_service_level_agreement.default_service_level_agreement) def make_service_level_agreement(): make_service_level() @@ -34,6 +41,7 @@ def make_service_level_agreement(): { "priority": "Medium", "response_time": 4, + "default_priority": 1, "response_time_period": "Hour", "resolution_time": 6, "resolution_time_period": "Hour", @@ -172,13 +180,14 @@ def make_service_level_agreement(): ] }) - service_level_agreement_exists = frappe.db.exists("Service Level Agreement", "SLA-_Test Service Level Agreement") + service_level_agreement_exists = frappe.get_doc("Service Level Agreement", "SLA-_Test Service Level Agreement") + if not service_level_agreement_exists: service_level_agreement.insert(ignore_permissions=True) - return service_level_agreement.name + return service_level_agreement else: return service_level_agreement_exists def get_service_level_agreement(): - service_level_agreement = frappe.db.exists("Service Level Agreement", "SLA-_Test Service Level Agreement") + service_level_agreement = frappe.get_doc("Service Level Agreement", "SLA-_Test Service Level Agreement") return service_level_agreement \ No newline at end of file From fee2fee83a9580a4365c67aa38fc89232ce8dec4 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 28 May 2019 11:47:51 +0530 Subject: [PATCH 29/92] fix: test cases --- erpnext/support/doctype/service_level/test_service_level.py | 4 ++-- .../service_level_agreement/test_service_level_agreement.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/support/doctype/service_level/test_service_level.py b/erpnext/support/doctype/service_level/test_service_level.py index 79f064358d..9131d807f6 100644 --- a/erpnext/support/doctype/service_level/test_service_level.py +++ b/erpnext/support/doctype/service_level/test_service_level.py @@ -166,13 +166,13 @@ def make_service_level(): } ] }) - service_level_exist = frappe.get_doc("Service Level", "_Test Service Level") + service_level_exist = frappe.db.exists("Service Level", {"service_level": "_Test Service Level"}) if not service_level_exist: service_level.insert() return service_level else: - return service_level_exist + return frappe.get_doc("Service Level", "_Test Service Level") def get_service_level(): return frappe.get_doc("Service Level", "_Test Service Level") diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py index 2411d2163a..2679f97f55 100644 --- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py @@ -94,6 +94,7 @@ def make_service_level_agreement(): }) default_service_level_agreement_exists = frappe.db.exists("Service Level Agreement", "SLA-Default Service Level Agreement") + if not default_service_level_agreement_exists: default_service_level_agreement.insert(ignore_permissions=True) @@ -180,13 +181,13 @@ def make_service_level_agreement(): ] }) - service_level_agreement_exists = frappe.get_doc("Service Level Agreement", "SLA-_Test Service Level Agreement") + service_level_agreement_exists = frappe.db.exists("Service Level Agreement", {"service_level_agreement_name": "_Test Service Level Agreement"}) if not service_level_agreement_exists: service_level_agreement.insert(ignore_permissions=True) return service_level_agreement else: - return service_level_agreement_exists + return frappe.get_doc("Service Level Agreement", "SLA-_Test Service Level Agreement") def get_service_level_agreement(): service_level_agreement = frappe.get_doc("Service Level Agreement", "SLA-_Test Service Level Agreement") From da91cfe1e23eed929e88ae5100d0ffc7c06b7988 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 28 May 2019 23:38:43 +0530 Subject: [PATCH 30/92] fix: set default priority on sla change --- erpnext/support/doctype/issue/issue.js | 1 - erpnext/support/doctype/issue/issue.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index af742acc5f..44b605d91b 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -67,7 +67,6 @@ frappe.ui.form.on("Issue", { message: __('Changing 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(__("Service Level Agreement changed to {0}.", [frm.doc.service_level_agreement])); diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index b47f7108bc..734b4433ba 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -163,7 +163,7 @@ class Issue(Document): self.resolution_by_variance = round(time_diff_in_hours(self.resolution_by, now_datetime())) @frappe.whitelist() - def change_service_level_agreement_and_priority(self, priority, service_level_agreement): + 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) From 68ed272bfa485574bdea47fa649f1588189d46a7 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 3 Jun 2019 18:59:55 +0530 Subject: [PATCH 31/92] feat: show priorities listed in sla in issue --- erpnext/support/doctype/issue/issue.js | 18 ++++++++++++++++++ .../service_level_agreement.py | 6 +++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index 44b605d91b..9ee981dea6 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -43,6 +43,24 @@ frappe.ui.form.on("Issue", { frm.save(); }); } + + frappe.call({ + method: "erpnext.support.doctype.service_level_agreement.service_level_agreement.get_service_level_agreement_priorities", + args: { + name: frm.doc.service_level_agreement, + }, + callback: function (r) { + if (r && r.message) { + frm.set_query('priority', function() { + return { + filters: { + "name": ["in", r.message], + } + }; + }); + } + } + }); }, priority: function(frm) { diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index 3368aff613..8ea29c09ed 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -66,4 +66,8 @@ def get_active_service_level_agreement_for(priority, customer=None, service_leve agreement = frappe.get_list("Service Level Agreement", filters=filters, or_filters=or_filters, fields=["name", "default_priority", "customer"]) - return agreement[0] if agreement else None \ No newline at end of file + return agreement[0] if agreement else None + +@frappe.whitelist() +def get_service_level_agreement_priorities(name): + return [priority.priority for priority in frappe.get_list("Service Level Priority", filters={"parent": name}, fields=["priority"])] \ No newline at end of file From b903da6bfdf7b0feaa5a5607f376d050da163640 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 5 Jun 2019 13:42:03 +0530 Subject: [PATCH 32/92] fix: remove priorities list --- .../support/doctype/service_level/service_level.json | 9 +-------- erpnext/support/doctype/service_level/service_level.py | 9 --------- .../service_level_agreement.json | 10 +--------- 3 files changed, 2 insertions(+), 26 deletions(-) diff --git a/erpnext/support/doctype/service_level/service_level.json b/erpnext/support/doctype/service_level/service_level.json index d4ce7d34d6..ab2f4f2bcb 100644 --- a/erpnext/support/doctype/service_level/service_level.json +++ b/erpnext/support/doctype/service_level/service_level.json @@ -7,7 +7,6 @@ "field_order": [ "service_level", "employee_group", - "priorities_list", "column_break_2", "holiday_list", "default_priority", @@ -74,15 +73,9 @@ "label": "Default Priority", "options": "Issue Priority", "read_only": 1 - }, - { - "fieldname": "priorities_list", - "fieldtype": "Long Text", - "hidden": 1, - "label": "Priorities List" } ], - "modified": "2019-05-25 20:18:00.240337", + "modified": "2019-06-05 13:37:20.342946", "modified_by": "Administrator", "module": "Support", "name": "Service Level", diff --git a/erpnext/support/doctype/service_level/service_level.py b/erpnext/support/doctype/service_level/service_level.py index 80e4e22b90..4e70a01c7a 100644 --- a/erpnext/support/doctype/service_level/service_level.py +++ b/erpnext/support/doctype/service_level/service_level.py @@ -13,7 +13,6 @@ class ServiceLevel(Document): def validate(self): self.check_priorities() - self.set_priorities() self.check_support_and_resolution() def check_priorities(self): @@ -62,14 +61,6 @@ class ServiceLevel(Document): except Exception: frappe.throw(_("Select a Default Priority.")) - def set_priorities(self): - priorities = [] - - for priority in self.priorities: - priorities.append(priority.priority) - - self.priorities_list = ",".join(priorities) - def check_support_and_resolution(self): week = get_weekdays() support_days = [] diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index 98baa6ece9..7722f6ee4f 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -9,7 +9,6 @@ "customer", "default_service_level_agreement", "holiday_list", - "priorities_list", "column_break_2", "service_level", "employee_group", @@ -149,16 +148,9 @@ "label": "Default Priority", "options": "Issue Priority", "read_only": 1 - }, - { - "fetch_from": "service_level.priorities_list", - "fieldname": "priorities_list", - "fieldtype": "Text", - "hidden": 1, - "label": "Priorities List" } ], - "modified": "2019-05-25 20:20:41.231834", + "modified": "2019-06-05 13:41:24.189152", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", From e175dd8249c8fbcb300baebe49c9b711d0128002 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 6 Jun 2019 10:58:42 +0530 Subject: [PATCH 33/92] patch: set priorities for issue --- erpnext/patches.txt | 1 + erpnext/patches/v12_0/set_priority_for_issue.py | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 erpnext/patches/v12_0/set_priority_for_issue.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 480facb3ce..d711e1f17b 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -604,3 +604,4 @@ execute:frappe.delete_doc("Report", "Inactive Items") erpnext.patches.v11_1.delete_scheduling_tool erpnext.patches.v12_0.make_custom_fields_for_bank_remittance execute:frappe.delete_doc_if_exists("Page", "support-analytics") +erpnext.patches.v12_0.set_priority_for_issue diff --git a/erpnext/patches/v12_0/set_priority_for_issue.py b/erpnext/patches/v12_0/set_priority_for_issue.py new file mode 100644 index 0000000000..13d0de1311 --- /dev/null +++ b/erpnext/patches/v12_0/set_priority_for_issue.py @@ -0,0 +1,15 @@ +import frappe + +def execute(): + priorities = frappe.get_meta("Issue").get_field("priority").options.split("\n") + + for priority in priorities: + frappe.get_doc({ + "doctype": "Issue Priority", + "name":priority + }).insert(ignore_permissions=True) + + frappe.reload_doc("support", "doctype", "issue") + + for issue in frappe.get_list("Issue", fields=["name", "priority"]): + frappe.db.set_value("Issue", issue.name, "priority", issue.priority) \ No newline at end of file From b9c24a01dae1358504686e5d92767b434fea64c9 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 6 Jun 2019 11:15:33 +0530 Subject: [PATCH 34/92] patch: reload_doc before inserting values --- erpnext/patches/v12_0/set_priority_for_issue.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/patches/v12_0/set_priority_for_issue.py b/erpnext/patches/v12_0/set_priority_for_issue.py index 13d0de1311..bedf5c3421 100644 --- a/erpnext/patches/v12_0/set_priority_for_issue.py +++ b/erpnext/patches/v12_0/set_priority_for_issue.py @@ -1,6 +1,8 @@ import frappe def execute(): + frappe.reload_doc("support", "doctype", "issue_priority") + priorities = frappe.get_meta("Issue").get_field("priority").options.split("\n") for priority in priorities: From cbbe2814a6032d83548d73cb8e4346674dba8d42 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 6 Jun 2019 11:49:15 +0530 Subject: [PATCH 35/92] patch: add priority in service level and agreement --- erpnext/patches.txt | 2 +- .../patches/v12_0/set_priority_for_issue.py | 17 ------- .../patches/v12_0/set_priority_for_support.py | 47 +++++++++++++++++++ 3 files changed, 48 insertions(+), 18 deletions(-) delete mode 100644 erpnext/patches/v12_0/set_priority_for_issue.py create mode 100644 erpnext/patches/v12_0/set_priority_for_support.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index d711e1f17b..b94f0b23a9 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -604,4 +604,4 @@ execute:frappe.delete_doc("Report", "Inactive Items") erpnext.patches.v11_1.delete_scheduling_tool erpnext.patches.v12_0.make_custom_fields_for_bank_remittance execute:frappe.delete_doc_if_exists("Page", "support-analytics") -erpnext.patches.v12_0.set_priority_for_issue +erpnext.patches.v12_0.set_priority_for_support diff --git a/erpnext/patches/v12_0/set_priority_for_issue.py b/erpnext/patches/v12_0/set_priority_for_issue.py deleted file mode 100644 index bedf5c3421..0000000000 --- a/erpnext/patches/v12_0/set_priority_for_issue.py +++ /dev/null @@ -1,17 +0,0 @@ -import frappe - -def execute(): - frappe.reload_doc("support", "doctype", "issue_priority") - - priorities = frappe.get_meta("Issue").get_field("priority").options.split("\n") - - for priority in priorities: - frappe.get_doc({ - "doctype": "Issue Priority", - "name":priority - }).insert(ignore_permissions=True) - - frappe.reload_doc("support", "doctype", "issue") - - for issue in frappe.get_list("Issue", fields=["name", "priority"]): - frappe.db.set_value("Issue", issue.name, "priority", issue.priority) \ No newline at end of file diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py new file mode 100644 index 0000000000..48338a843d --- /dev/null +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -0,0 +1,47 @@ +import frappe + +def execute(): + frappe.reload_doc("support", "doctype", "issue_priority") + + priorities = frappe.get_meta("Issue").get_field("priority").options.split("\n") + + for priority in priorities: + frappe.get_doc({ + "doctype": "Issue Priority", + "name":priority + }).insert(ignore_permissions=True) + + frappe.reload_doc("support", "doctype", "issue") + frappe.reload_doc("support", "doctype", "service_level") + frappe.reload_doc("support", "doctype", "service_level_agreement") + + for issue in frappe.get_list("Issue", fields=["name", "priority"]): + frappe.db.set_value("Issue", issue.name, "priority", issue.priority) + + for service_level in frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", + "resolution_time", "resolution_time_period"]): + + doc = frappe.get_doc("Service Level", service_level.name) + doc.update("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) + + for service_level_agreement in frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", "response_time_period", + "resolution_time", "resolution_time_period"]): + + doc = frappe.get_doc("Service Level", service_level_agreement.name) + doc.update("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) \ No newline at end of file From 7acdcac124af2e74b06bfbf052a388acf5235fe1 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 6 Jun 2019 11:56:38 +0530 Subject: [PATCH 36/92] patch: fixes --- erpnext/patches/v12_0/set_priority_for_support.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index 48338a843d..5f2d92a023 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -8,7 +8,7 @@ def execute(): for priority in priorities: frappe.get_doc({ "doctype": "Issue Priority", - "name":priority + "name": priority }).insert(ignore_permissions=True) frappe.reload_doc("support", "doctype", "issue") @@ -22,26 +22,26 @@ def execute(): "resolution_time", "resolution_time_period"]): doc = frappe.get_doc("Service Level", service_level.name) - doc.update("priorities": [{ + 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) for service_level_agreement in frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]): - doc = frappe.get_doc("Service Level", service_level_agreement.name) - doc.update("priorities": [{ + doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name) + 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) \ No newline at end of file From b318b83bb793c63fa57c2e37a3b780ca290648bf Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 6 Jun 2019 12:03:37 +0530 Subject: [PATCH 37/92] patch: fixes --- erpnext/patches/v12_0/set_priority_for_support.py | 1 + .../service_level_agreement/service_level_agreement.json | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index 5f2d92a023..f04b45a751 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -36,6 +36,7 @@ def execute(): "resolution_time", "resolution_time_period"]): doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name) + doc.service_level_agreement_name = service_level_agreement.name doc.append("priorities", { "priority": service_level_agreement.priority, "default_priority": 1, diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index 7722f6ee4f..a8183ba52d 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -106,7 +106,7 @@ "collapsible": 1, "fieldname": "response_and_resolution_time_section", "fieldtype": "Section Break", - "label": "Response and Resolution Time" + "label": "Priorities, Response and Resolution Time" }, { "collapsible": 1, @@ -150,7 +150,7 @@ "read_only": 1 } ], - "modified": "2019-06-05 13:41:24.189152", + "modified": "2019-06-06 12:03:11.247979", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", From ab97cd4db179920da4b5e08ef8be3bdf0f087c3e Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 6 Jun 2019 14:13:10 +0530 Subject: [PATCH 38/92] feat: dashboards --- .../doctype/service_level/service_level.json | 4 +- .../service_level/service_level_dashboard.py | 12 +++++ .../service_level_agreement.json | 49 +++++++------------ .../service_level_agreement.py | 24 +++++---- .../service_level_agreement_dashboard.py | 12 +++++ 5 files changed, 54 insertions(+), 47 deletions(-) create mode 100644 erpnext/support/doctype/service_level/service_level_dashboard.py create mode 100644 erpnext/support/doctype/service_level_agreement/service_level_agreement_dashboard.py diff --git a/erpnext/support/doctype/service_level/service_level.json b/erpnext/support/doctype/service_level/service_level.json index ab2f4f2bcb..dced3aa9e9 100644 --- a/erpnext/support/doctype/service_level/service_level.json +++ b/erpnext/support/doctype/service_level/service_level.json @@ -51,7 +51,7 @@ { "fieldname": "section_break_01", "fieldtype": "Section Break", - "label": "Support and Resolution" + "label": "Support Hours" }, { "fieldname": "support_and_resolution", @@ -75,7 +75,7 @@ "read_only": 1 } ], - "modified": "2019-06-05 13:37:20.342946", + "modified": "2019-06-06 12:58:03.464056", "modified_by": "Administrator", "module": "Support", "name": "Service Level", diff --git a/erpnext/support/doctype/service_level/service_level_dashboard.py b/erpnext/support/doctype/service_level/service_level_dashboard.py new file mode 100644 index 0000000000..393095e117 --- /dev/null +++ b/erpnext/support/doctype/service_level/service_level_dashboard.py @@ -0,0 +1,12 @@ +from frappe import _ + +def get_data(): + return { + 'fieldname': 'service_level', + 'transactions': [ + { + 'label': _('Service Level Agreement'), + 'items': ['Service Level Agreement'] + } + ] + } \ No newline at end of file diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index a8183ba52d..c68d385345 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -1,24 +1,22 @@ { - "autoname": "format:SLA-{service_level_agreement_name}", + "autoname": "format:SLA-{service_level}-{####}", "creation": "2018-12-26 21:08:15.448812", "doctype": "DocType", "editable_grid": 1, "engine": "InnoDB", "field_order": [ - "service_level_agreement_name", + "service_level", "customer", "default_service_level_agreement", "holiday_list", "column_break_2", - "service_level", "employee_group", "default_priority", "agreement_details_section", "start_date", - "agreement_status", + "active", "column_break_7", "end_date", - "ignore_start_and_end_date", "response_and_resolution_time_section", "priorities", "support_and_resolution_section_break", @@ -30,6 +28,7 @@ "fieldname": "customer", "fieldtype": "Link", "in_list_view": 1, + "in_standard_filter": 1, "label": "Customer", "options": "Customer", "set_only_once": 1 @@ -39,7 +38,6 @@ "depends_on": "eval: !doc.customer;", "fieldname": "default_service_level_agreement", "fieldtype": "Check", - "in_list_view": 1, "label": "Default Service Level Agreement", "set_only_once": 1 }, @@ -47,6 +45,7 @@ "fieldname": "service_level", "fieldtype": "Link", "in_list_view": 1, + "in_standard_filter": 1, "label": "Service Level", "options": "Service Level", "reqd": 1, @@ -68,6 +67,8 @@ "fetch_from": "service_level.employee_group", "fieldname": "employee_group", "fieldtype": "Link", + "in_list_view": 1, + "in_standard_filter": 1, "label": "Employee Group", "options": "Employee Group", "read_only": 1 @@ -83,14 +84,6 @@ "fieldtype": "Date", "label": "Start Date" }, - { - "default": "Active", - "fieldname": "agreement_status", - "fieldtype": "Select", - "label": "Agreement Status", - "options": "Active\nExpired", - "read_only": 1 - }, { "depends_on": "eval: !doc.default_contract", "fieldname": "column_break_7", @@ -106,13 +99,13 @@ "collapsible": 1, "fieldname": "response_and_resolution_time_section", "fieldtype": "Section Break", - "label": "Priorities, Response and Resolution Time" + "label": "Response and Resolution Time" }, { "collapsible": 1, "fieldname": "support_and_resolution_section_break", "fieldtype": "Section Break", - "label": "Support and Resolution" + "label": "Support Hours" }, { "fieldname": "support_and_resolution", @@ -126,21 +119,6 @@ "label": "Priorities", "options": "Service Level Priority" }, - { - "fieldname": "service_level_agreement_name", - "fieldtype": "Data", - "label": "Service Level Agreement Name", - "reqd": 1, - "unique": 1 - }, - { - "default": "0", - "depends_on": "eval: !doc.default_service_level_agreement", - "fieldname": "ignore_start_and_end_date", - "fieldtype": "Check", - "label": "Ignore Start and End Date", - "set_only_once": 1 - }, { "fetch_from": "service_level.default_priority", "fieldname": "default_priority", @@ -148,9 +126,16 @@ "label": "Default Priority", "options": "Issue Priority", "read_only": 1 + }, + { + "default": "1", + "fieldname": "active", + "fieldtype": "Check", + "label": "Active", + "read_only": 1 } ], - "modified": "2019-06-06 12:03:11.247979", + "modified": "2019-06-06 12:56:24.545060", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index 8ea29c09ed..4ff0312b47 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -14,14 +14,12 @@ class ServiceLevelAgreement(Document): if frappe.db.exists("Service Level Agreement", {"default_service_level_agreement": "1", "name": ["!=", self.name]}): frappe.throw(_("A Default Service Level Agreement already exists.")) else: - if not self.ignore_start_and_end_date and not (self.start_date and self.end_date): - frappe.throw(_("Enter Start and End Date for the Agreement.")) + 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 not self.ignore_start_and_end_date and self.start_date >= self.end_date: - frappe.throw(_("Start Date of Agreement can't be greater than or equal to End Date.")) - - if not self.ignore_start_and_end_date and self.end_date < frappe.utils.getdate(): - frappe.throw(_("End Date of Agreement can't be less than today.")) + if self.end_date < frappe.utils.getdate(): + frappe.throw(_("End Date of Agreement can't be less than today.")) def get_service_level_agreement_priority(self, priority): priority = frappe.get_doc("Service Level Priority", {"priority": priority, "parent": self.name}) @@ -36,18 +34,18 @@ class ServiceLevelAgreement(Document): def check_agreement_status(): service_level_agreements = frappe.get_list("Service Level Agreement", filters=[ - {"agreement_status": "Active"}, + {"active": 1}, {"default_service_level_agreement": 0} - ], fields=["name", "end_date"]) + ], fields=["name"]) for service_level_agreement in service_level_agreements: - if service_level_agreement.end_date < frappe.utils.getdate(): - frappe.db.set_value("Service Level Agreement", service_level_agreement.name, - "agreement_status", "Expired") + doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name) + if doc.end_date and doc.end_date < frappe.utils.getdate(): + frappe.db.set_value("Service Level Agreement", service_level_agreement.name, "active", 0) def get_active_service_level_agreement_for(priority, customer=None, service_level_agreement=None): filters = [ - ["Service Level Agreement", "agreement_status", "=", "Active"] + ["Service Level Agreement", "active", "=", 1] ] if priority: diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement_dashboard.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement_dashboard.py new file mode 100644 index 0000000000..f2bd681396 --- /dev/null +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement_dashboard.py @@ -0,0 +1,12 @@ +from frappe import _ + +def get_data(): + return { + 'fieldname': 'service_level_agreement', + 'transactions': [ + { + 'label': _('Issue'), + 'items': ['Issue'] + } + ] + } \ No newline at end of file From db1d1197eaf683548a64f7d98e0c4148d9b049d0 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 6 Jun 2019 14:17:07 +0530 Subject: [PATCH 39/92] feat: add fixtures --- erpnext/setup/setup_wizard/operations/install_fixtures.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py index 89f4e3036e..4b734df61d 100644 --- a/erpnext/setup/setup_wizard/operations/install_fixtures.py +++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py @@ -173,6 +173,11 @@ def install(country=None): {"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 {'doctype': 'Job Applicant Source', 'source_name': _('Website Listing')}, {'doctype': 'Job Applicant Source', 'source_name': _('Walk In')}, From 0674d16fee33d08c4b69a15f90f6255fae453304 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 7 Jun 2019 15:28:42 +0530 Subject: [PATCH 40/92] feat: sla based on customer/group/territory --- erpnext/hooks.py | 1 - .../patches/v12_0/set_priority_for_support.py | 9 +- .../doctype/customer_group/customer_group.py | 2 +- erpnext/support/doctype/issue/issue.js | 37 +-- erpnext/support/doctype/issue/issue.py | 38 ++- .../service_level_agreement.json | 42 +++- .../service_level_agreement.py | 16 +- .../test_service_level_agreement.py | 226 +++++++++--------- 8 files changed, 194 insertions(+), 177 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index c72dacfd62..b272f60860 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -264,7 +264,6 @@ scheduler_events = { "erpnext.projects.doctype.project.project.send_project_status_email_to_users", "erpnext.quality_management.doctype.quality_review.quality_review.review", "erpnext.support.doctype.service_level_agreement.service_level_agreement.check_agreement_status", - "erpnext.support.doctype.issue.issue.set_service_level_agreement_status" ], "daily_long": [ "erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms" diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index f04b45a751..53aed92f17 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -6,10 +6,11 @@ def execute(): priorities = frappe.get_meta("Issue").get_field("priority").options.split("\n") for priority in priorities: - frappe.get_doc({ - "doctype": "Issue Priority", - "name": priority - }).insert(ignore_permissions=True) + if not frappe.db.exists("Issue Priority", priority): + frappe.get_doc({ + "doctype": "Issue Priority", + "name": priority + }).insert(ignore_permissions=True) frappe.reload_doc("support", "doctype", "issue") frappe.reload_doc("support", "doctype", "service_level") diff --git a/erpnext/setup/doctype/customer_group/customer_group.py b/erpnext/setup/doctype/customer_group/customer_group.py index 388ddcaada..f62613ea1b 100644 --- a/erpnext/setup/doctype/customer_group/customer_group.py +++ b/erpnext/setup/doctype/customer_group/customer_group.py @@ -8,7 +8,7 @@ from frappe import _ from frappe.utils.nestedset import NestedSet class CustomerGroup(NestedSet): - nsm_parent_field = 'parent_customer_group'; + nsm_parent_field = 'parent_customer_group' def on_update(self): self.validate_name_with_customer() diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index 9ee981dea6..7c939737ed 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -1,6 +1,25 @@ frappe.ui.form.on("Issue", { onload: function(frm) { frm.email_field = "raised_by"; + if (frm.doc.service_level_agreement) { + frappe.call({ + method: "erpnext.support.doctype.service_level_agreement.service_level_agreement.get_service_level_agreement_priorities", + args: { + name: frm.doc.service_level_agreement, + }, + callback: function (r) { + if (r && r.message) { + frm.set_query('priority', function() { + return { + filters: { + "name": ["in", r.message], + } + }; + }); + } + } + }); + } }, refresh: function (frm) { @@ -43,24 +62,6 @@ frappe.ui.form.on("Issue", { frm.save(); }); } - - frappe.call({ - method: "erpnext.support.doctype.service_level_agreement.service_level_agreement.get_service_level_agreement_priorities", - args: { - name: frm.doc.service_level_agreement, - }, - callback: function (r) { - if (r && r.message) { - frm.set_query('priority', function() { - return { - filters: { - "name": ["in", r.message], - } - }; - }); - } - } - }); }, priority: function(frm) { diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 734b4433ba..525f8293f6 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -77,11 +77,9 @@ class Issue(Document): def update_agreement_status(self): current_time = frappe.flags.current_time or now_datetime() - if self.service_level_agreement and self.agreement_fulfilled == "Ongoing": - response_time_diff = round(time_diff_in_hours(self.response_by, current_time), 2) - resolution_time_diff = round(time_diff_in_hours(self.resolution_by, current_time), 2) - if response_time_diff < 0 or resolution_time_diff < 0: + if self.service_level_agreement and self.agreement_fulfilled == "Ongoing": + if self.response_by_variance < 0 or self.resolution_by_variance < 0: self.agreement_fulfilled = "Failed" else: self.agreement_fulfilled = "Fulfilled" @@ -232,33 +230,27 @@ def get_expected_time_for(parameter, service_level, start_date_time): return current_date_time -def set_service_level_agreement_status(): - issues = frappe.get_list("Issue", filters={"status": "Open", "agreement_fulfilled": "Ongoing"}) - for issue in issues: - doc = frappe.get_doc("Issue", issue.name) - if doc.service_level_agreement and doc.agreement_fulfilled == "Ongoing": - response_time_diff = round(time_diff_in_hours(doc.response_by, now_datetime()), 2) - resolution_time_diff = round(time_diff_in_hours(doc.resolution_by, now_datetime()), 2) - if response_time_diff < 0 or resolution_time_diff < 0: - frappe.db.set_value("Issue", doc.name, "agreement_fulfilled", "Failed") - else: - frappe.db.set_value("Issue", doc.name, "agreement_fulfilled", "Fulfilled") - def set_service_level_agreement_variance(issue=None): - filters = {"status": "Open", "agreement_fulfilled": "Ongoing"} + current_time = frappe.flags.current_time or now_datetime() + filters = {"status": "Open", "agreement_fulfilled": "Ongoing"} if issue: filters = {"name": issue} - issues = frappe.get_list("Issue", filters=filters) - for issue in issues: + for issue in frappe.get_list("Issue", filters=filters): doc = frappe.get_doc("Issue", issue.name) - if not doc.first_responded_on: - variance = round(time_diff_in_hours(doc.response_by, now_datetime()), 2) + + 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 not doc.resolution_date: - variance = round(time_diff_in_hours(doc.resolution_by, now_datetime()), 2) + 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): return { diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index c68d385345..5b6b7cc239 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -6,12 +6,15 @@ "engine": "InnoDB", "field_order": [ "service_level", - "customer", "default_service_level_agreement", "holiday_list", "column_break_2", "employee_group", "default_priority", + "apply_to_section", + "apply_to", + "column_break_10", + "entity", "agreement_details_section", "start_date", "active", @@ -23,16 +26,6 @@ "support_and_resolution" ], "fields": [ - { - "depends_on": "eval: !doc.default_service_level_agreement;", - "fieldname": "customer", - "fieldtype": "Link", - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Customer", - "options": "Customer", - "set_only_once": 1 - }, { "default": "0", "depends_on": "eval: !doc.customer;", @@ -133,9 +126,34 @@ "fieldtype": "Check", "label": "Active", "read_only": 1 + }, + { + "collapsible_depends_on": "eval: !doc.default_service_level_agreement;", + "fieldname": "apply_to_section", + "fieldtype": "Section Break", + "label": "Apply To" + }, + { + "fieldname": "apply_to", + "fieldtype": "Select", + "in_standard_filter": 1, + "label": "Apply To", + "options": "\nCustomer\nCustomer Group\nTerritory" + }, + { + "fieldname": "column_break_10", + "fieldtype": "Column Break" + }, + { + "fieldname": "entity", + "fieldtype": "Dynamic Link", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Entity", + "options": "apply_to" } ], - "modified": "2019-06-06 12:56:24.545060", + "modified": "2019-06-07 00:30:34.755416", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index 4ff0312b47..ccc287bdc8 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -45,14 +45,14 @@ def check_agreement_status(): def get_active_service_level_agreement_for(priority, customer=None, service_level_agreement=None): filters = [ - ["Service Level Agreement", "active", "=", 1] + ["Service Level Agreement", "active", "=", 1], ] if priority: filters.append(["Service Level Priority", "priority", "=", priority]) or_filters = [ - ["Service Level Agreement", "customer", "=", customer] + ["Service Level Agreement", "entity", "in", [customer, get_customer_group(customer), get_customer_territory(customer)]] ] if service_level_agreement: or_filters = [ @@ -62,10 +62,18 @@ def get_active_service_level_agreement_for(priority, customer=None, service_leve 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", "customer"]) + fields=["name", "default_priority"], debug=True) return agreement[0] if agreement else None @frappe.whitelist() def get_service_level_agreement_priorities(name): - return [priority.priority for priority in frappe.get_list("Service Level Priority", filters={"parent": name}, fields=["priority"])] \ No newline at end of file + return [priority.priority for priority in frappe.get_list("Service Level Priority", filters={"parent": name}, fields=["priority"])] + +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") \ No newline at end of file diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py index 2679f97f55..88e1ee4a90 100644 --- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py @@ -10,136 +10,116 @@ from erpnext.support.doctype.service_level.test_service_level import make_servic class TestServiceLevelAgreement(unittest.TestCase): def test_service_level_agreement(self): - test_make_service_level_agreement = make_service_level_agreement() - test_get_service_level_agreement = get_service_level_agreement() + make_service_level() - self.assertEqual(test_make_service_level_agreement.name, test_get_service_level_agreement.name) - self.assertEqual(test_make_service_level_agreement.customer, test_get_service_level_agreement.customer) - self.assertEqual(test_make_service_level_agreement.default_service_level_agreement, test_get_service_level_agreement.default_service_level_agreement) -def make_service_level_agreement(): - make_service_level() + # Default Service Level Agreement + 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", + apply_to=None, entity=None, response_time=4, resolution_time=6) + get_default_service_level_agreement = get_service_level_agreement(default_service_level_agreement=1) - # Default Service Level Agreement - default_service_level_agreement = frappe.get_doc({ - "doctype": "Service Level Agreement", - "service_level_agreement_name": "Default Service Level Agreement", - "default_service_level_agreement": 1, - "service_level": "__Test Service Level", - "holiday_list": "__Test Holiday List", - "employee_group": "_Test Employee Group", - "start_date": frappe.utils.getdate(), - "end_date": frappe.utils.add_to_date(frappe.utils.getdate(), days=100), - "priorities": [ - { - "priority": "Low", - "response_time": 4, - "response_time_period": "Hour", - "resolution_time": 6, - "resolution_time_period": "Hour", - }, - { - "priority": "Medium", - "response_time": 4, - "default_priority": 1, - "response_time_period": "Hour", - "resolution_time": 6, - "resolution_time_period": "Hour", - }, - { - "priority": "High", - "response_time": 4, - "response_time_period": "Hour", - "resolution_time": 6, - "resolution_time_period": "Hour", - } - ], - "support_and_resolution": [ - { - "workday": "Monday", - "start_time": "10:00:00", - "end_time": "18:00:00", - }, - { - "workday": "Tuesday", - "start_time": "10:00:00", - "end_time": "18:00:00", - }, - { - "workday": "Wednesday", - "start_time": "10:00:00", - "end_time": "18:00:00", - }, - { - "workday": "Thursday", - "start_time": "10:00:00", - "end_time": "18:00:00", - }, - { - "workday": "Friday", - "start_time": "10:00:00", - "end_time": "18:00:00", - }, - { - "workday": "Saturday", - "start_time": "10:00:00", - "end_time": "18:00:00", - }, - { - "workday": "Sunday", - "start_time": "10:00:00", - "end_time": "18:00:00", - } - ] - }) + self.assertEqual(create_default_service_level_agreement.name, get_default_service_level_agreement.name) + self.assertEqual(create_default_service_level_agreement.apply_to, get_default_service_level_agreement.apply_to) + 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) - default_service_level_agreement_exists = frappe.db.exists("Service Level Agreement", "SLA-Default Service Level Agreement") - if not default_service_level_agreement_exists: - default_service_level_agreement.insert(ignore_permissions=True) + # Service Level Agreement for Customer + customer = frappe.get_doc({ + "doctype": "Customer", + "customer_name": "_Test Customer", + "customer_group": "Commercial", + "customer_type": "Individual", + "territory": "Rest Of The World" + }) + if not frappe.db.exists("Customer", "_Test Customer"): + customer.insert(ignore_permissions=True) + else: + customer = frappe.get_doc("Customer", "_Test Customer") - customer = frappe.get_doc({ - "doctype": "Customer", - "customer_name": "_Test Customer", - "customer_group": "Commercial", - "customer_type": "Individual", - "territory": "Rest Of The World" - }) - if not frappe.db.exists("Customer", "_Test Customer"): - customer.insert(ignore_permissions=True) + 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", + apply_to="Customer", entity=customer.name, response_time=2, resolution_time=3) + get_customer_service_level_agreement = get_service_level_agreement(apply_to="Customer", entity=customer.name) + + self.assertEqual(create_customer_service_level_agreement.name, get_customer_service_level_agreement.name) + self.assertEqual(create_customer_service_level_agreement.apply_to, get_customer_service_level_agreement.apply_to) + 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", + apply_to="Customer Group", entity=customer_group.name, response_time=4, resolution_time=6) + get_customer_group_service_level_agreement = get_service_level_agreement(apply_to="Customer Group", entity=customer_group.name) + + self.assertEqual(create_customer_group_service_level_agreement.name, get_customer_group_service_level_agreement.name) + self.assertEqual(create_customer_group_service_level_agreement.apply_to, get_customer_group_service_level_agreement.apply_to) + 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", + apply_to="Territory", entity=territory.name, response_time=2, resolution_time=3) + get_territory_service_level_agreement = get_service_level_agreement(apply_to="Territory", entity=territory.name) + + self.assertEqual(create_territory_service_level_agreement.name, get_territory_service_level_agreement.name) + self.assertEqual(create_territory_service_level_agreement.apply_to, get_territory_service_level_agreement.apply_to) + 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, apply_to=None, entity=None): + if default_service_level_agreement: + filters = {"default_service_level_agreement": default_service_level_agreement} else: - customer = frappe.get_doc("Customer", "_Test Customer") + filters = {"apply_to": apply_to, "entity": entity} + + service_level_agreement = frappe.get_doc("Service Level Agreement", filters) + print(service_level_agreement) + return service_level_agreement + +def create_service_level_agreement(default_service_level_agreement, service_level, holiday_list, employee_group, + response_time, apply_to, entity, resolution_time): service_level_agreement = frappe.get_doc({ "doctype": "Service Level Agreement", - "service_level_agreement_name": "_Test Service Level Agreement", - "customer": customer.customer_name, - "service_level": "_Test Service Level", - "holiday_list": "__Test Holiday List", - "employee_group": "_Test Employee Group", + "default_service_level_agreement": default_service_level_agreement, + "service_level": service_level, + "holiday_list": holiday_list, + "employee_group": employee_group, + "apply_to": apply_to, + "entity": entity, "start_date": frappe.utils.getdate(), "end_date": frappe.utils.add_to_date(frappe.utils.getdate(), days=100), "priorities": [ { "priority": "Low", - "response_time": 2, - "response_time_period": "Day", - "resolution_time": 3, - "resolution_time_period": "Day", + "response_time": response_time, + "response_time_period": "Hour", + "resolution_time": resolution_time, + "resolution_time_period": "Hour", }, { "priority": "Medium", - "response_time": 2, - "response_time_period": "Day", - "resolution_time": 3, - "resolution_time_period": "Day", + "response_time": response_time, + "default_priority": 1, + "response_time_period": "Hour", + "resolution_time": resolution_time, + "resolution_time_period": "Hour", }, { "priority": "High", - "response_time": 2, - "response_time_period": "Day", - "resolution_time": 3, - "resolution_time_period": "Day", + "response_time": response_time, + "response_time_period": "Hour", + "resolution_time": resolution_time, + "resolution_time_period": "Hour", } ], "support_and_resolution": [ @@ -181,14 +161,32 @@ def make_service_level_agreement(): ] }) - service_level_agreement_exists = frappe.db.exists("Service Level Agreement", {"service_level_agreement_name": "_Test Service Level Agreement"}) + service_level_agreement_exists = frappe.db.exists("Service Level Agreement", service_level_agreement.name) 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", "SLA-_Test Service Level Agreement") + return frappe.get_doc("Service Level Agreement", service_level_agreement.name) -def get_service_level_agreement(): - service_level_agreement = frappe.get_doc("Service Level Agreement", "SLA-_Test Service Level Agreement") - return service_level_agreement \ No newline at end of file +def create_customer_group(): + customer_group = frappe.get_doc({ + "doctype": "Customer Group", + "customer_group_name": "_Test SLA Customer Group" + }) + + if not frappe.db.exists("Customer Group", {"customer_group_name": "_Test SLA Customer Group"}): + customer_group.insert() + + return customer_group.name + +def create_territory(): + territory = frappe.get_doc({ + "doctype": "Territory", + "territory_name": "_Test SLA Territory", + }) + + if not frappe.db.exists("Territory", {"territory_name": "_Test SLA Territory"}): + territory.insert() + + return territory.name \ No newline at end of file From 88becdd869d1c9ff981f2acccf0433ae20b20f5b Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 9 Jun 2019 19:33:55 +0530 Subject: [PATCH 41/92] test: test cases for sla with apply_to --- .../test_service_level_agreement.py | 53 ++++++++++--------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py index 88e1ee4a90..214fe4bfcf 100644 --- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py @@ -12,7 +12,6 @@ class TestServiceLevelAgreement(unittest.TestCase): def test_service_level_agreement(self): make_service_level() - # Default Service Level Agreement 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", @@ -24,50 +23,36 @@ class TestServiceLevelAgreement(unittest.TestCase): 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 = frappe.get_doc({ - "doctype": "Customer", - "customer_name": "_Test Customer", - "customer_group": "Commercial", - "customer_type": "Individual", - "territory": "Rest Of The World" - }) - if not frappe.db.exists("Customer", "_Test Customer"): - customer.insert(ignore_permissions=True) - else: - customer = frappe.get_doc("Customer", "_Test 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", - apply_to="Customer", entity=customer.name, response_time=2, resolution_time=3) - get_customer_service_level_agreement = get_service_level_agreement(apply_to="Customer", entity=customer.name) + apply_to="Customer", entity=customer, response_time=2, resolution_time=3) + get_customer_service_level_agreement = get_service_level_agreement(apply_to="Customer", entity=customer) self.assertEqual(create_customer_service_level_agreement.name, get_customer_service_level_agreement.name) self.assertEqual(create_customer_service_level_agreement.apply_to, get_customer_service_level_agreement.apply_to) 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", - apply_to="Customer Group", entity=customer_group.name, response_time=4, resolution_time=6) - get_customer_group_service_level_agreement = get_service_level_agreement(apply_to="Customer Group", entity=customer_group.name) + apply_to="Customer Group", entity=customer_group, response_time=4, resolution_time=6) + get_customer_group_service_level_agreement = get_service_level_agreement(apply_to="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.apply_to, get_customer_group_service_level_agreement.apply_to) 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", - apply_to="Territory", entity=territory.name, response_time=2, resolution_time=3) - get_territory_service_level_agreement = get_service_level_agreement(apply_to="Territory", entity=territory.name) + apply_to="Territory", entity=territory, response_time=2, resolution_time=3) + get_territory_service_level_agreement = get_service_level_agreement(apply_to="Territory", entity=territory) self.assertEqual(create_territory_service_level_agreement.name, get_territory_service_level_agreement.name) self.assertEqual(create_territory_service_level_agreement.apply_to, get_territory_service_level_agreement.apply_to) @@ -169,6 +154,20 @@ def create_service_level_agreement(default_service_level_agreement, service_leve else: return frappe.get_doc("Service Level Agreement", service_level_agreement.name) +def create_customer(): + customer = frappe.get_doc({ + "doctype": "Customer", + "customer_name": "_Test Customer", + "customer_group": "Commercial", + "customer_type": "Individual", + "territory": "Rest Of The World" + }) + if not frappe.db.exists("Customer", "_Test Customer"): + customer.insert(ignore_permissions=True) + return customer.name + else: + return frappe.db.exists("Customer", "_Test Customer") + def create_customer_group(): customer_group = frappe.get_doc({ "doctype": "Customer Group", @@ -177,8 +176,9 @@ def create_customer_group(): if not frappe.db.exists("Customer Group", {"customer_group_name": "_Test SLA Customer Group"}): customer_group.insert() - - return customer_group.name + return customer_group.name + else: + return frappe.db.exists("Customer Group", {"customer_group_name": "_Test SLA Customer Group"}) def create_territory(): territory = frappe.get_doc({ @@ -188,5 +188,6 @@ def create_territory(): if not frappe.db.exists("Territory", {"territory_name": "_Test SLA Territory"}): territory.insert() - - return territory.name \ No newline at end of file + return territory.name + else: + return frappe.db.exists("Territory", {"territory_name": "_Test SLA Territory"}) \ No newline at end of file From 65e0ae21712d4d9a091b96b8cdc69c73cf9f99eb Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 10 Jun 2019 11:24:24 +0530 Subject: [PATCH 42/92] test: new test cases for sla --- erpnext/support/doctype/issue/issue.py | 10 +- erpnext/support/doctype/issue/test_issue.py | 60 +++++++- .../service_level/test_service_level.py | 144 ++++++------------ .../service_level_agreement.py | 2 +- .../test_service_level_agreement.py | 52 +++++-- 5 files changed, 146 insertions(+), 122 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 525f8293f6..773e61a516 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -11,7 +11,7 @@ from frappe.utils import now, time_diff_in_hours, now_datetime, getdate, get_wee from datetime import datetime, timedelta from frappe.model.mapper import get_mapped_doc 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 frappe.email.inbox import link_communication_to_document @@ -63,10 +63,10 @@ class Issue(Document): def update_status(self): status = frappe.db.get_value("Issue", self.name, "status") if self.status!="Open" and status =="Open" and not self.first_responded_on: - self.first_responded_on = now_datetime() + self.first_responded_on = frappe.flags.current_time or now_datetime() if self.status=="Closed" and status !="Closed": - self.resolution_date = now_datetime() + self.resolution_date = frappe.flags.current_time or now_datetime() if frappe.db.get_value("Issue", self.name, "agreement_fulfilled") == "Ongoing": set_service_level_agreement_variance(issue=self.name) self.update_agreement_status() @@ -79,7 +79,9 @@ class Issue(Document): current_time = frappe.flags.current_time or now_datetime() if self.service_level_agreement and self.agreement_fulfilled == "Ongoing": - if self.response_by_variance < 0 or self.resolution_by_variance < 0: + if frappe.db.get_value("Issue", self.name, "response_by_variance") < 0 or \ + frappe.db.get_value("Issue", self.name, "resolution_by_variance") < 0: + self.agreement_fulfilled = "Failed" else: self.agreement_fulfilled = "Fulfilled" diff --git a/erpnext/support/doctype/issue/test_issue.py b/erpnext/support/doctype/issue/test_issue.py index 565c603928..22e00c604e 100644 --- a/erpnext/support/doctype/issue/test_issue.py +++ b/erpnext/support/doctype/issue/test_issue.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe 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 import datetime from datetime import timedelta @@ -18,15 +18,30 @@ class TestIssue(unittest.TestCase): 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" # 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") - self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 7, 18, 0)) - self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 9, 18, 0)) + self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0)) + self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0)) + + # make issue with customer_group specific SLA + customer = create_customer("__Test Customer", "_Test SLA Customer Group", "__Test SLA Territory") + issue = make_issue(creation, "__Test Customer") + + 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") + + self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0)) + self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0)) # make issue with default SLA issue = make_issue(creation) @@ -41,7 +56,7 @@ class TestIssue(unittest.TestCase): self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 18, 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.save() @@ -52,10 +67,39 @@ def make_issue(creation=None, customer=None): issue = frappe.get_doc({ "doctype": "Issue", - "subject": "Issue 1", + "subject": "Service Level Agreement Issue", "customer": customer, "raised_by": "test@example.com", "creation": creation }).insert(ignore_permissions=True) - return issue \ No newline at end of file + 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) diff --git a/erpnext/support/doctype/service_level/test_service_level.py b/erpnext/support/doctype/service_level/test_service_level.py index 9131d807f6..09577df166 100644 --- a/erpnext/support/doctype/service_level/test_service_level.py +++ b/erpnext/support/doctype/service_level/test_service_level.py @@ -4,9 +4,6 @@ from __future__ import unicode_literals from erpnext.hr.doctype.employee_group.test_employee_group import make_employee_group from erpnext.support.doctype.issue_priority.test_issue_priority import make_priorities -from frappe.utils import now_datetime -import datetime -from datetime import timedelta import frappe import unittest @@ -14,45 +11,54 @@ import unittest class TestServiceLevel(unittest.TestCase): def test_service_level(self): - test_make_service_level = make_service_level() - get_make_service_level = get_service_level() + employee_group = make_employee_group() + make_holiday_list() + make_priorities() + + # Default Service Level + 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) -def make_service_level(): - employee_group = make_employee_group() - make_holiday_list() - make_priorities() + # 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") - # Default Service Level Agreement - default_service_level = frappe.get_doc({ + 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", - "service_level": "__Test Service Level", - "holiday_list": "__Test Holiday List", + "service_level": service_level, + "holiday_list": holiday_list, "employee_group": employee_group, "priorities": [ { "priority": "Low", - "response_time": 4, + "response_time": response_time, "response_time_period": "Hour", - "resolution_time": 6, + "resolution_time": resolution_time, "resolution_time_period": "Hour", }, { "priority": "Medium", - "response_time": 4, + "response_time": response_time, "default_priority": 1, "response_time_period": "Hour", - "resolution_time": 6, + "resolution_time": resolution_time, "resolution_time_period": "Hour", }, { "priority": "High", - "response_time": 4, + "response_time": response_time, "response_time_period": "Hour", - "resolution_time": 6, + "resolution_time": resolution_time, "resolution_time_period": "Hour", } ], @@ -95,92 +101,21 @@ def make_service_level(): ] }) - default_service_level_exists = frappe.db.exists("Service Level", "__Test Service Level") - if not default_service_level_exists: - default_service_level.insert() + sl_exists = frappe.db.exists("Service Level", {"service_level": service_level}) - service_level = frappe.get_doc({ - "doctype": "Service Level", - "service_level": "_Test Service Level", - "holiday_list": "__Test Holiday List", - "employee_group": employee_group, - "priorities": [ - { - "priority": "Low", - "response_time": 2, - "response_time_period": "Day", - "resolution_time": 3, - "resolution_time_period": "Day", - }, - { - "priority": "Medium", - "response_time": 2, - "default_priority": 1, - "response_time_period": "Day", - "resolution_time": 3, - "resolution_time_period": "Day", - }, - { - "priority": "High", - "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", {"service_level": "_Test Service Level"}) - - if not service_level_exist: - service_level.insert() - return service_level + if not sl_exists: + sl.insert() + return sl else: - return frappe.get_doc("Service Level", "_Test Service Level") + return frappe.get_doc("Service Level", {"service_level": service_level}) -def get_service_level(): - return frappe.get_doc("Service Level", "_Test Service Level") +def get_service_level(service_level): + return frappe.get_doc("Service Level", service_level) def make_holiday_list(): holiday_list = frappe.db.exists("Holiday List", "__Test Holiday List") if not holiday_list: - now = datetime.datetime.now() + now = frappe.utils.now_datetime() holiday_list = frappe.get_doc({ "doctype": "Holiday List", "holiday_list_name": "__Test Holiday List", @@ -200,4 +135,15 @@ def make_holiday_list(): "holiday_date": "2019-02-11" }, ] - }).insert() \ No newline at end of file + }).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) diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index ccc287bdc8..aeeb86dec5 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -62,7 +62,7 @@ def get_active_service_level_agreement_for(priority, customer=None, service_leve 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"], debug=True) + fields=["name", "default_priority"]) return agreement[0] if agreement else None diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py index 214fe4bfcf..e04265fcc1 100644 --- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py @@ -5,12 +5,12 @@ from __future__ import unicode_literals import frappe 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): def test_service_level_agreement(self): - make_service_level() + create_service_level_for_sla() # Default Service Level Agreement create_default_service_level_agreement = create_service_level_agreement(default_service_level_agreement=1, @@ -26,7 +26,7 @@ class TestServiceLevelAgreement(unittest.TestCase): # 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", + service_level="_Test Service Level", holiday_list="__Test Holiday List", employee_group="_Test Employee Group", apply_to="Customer", entity=customer, response_time=2, resolution_time=3) get_customer_service_level_agreement = get_service_level_agreement(apply_to="Customer", entity=customer) @@ -38,8 +38,8 @@ class TestServiceLevelAgreement(unittest.TestCase): # 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", - apply_to="Customer Group", entity=customer_group, response_time=4, resolution_time=6) + service_level="_Test Service Level", holiday_list="__Test Holiday List", employee_group="_Test Employee Group", + apply_to="Customer Group", entity=customer_group, response_time=2, resolution_time=3) get_customer_group_service_level_agreement = get_service_level_agreement(apply_to="Customer Group", entity=customer_group) self.assertEqual(create_customer_group_service_level_agreement.name, get_customer_group_service_level_agreement.name) @@ -50,7 +50,7 @@ class TestServiceLevelAgreement(unittest.TestCase): # 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", + service_level="_Test Service Level", holiday_list="__Test Holiday List", employee_group="_Test Employee Group", apply_to="Territory", entity=territory, response_time=2, resolution_time=3) get_territory_service_level_agreement = get_service_level_agreement(apply_to="Territory", entity=territory) @@ -67,7 +67,6 @@ def get_service_level_agreement(default_service_level_agreement=None, apply_to=N filters = {"apply_to": apply_to, "entity": entity} service_level_agreement = frappe.get_doc("Service Level Agreement", filters) - print(service_level_agreement) return service_level_agreement def create_service_level_agreement(default_service_level_agreement, service_level, holiday_list, employee_group, @@ -146,13 +145,24 @@ def create_service_level_agreement(default_service_level_agreement, service_leve ] }) - service_level_agreement_exists = frappe.db.exists("Service Level Agreement", service_level_agreement.name) + filters = { + "default_service_level_agreement": service_level_agreement.default_service_level_agreement, + "service_level": service_level_agreement.service_level + } + + if not default_service_level_agreement: + filters.update({ + "apply_to": apply_to, + "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.name) + return frappe.get_doc("Service Level Agreement", service_level_agreement_exists) def create_customer(): customer = frappe.get_doc({ @@ -190,4 +200,26 @@ def create_territory(): territory.insert() return territory.name else: - return frappe.db.exists("Territory", {"territory_name": "_Test SLA Territory"}) \ No newline at end of file + 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", + apply_to=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", + apply_to="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", + apply_to="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", + apply_to="Territory", entity="_Test SLA Territory", response_time=2, resolution_time=3) From 0b36d324ee04648fe31169345430b2c6e4335bc3 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 10 Jun 2019 11:36:51 +0530 Subject: [PATCH 43/92] fix: display depends for apply_to in sla --- .../service_level_agreement/service_level_agreement.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index 5b6b7cc239..f7505d6fdc 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -72,7 +72,7 @@ "label": "Agreement Details" }, { - "depends_on": "eval: !doc.default_service_level_agreement && !doc.ignore_start_and_end_date", + "depends_on": "eval: !doc.default_service_level_agreement", "fieldname": "start_date", "fieldtype": "Date", "label": "Start Date" @@ -83,7 +83,7 @@ "fieldtype": "Column Break" }, { - "depends_on": "eval: !doc.default_service_level_agreement && !doc.ignore_start_and_end_date", + "depends_on": "eval: !doc.default_service_level_agreement", "fieldname": "end_date", "fieldtype": "Date", "label": "End Date" @@ -128,7 +128,7 @@ "read_only": 1 }, { - "collapsible_depends_on": "eval: !doc.default_service_level_agreement;", + "depends_on": "eval: !doc.default_service_level_agreement", "fieldname": "apply_to_section", "fieldtype": "Section Break", "label": "Apply To" @@ -153,7 +153,7 @@ "options": "apply_to" } ], - "modified": "2019-06-07 00:30:34.755416", + "modified": "2019-06-10 11:32:47.778830", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", From 874326dc7b6eae5fcc076bda7255970fafe57150 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 10 Jun 2019 12:33:30 +0530 Subject: [PATCH 44/92] patch: set apply_to as customer --- erpnext/patches/v12_0/set_priority_for_support.py | 6 +++++- erpnext/support/doctype/issue/test_issue.py | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index 53aed92f17..0a12ffab8d 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -37,7 +37,11 @@ def execute(): "resolution_time", "resolution_time_period"]): doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name) - doc.service_level_agreement_name = service_level_agreement.name + + if doc.customer: + doc.append_to = "Customer" + doc.entity = doc.customer + doc.append("priorities", { "priority": service_level_agreement.priority, "default_priority": 1, diff --git a/erpnext/support/doctype/issue/test_issue.py b/erpnext/support/doctype/issue/test_issue.py index 22e00c604e..1a793a6144 100644 --- a/erpnext/support/doctype/issue/test_issue.py +++ b/erpnext/support/doctype/issue/test_issue.py @@ -70,6 +70,7 @@ def make_issue(creation=None, customer=None): "subject": "Service Level Agreement Issue", "customer": customer, "raised_by": "test@example.com", + "description": "Service Level Agreement Issue", "creation": creation }).insert(ignore_permissions=True) From 199b43dbbbc4b16b3a17cabec90d11b7e3d00b24 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 17 Jun 2019 09:35:34 +0530 Subject: [PATCH 45/92] fix: patch fixes for sla --- erpnext/patches/v12_0/set_priority_for_support.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index 0a12ffab8d..2c84e59401 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -39,7 +39,7 @@ def execute(): doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name) if doc.customer: - doc.append_to = "Customer" + doc.apply_to = "Customer" doc.entity = doc.customer doc.append("priorities", { From 67f9b637932176e557b88d77ea98f7e1edfeeb29 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 17 Jun 2019 11:49:02 +0530 Subject: [PATCH 46/92] patch: get priority before reload_doc --- .../patches/v12_0/set_priority_for_support.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index 2c84e59401..cde211b87e 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -12,16 +12,22 @@ def execute(): "name": priority }).insert(ignore_permissions=True) + issue_priority = frappe.get_list("Issue", fields=["name", "priority"]) + + service_level_priority = frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", + "resolution_time", "resolution_time_period"]) + + service_level_agreement_priority = frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", "response_time_period", + "resolution_time", "resolution_time_period"]) + frappe.reload_doc("support", "doctype", "issue") frappe.reload_doc("support", "doctype", "service_level") frappe.reload_doc("support", "doctype", "service_level_agreement") - for issue in frappe.get_list("Issue", fields=["name", "priority"]): + for issue in issue_priority: frappe.db.set_value("Issue", issue.name, "priority", issue.priority) - for service_level in frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", - "resolution_time", "resolution_time_period"]): - + for service_level in service_level_priority: doc = frappe.get_doc("Service Level", service_level.name) doc.append("priorities", { "priority": service_level.priority, @@ -33,8 +39,7 @@ def execute(): }) doc.save(ignore_permissions=True) - for service_level_agreement in frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", "response_time_period", - "resolution_time", "resolution_time_period"]): + for service_level_agreement in service_level_agreement_priority: doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name) From bdf9737d73dd4fe1a1ad11e659c4820e198a97c6 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 17 Jun 2019 18:00:57 +0530 Subject: [PATCH 47/92] patch: reload service level priority --- erpnext/patches/v12_0/set_priority_for_support.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index cde211b87e..a7465a36de 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -21,6 +21,7 @@ def execute(): "resolution_time", "resolution_time_period"]) frappe.reload_doc("support", "doctype", "issue") + frappe.reload_doc("support", "doctype", "service_level_priority") frappe.reload_doc("support", "doctype", "service_level") frappe.reload_doc("support", "doctype", "service_level_agreement") From 0ad3887d516c2f344e6ef853f4b701472a7fff6f Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 17 Jun 2019 23:52:53 +0530 Subject: [PATCH 48/92] patch: fixes --- erpnext/patches/v12_0/set_priority_for_support.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index a7465a36de..966978a490 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -14,11 +14,11 @@ def execute(): issue_priority = frappe.get_list("Issue", fields=["name", "priority"]) - service_level_priority = frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", + service_level_priority = frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", \ "resolution_time", "resolution_time_period"]) - service_level_agreement_priority = frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", "response_time_period", - "resolution_time", "resolution_time_period"]) + service_level_agreement_priority = frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", \ + "response_time_period", "resolution_time", "resolution_time_period"]) frappe.reload_doc("support", "doctype", "issue") frappe.reload_doc("support", "doctype", "service_level_priority") From befd393dcbb3e389f0e9e3abbb0b1b9c1f38d477 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 18 Jun 2019 12:51:12 +0530 Subject: [PATCH 49/92] fix: patch --- erpnext/patches/v12_0/set_priority_for_support.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index 966978a490..009740dfba 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -14,11 +14,9 @@ def execute(): issue_priority = frappe.get_list("Issue", fields=["name", "priority"]) - service_level_priority = frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", \ - "resolution_time", "resolution_time_period"]) + service_level_priority = frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]) - service_level_agreement_priority = frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", \ - "response_time_period", "resolution_time", "resolution_time_period"]) + service_level_agreement_priority = frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]) frappe.reload_doc("support", "doctype", "issue") frappe.reload_doc("support", "doctype", "service_level_priority") From 7881e838c6b58725d7634d28fa829f702c9b1a42 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 18 Jun 2019 19:35:50 +0530 Subject: [PATCH 50/92] patch: refactor patch for travis test --- .../patches/v12_0/set_priority_for_support.py | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index 009740dfba..d0c6c4f039 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -2,30 +2,32 @@ import frappe def execute(): frappe.reload_doc("support", "doctype", "issue_priority") + frappe.reload_doc("support", "doctype", "service_level_priority") - priorities = frappe.get_meta("Issue").get_field("priority").options.split("\n") + set_issue_priority() + set_priority_for_issue() + set_priorities_service_level() + set_priorities_service_level_agreement() - for priority in priorities: +def set_issue_priority(): + for priority in frappe.get_meta("Issue").get_field("priority").options.split("\n"): if not frappe.db.exists("Issue Priority", priority): frappe.get_doc({ "doctype": "Issue Priority", "name": priority }).insert(ignore_permissions=True) +def set_priority_for_issue(): issue_priority = frappe.get_list("Issue", fields=["name", "priority"]) - - service_level_priority = frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]) - - service_level_agreement_priority = frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]) - frappe.reload_doc("support", "doctype", "issue") - frappe.reload_doc("support", "doctype", "service_level_priority") - frappe.reload_doc("support", "doctype", "service_level") - frappe.reload_doc("support", "doctype", "service_level_agreement") for issue in issue_priority: frappe.db.set_value("Issue", issue.name, "priority", issue.priority) +def set_priorities_service_level(): + 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_priority: doc = frappe.get_doc("Service Level", service_level.name) doc.append("priorities", { @@ -38,8 +40,11 @@ def execute(): }) doc.save(ignore_permissions=True) - for service_level_agreement in service_level_agreement_priority: +def set_priorities_service_level_agreement(): + service_level_agreement_priority = 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_priority: doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name) if doc.customer: From e48ca44bf5e7be9d1d19cced6e73c1c7f872f0be Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 18 Jun 2019 20:02:00 +0530 Subject: [PATCH 51/92] patch: fix typo --- erpnext/patches/v12_0/set_priority_for_support.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index d0c6c4f039..85537f8a0a 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -28,7 +28,7 @@ def set_priorities_service_level(): 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_priority: + for service_level in service_level_priorities: doc = frappe.get_doc("Service Level", service_level.name) doc.append("priorities", { "priority": service_level.priority, @@ -41,10 +41,10 @@ def set_priorities_service_level(): doc.save(ignore_permissions=True) def set_priorities_service_level_agreement(): - service_level_agreement_priority = frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]) + 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_priority: + for service_level_agreement in service_level_agreement_priorities: doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name) if doc.customer: From f4f7e781c5952bc55e9d2ddbd7e943a14dfc17bb Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 19 Jun 2019 12:01:59 +0530 Subject: [PATCH 52/92] debug: travis --- erpnext/patches/v12_0/set_priority_for_support.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index 85537f8a0a..08a9e2832e 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -25,7 +25,8 @@ def set_priority_for_issue(): frappe.db.set_value("Issue", issue.name, "priority", issue.priority) def set_priorities_service_level(): - service_level_priorities = frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]) + service_level_priorities = frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"], debug=True) + print(service_level_priorities) frappe.reload_doc("support", "doctype", "service_level") for service_level in service_level_priorities: @@ -41,7 +42,8 @@ def set_priorities_service_level(): doc.save(ignore_permissions=True) def set_priorities_service_level_agreement(): - service_level_agreement_priorities = frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]) + service_level_agreement_priorities = frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"], debug=True) + print(service_level_agreement_priorities) frappe.reload_doc("support", "doctype", "service_level_agreement") for service_level_agreement in service_level_agreement_priorities: From 36d6e570c485de5278096b428bfb8c1ae3e91544 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 19 Jun 2019 14:43:21 +0530 Subject: [PATCH 53/92] patch: try catch to handle TableMissingError --- .../patches/v12_0/set_priority_for_support.py | 68 ++++++++++--------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index 08a9e2832e..e61fbabec3 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -25,40 +25,46 @@ def set_priority_for_issue(): frappe.db.set_value("Issue", issue.name, "priority", issue.priority) def set_priorities_service_level(): - service_level_priorities = frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"], debug=True) - print(service_level_priorities) - frappe.reload_doc("support", "doctype", "service_level") + try: + service_level_priorities = frappe.get_list("Service Level", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]) - for service_level in service_level_priorities: - 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) + frappe.reload_doc("support", "doctype", "service_level") + + for service_level in service_level_priorities: + 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(): - service_level_agreement_priorities = frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"], debug=True) - print(service_level_agreement_priorities) - frappe.reload_doc("support", "doctype", "service_level_agreement") + try: + service_level_agreement_priorities = frappe.get_list("Service Level Agreement", fields=["name", "priority", "response_time", "response_time_period", "resolution_time", "resolution_time_period"]) - for service_level_agreement in service_level_agreement_priorities: - doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name) + frappe.reload_doc("support", "doctype", "service_level_agreement") - if doc.customer: - doc.apply_to = "Customer" - doc.entity = doc.customer + for service_level_agreement in service_level_agreement_priorities: + doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name) - 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) \ No newline at end of file + if doc.customer: + doc.apply_to = "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") \ No newline at end of file From 41bf0c6855d11b863f012ca4cc5d60ca0019203a Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 20 Jun 2019 10:00:11 +0530 Subject: [PATCH 54/92] feat: filter sla based on customer in issue --- .../v12_0/move_parameters_to_priority.py | 38 ------------------- erpnext/support/doctype/issue/issue.js | 19 ++++++++++ .../service_level_agreement.py | 12 ++++++ 3 files changed, 31 insertions(+), 38 deletions(-) delete mode 100644 erpnext/patches/v12_0/move_parameters_to_priority.py diff --git a/erpnext/patches/v12_0/move_parameters_to_priority.py b/erpnext/patches/v12_0/move_parameters_to_priority.py deleted file mode 100644 index 310bfe2572..0000000000 --- a/erpnext/patches/v12_0/move_parameters_to_priority.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -def execute(): - priority = ["Low", "Medium", "High"] - - service_levels = frappe.get_list("Service Level") - for service_level in service_levels: - doc = frappe.get_doc("Service Level", service_level) - for value in priority: - doc.append("priorities", - { - "priority": "{0}".format(value), - "response_time": doc.response_time, - "response_time_period": doc.response_time_period, - "resolution_time": doc.resolution_time, - "resolution_time_period": doc.resolution_time_period, - } - ) - doc.save(ignore_permissions=True) - - service_level_agreements = frappe.get_list("Service Level Agreement") - for service_level_agreement in service_level_agreements: - doc = frappe.get_doc("Service Level Agreement", service_level_agreement) - for value in priority: - doc.append("priorities", - { - "priority": "{0}".format(value), - "response_time": doc.response_time, - "response_time_period": doc.response_time_period, - "resolution_time": doc.resolution_time, - "resolution_time_period": doc.resolution_time_period, - } - ) - doc.save(ignore_permissions=True) \ No newline at end of file diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index 7c939737ed..05bfe97c3d 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -1,6 +1,7 @@ frappe.ui.form.on("Issue", { onload: function(frm) { frm.email_field = "raised_by"; + if (frm.doc.service_level_agreement) { frappe.call({ method: "erpnext.support.doctype.service_level_agreement.service_level_agreement.get_service_level_agreement_priorities", @@ -19,6 +20,24 @@ frappe.ui.form.on("Issue", { } } }); + + frappe.call({ + method: "erpnext.support.doctype.service_level_agreement.service_level_agreement.get_valid_service_level_agreements", + args: { + customer: frm.doc.customer, + }, + callback: function (r) { + if (r && r.message) { + frm.set_query('service_level_agreement', function() { + return { + filters: { + "name": ["in", r.message], + } + }; + }); + } + } + }); } }, diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index aeeb86dec5..5d71e1fa43 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -70,6 +70,18 @@ def get_active_service_level_agreement_for(priority, customer=None, service_leve def get_service_level_agreement_priorities(name): return [priority.priority for priority in frappe.get_list("Service Level Priority", filters={"parent": name}, fields=["priority"])] +@frappe.whitelist() +def get_valid_service_level_agreements(customer): + 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] + ] + + if not customer: + or_filters = ["Service Level Agreement", "default_service_level_agreement", "=", 1] + + return [d.name for d in frappe.get_list("Service Level Agreement", or_filters=or_filters)] + def get_customer_group(customer): if customer: return frappe.db.get_value("Customer", customer, "customer_group") From bbe84ac0eff06091557923d8b894313987cf0ddc Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 20 Jun 2019 10:53:34 +0530 Subject: [PATCH 55/92] feat: change apply_to to entity --- .../patches/v12_0/set_priority_for_support.py | 2 +- .../service_level_agreement.json | 34 ++++++++-------- .../test_service_level_agreement.py | 40 +++++++++---------- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index e61fbabec3..21bb400759 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -54,7 +54,7 @@ def set_priorities_service_level_agreement(): doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name) if doc.customer: - doc.apply_to = "Customer" + doc.entity_type = "Customer" doc.entity = doc.customer doc.append("priorities", { diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index f7505d6fdc..17ccb5c76a 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -11,8 +11,8 @@ "column_break_2", "employee_group", "default_priority", - "apply_to_section", - "apply_to", + "entity_section", + "entity_type", "column_break_10", "entity", "agreement_details_section", @@ -127,19 +127,6 @@ "label": "Active", "read_only": 1 }, - { - "depends_on": "eval: !doc.default_service_level_agreement", - "fieldname": "apply_to_section", - "fieldtype": "Section Break", - "label": "Apply To" - }, - { - "fieldname": "apply_to", - "fieldtype": "Select", - "in_standard_filter": 1, - "label": "Apply To", - "options": "\nCustomer\nCustomer Group\nTerritory" - }, { "fieldname": "column_break_10", "fieldtype": "Column Break" @@ -150,10 +137,23 @@ "in_list_view": 1, "in_standard_filter": 1, "label": "Entity", - "options": "apply_to" + "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" } ], - "modified": "2019-06-10 11:32:47.778830", + "modified": "2019-06-20 10:34:58.634693", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py index e04265fcc1..6aa5394192 100644 --- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py @@ -15,11 +15,11 @@ class TestServiceLevelAgreement(unittest.TestCase): # Default Service Level Agreement 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", - apply_to=None, entity=None, response_time=4, resolution_time=6) + 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.apply_to, get_default_service_level_agreement.apply_to) + 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) @@ -27,11 +27,11 @@ class TestServiceLevelAgreement(unittest.TestCase): 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", - apply_to="Customer", entity=customer, response_time=2, resolution_time=3) - get_customer_service_level_agreement = get_service_level_agreement(apply_to="Customer", entity=customer) + 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.apply_to, get_customer_service_level_agreement.apply_to) + 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) @@ -39,11 +39,11 @@ class TestServiceLevelAgreement(unittest.TestCase): 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", - apply_to="Customer Group", entity=customer_group, response_time=2, resolution_time=3) - get_customer_group_service_level_agreement = get_service_level_agreement(apply_to="Customer Group", entity=customer_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.apply_to, get_customer_group_service_level_agreement.apply_to) + 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) @@ -51,26 +51,26 @@ class TestServiceLevelAgreement(unittest.TestCase): 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", - apply_to="Territory", entity=territory, response_time=2, resolution_time=3) - get_territory_service_level_agreement = get_service_level_agreement(apply_to="Territory", entity=territory) + 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.apply_to, get_territory_service_level_agreement.apply_to) + 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, apply_to=None, entity=None): +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 = {"apply_to": apply_to, "entity": entity} + 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, apply_to, entity, resolution_time): + response_time, entity_type, entity, resolution_time): service_level_agreement = frappe.get_doc({ "doctype": "Service Level Agreement", @@ -78,7 +78,7 @@ def create_service_level_agreement(default_service_level_agreement, service_leve "service_level": service_level, "holiday_list": holiday_list, "employee_group": employee_group, - "apply_to": apply_to, + "entity_type": entity_type, "entity": entity, "start_date": frappe.utils.getdate(), "end_date": frappe.utils.add_to_date(frappe.utils.getdate(), days=100), @@ -152,7 +152,7 @@ def create_service_level_agreement(default_service_level_agreement, service_leve if not default_service_level_agreement: filters.update({ - "apply_to": apply_to, + "entity_type": entity_type, "entity": entity }) @@ -207,19 +207,19 @@ def create_service_level_agreements_for_issues(): create_service_level_agreement(default_service_level_agreement=1, service_level="__Test Service Level", holiday_list="__Test Holiday List", employee_group="_Test Employee Group", - apply_to=None, entity=None, response_time=4, resolution_time=6) + 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", - apply_to="Customer", entity="_Test Customer", response_time=2, resolution_time=3) + 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", - apply_to="Customer Group", entity="_Test SLA Customer Group", response_time=2, resolution_time=3) + 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", - apply_to="Territory", entity="_Test SLA Territory", response_time=2, resolution_time=3) + entity_type="Territory", entity="_Test SLA Territory", response_time=2, resolution_time=3) From a03aa0014e554a971621589d67a27a5e855381eb Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 20 Jun 2019 11:32:49 +0530 Subject: [PATCH 56/92] feat: update sla using custom script --- erpnext/support/doctype/issue/issue.py | 15 +++++++++++++-- .../service_level_agreement.py | 16 +++++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 773e61a516..3fe8ca0bc6 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -76,8 +76,6 @@ class Issue(Document): self.resolution_date = None 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 frappe.db.get_value("Issue", self.name, "response_by_variance") < 0 or \ frappe.db.get_value("Issue", self.name, "resolution_by_variance") < 0: @@ -86,6 +84,19 @@ class Issue(Document): else: 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): communication = frappe.new_doc("Communication") communication.update({ diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index 5d71e1fa43..6231812744 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -71,14 +71,16 @@ def get_service_level_agreement_priorities(name): return [priority.priority for priority in frappe.get_list("Service Level Priority", filters={"parent": name}, fields=["priority"])] @frappe.whitelist() -def get_valid_service_level_agreements(customer): - 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] - ] - +def get_valid_service_level_agreements(customer=None): if not customer: - or_filters = ["Service Level Agreement", "default_service_level_agreement", "=", 1] + 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 [d.name for d in frappe.get_list("Service Level Agreement", or_filters=or_filters)] From 9f19a82ec99c9b614132f4f08928b1776260ce62 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 20 Jun 2019 23:29:56 +0530 Subject: [PATCH 57/92] fix: scheduling bug if out of bussiness hours --- erpnext/support/doctype/issue/issue.py | 6 +- erpnext/support/doctype/issue/test_issue.py | 59 ++++++++++++++----- .../service_level_agreement.json | 8 +-- .../service_level_agreement.py | 4 ++ 4 files changed, 54 insertions(+), 23 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 3fe8ca0bc6..b8d213c6c4 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -7,7 +7,7 @@ import json from frappe import _ from frappe import utils from frappe.model.document import Document -from frappe.utils import now, time_diff_in_hours, now_datetime, getdate, get_weekdays, add_to_date, today, get_time, get_datetime +from frappe.utils import now, time_diff_in_hours, now_datetime, getdate, get_weekdays, add_to_date, today, get_time, get_datetime, get_time_in_timedelta from datetime import datetime, timedelta from frappe.model.mapper import get_mapped_doc from frappe.utils.user import is_website_user @@ -217,7 +217,9 @@ def get_expected_time_for(parameter, service_level, start_date_time): current_weekday = weekdays[current_date_time.weekday()] if not is_holiday(current_date_time, holidays) and current_weekday in support_days: - start_time = current_date_time - datetime(current_date_time.year, current_date_time.month, current_date_time.day) if getdate(current_date_time) == getdate(start_date_time) else support_days[current_weekday].start_time + start_time = current_date_time - datetime(current_date_time.year, current_date_time.month, current_date_time.day) \ + if getdate(current_date_time) == getdate(start_date_time) and get_time_in_timedelta(current_date_time.time()) > support_days[current_weekday].start_time \ + else support_days[current_weekday].start_time end_time = support_days[current_weekday].end_time time_left_today = time_diff_in_hours(end_time, start_time) diff --git a/erpnext/support/doctype/issue/test_issue.py b/erpnext/support/doctype/issue/test_issue.py index 1a793a6144..519c107608 100644 --- a/erpnext/support/doctype/issue/test_issue.py +++ b/erpnext/support/doctype/issue/test_issue.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe import unittest from erpnext.support.doctype.service_level_agreement.test_service_level_agreement import create_service_level_agreements_for_issues -from frappe.utils import now_datetime +from frappe.utils import now_datetime, get_datetime import datetime from datetime import timedelta from frappe.desk.form import assign_to @@ -20,38 +20,65 @@ class TestIssue(unittest.TestCase): def test_response_time_and_resolution_time_based_on_different_sla(self): create_service_level_agreements_for_issues() - creation = "2019-03-04 12:00:00" - - # make issue with customer specific SLA + creation = datetime.datetime(2019, 3, 4, 12, 0) + """ + make issue with customer specific SLA + """ customer = create_customer("_Test Customer", "__Test SLA Customer Group", "__Test SLA Territory") - issue = make_issue(creation, "_Test Customer") + issue = make_issue(creation, "_Test Customer", 1) self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0)) self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0)) - # make issue with customer_group specific SLA + """ + make issue with customer_group specific SLA + """ customer = create_customer("__Test Customer", "_Test SLA Customer Group", "__Test SLA Territory") - issue = make_issue(creation, "__Test Customer") + issue = make_issue(creation, "__Test Customer", 2) self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0)) self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0)) - # make issue with territory specific SLA + """ + make issue with territory specific SLA + """ customer = create_customer("___Test Customer", "__Test SLA Customer Group", "_Test SLA Territory") - issue = make_issue(creation, "___Test Customer") + issue = make_issue(creation, "___Test Customer", 3) self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0)) self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0)) - # make issue with default SLA - issue = make_issue(creation) + """ + make issue with default SLA + """ + issue = make_issue(creation=creation, index=4) self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 16, 0)) self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 18, 0)) - creation = "2019-03-04 14:00:00" - # make issue with default SLA next day - issue = make_issue(creation) + """ + make issue with default SLA before working hours + """ + creation = datetime.datetime(2019, 3, 4, 7, 0) + issue = make_issue(creation=creation, index=5) + + self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0)) + self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 16, 0)) + + """ + make issue with default SLA after working hours + """ + creation = datetime.datetime(2019, 3, 4, 20, 0) + issue = make_issue(creation, index=6) + + self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 6, 14, 0)) + self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 6, 16, 0)) + + """ + make issue with default SLA next day + """ + creation = datetime.datetime(2019, 3, 4, 14, 0) + issue = make_issue(creation=creation, index=7) self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 18, 0)) self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 6, 12, 0)) @@ -63,11 +90,11 @@ class TestIssue(unittest.TestCase): self.assertEqual(issue.agreement_fulfilled, 'Fulfilled') -def make_issue(creation=None, customer=None): +def make_issue(creation=None, customer=None, index=0): issue = frappe.get_doc({ "doctype": "Issue", - "subject": "Service Level Agreement Issue", + "subject": "Service Level Agreement Issue {0}".format(index), "customer": customer, "raised_by": "test@example.com", "description": "Service Level Agreement Issue", diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json index 17ccb5c76a..f91a80c60d 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json @@ -31,8 +31,7 @@ "depends_on": "eval: !doc.customer;", "fieldname": "default_service_level_agreement", "fieldtype": "Check", - "label": "Default Service Level Agreement", - "set_only_once": 1 + "label": "Default Service Level Agreement" }, { "fieldname": "service_level", @@ -41,8 +40,7 @@ "in_standard_filter": 1, "label": "Service Level", "options": "Service Level", - "reqd": 1, - "set_only_once": 1 + "reqd": 1 }, { "fetch_from": "service_level.holiday_list", @@ -153,7 +151,7 @@ "options": "\nCustomer\nCustomer Group\nTerritory" } ], - "modified": "2019-06-20 10:34:58.634693", + "modified": "2019-06-20 18:04:14.293378", "modified_by": "Administrator", "module": "Support", "name": "Service Level Agreement", diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index 6231812744..b804581298 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -21,6 +21,10 @@ class ServiceLevelAgreement(Document): if self.end_date < frappe.utils.getdate(): frappe.throw(_("End Date of Agreement can't be less than today.")) + if self.entity_type and self.entity: + if frappe.db.exists("Service Level Agreement", {"entity_type": self.entity_type, "entity": self.entity, "name": ["!=", self.name]}): + frappe.throw(_("Service Level Agreement with Entity Type {0} and Entity {1} already exists.").format(self.entity_type, self.entity)) + def get_service_level_agreement_priority(self, priority): priority = frappe.get_doc("Service Level Priority", {"priority": priority, "parent": self.name}) From aef77058b6f8cf4f61d292f760318bd9e4f8942c Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Fri, 21 Jun 2019 11:37:45 +0530 Subject: [PATCH 58/92] fix(BOM): set default value of include_exploded_item to 0 --- .../doctype/purchase_order_item/purchase_order_item.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json index 1b63f8f857..3afa7d242c 100644 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json @@ -557,7 +557,7 @@ "print_hide": 1 }, { - "default": "1", + "default": "0", "depends_on": "eval:parent.is_subcontracted == 'Yes'", "fieldname": "include_exploded_items", "fieldtype": "Check", @@ -712,4 +712,4 @@ "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 -} \ No newline at end of file +} From d1ca820e1ed0ab13f33004d5cefbc59ad77b44b1 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 21 Jun 2019 22:57:06 +0530 Subject: [PATCH 59/92] fix: add function for timedelta conversion --- erpnext/support/doctype/issue/issue.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index b8d213c6c4..05ae573694 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -7,7 +7,7 @@ import json from frappe import _ from frappe import utils from frappe.model.document import Document -from frappe.utils import now, time_diff_in_hours, now_datetime, getdate, get_weekdays, add_to_date, today, get_time, get_datetime, get_time_in_timedelta +from frappe.utils import now, time_diff_in_hours, now_datetime, getdate, get_weekdays, add_to_date, today, get_time, get_datetime from datetime import datetime, timedelta from frappe.model.mapper import get_mapped_doc from frappe.utils.user import is_website_user @@ -366,3 +366,9 @@ def make_issue_from_communication(communication, ignore_communication_links=Fals link_communication_to_document(doc, "Issue", issue.name, ignore_communication_links) return issue.name + +def get_time_in_timedelta(time): + """ + Converts datetime.time(10, 36, 55, 961454) to datetime.timedelta(seconds=38215) + """ + return datetime.timedelta(hours=time.hour, minutes=time.minute, seconds=time.second) \ No newline at end of file From 9a6517f8f0aaa27b3a121638d489e9b8c3fca04e Mon Sep 17 00:00:00 2001 From: sahil28297 <37302950+sahil28297@users.noreply.github.com> Date: Sun, 23 Jun 2019 20:06:18 +0530 Subject: [PATCH 60/92] fix(BOM): update modified field --- .../buying/doctype/purchase_order_item/purchase_order_item.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json index 3afa7d242c..05c4926fab 100644 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json @@ -701,7 +701,7 @@ ], "idx": 1, "istable": 1, - "modified": "2019-06-02 06:34:47.495730", + "modified": "2019-06-23 20:03:13.818917", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order Item", From de8c38f0fe12619c4f0cf3a30199481b537a981d Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 24 Jun 2019 00:31:33 +0530 Subject: [PATCH 61/92] fix: datetime import --- erpnext/support/doctype/issue/issue.py | 1 + .../support/doctype/issue_priority/test_issue_priority.py | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 05ae573694..0f6dd72f04 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -371,4 +371,5 @@ 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) \ No newline at end of file diff --git a/erpnext/support/doctype/issue_priority/test_issue_priority.py b/erpnext/support/doctype/issue_priority/test_issue_priority.py index 0d65122c0d..a7b55f8a74 100644 --- a/erpnext/support/doctype/issue_priority/test_issue_priority.py +++ b/erpnext/support/doctype/issue_priority/test_issue_priority.py @@ -7,7 +7,13 @@ import frappe import unittest class TestIssuePriority(unittest.TestCase): - pass + + 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") From 54ece39aefe5162eacb96047b79e3ba3a3bcfe88 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 24 Jun 2019 15:18:56 +0530 Subject: [PATCH 62/92] fix: review changes --- .../patches/v12_0/set_priority_for_support.py | 6 ++++ erpnext/support/doctype/issue/issue.js | 26 +++------------- erpnext/support/doctype/issue/test_issue.py | 30 ++++++------------- .../service_level_agreement.py | 25 ++++++++-------- 4 files changed, 31 insertions(+), 56 deletions(-) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index 21bb400759..e41b8b1bfc 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -10,6 +10,7 @@ def execute(): 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 not frappe.db.exists("Issue Priority", priority): frappe.get_doc({ @@ -18,6 +19,7 @@ def set_issue_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") @@ -25,6 +27,8 @@ def set_priority_for_issue(): 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"]) @@ -45,6 +49,8 @@ def set_priorities_service_level(): 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"]) diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index 05bfe97c3d..ba54edcf39 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -4,34 +4,24 @@ frappe.ui.form.on("Issue", { if (frm.doc.service_level_agreement) { frappe.call({ - method: "erpnext.support.doctype.service_level_agreement.service_level_agreement.get_service_level_agreement_priorities", + 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], + "name": ["in", r.message.priority], } }; }); - } - } - }); - - frappe.call({ - method: "erpnext.support.doctype.service_level_agreement.service_level_agreement.get_valid_service_level_agreements", - args: { - customer: frm.doc.customer, - }, - callback: function (r) { - if (r && r.message) { frm.set_query('service_level_agreement', function() { return { filters: { - "name": ["in", r.message], + "name": ["in", r.message.service_level_agreements], } }; }); @@ -85,10 +75,6 @@ frappe.ui.form.on("Issue", { priority: function(frm) { if (frm.doc.service_level_agreement) { - frappe.show_alert({ - indicator: 'green', - message: __('Changing Priority.') - }); frm.call('change_service_level_agreement_and_priority', { "priority": frm.doc.priority, "service_level_agreement": frm.doc.service_level_agreement @@ -100,10 +86,6 @@ frappe.ui.form.on("Issue", { }, service_level_agreement: function(frm) { - frappe.show_alert({ - indicator: 'green', - message: __('Changing Service Level Agreement.') - }); frm.call('change_service_level_agreement_and_priority', { "service_level_agreement": frm.doc.service_level_agreement }).then(() => { diff --git a/erpnext/support/doctype/issue/test_issue.py b/erpnext/support/doctype/issue/test_issue.py index 519c107608..1296b3609d 100644 --- a/erpnext/support/doctype/issue/test_issue.py +++ b/erpnext/support/doctype/issue/test_issue.py @@ -21,62 +21,50 @@ class TestIssue(unittest.TestCase): create_service_level_agreements_for_issues() creation = datetime.datetime(2019, 3, 4, 12, 0) - """ - make issue with customer specific SLA - """ + + # make issue with customer specific SLA 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, 4, 14, 0)) self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0)) - """ - make issue with customer_group specific SLA - """ + # make issue with customer_group specific SLA customer = create_customer("__Test Customer", "_Test SLA Customer Group", "__Test SLA Territory") issue = make_issue(creation, "__Test Customer", 2) self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0)) self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0)) - """ - make issue with territory specific SLA - """ + + # make issue with territory specific SLA customer = create_customer("___Test Customer", "__Test SLA Customer Group", "_Test SLA Territory") issue = make_issue(creation, "___Test Customer", 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=creation, index=4) self.assertEquals(issue.response_by, datetime.datetime(2019, 3, 4, 16, 0)) self.assertEquals(issue.resolution_by, datetime.datetime(2019, 3, 4, 18, 0)) - """ - make issue with default SLA before working hours - """ + # 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 - """ + # 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 creation = datetime.datetime(2019, 3, 4, 14, 0) issue = make_issue(creation=creation, index=7) diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index b804581298..332bf63580 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -70,12 +70,16 @@ def get_active_service_level_agreement_for(priority, customer=None, service_leve return agreement[0] if agreement else None -@frappe.whitelist() -def get_service_level_agreement_priorities(name): - return [priority.priority for priority in frappe.get_list("Service Level Priority", filters={"parent": name}, fields=["priority"])] +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_valid_service_level_agreements(customer=None): +def get_service_level_agreement_filters(name, customer=None): if not customer: or_filters = [ ["Service Level Agreement", "default_service_level_agreement", "=", 1] @@ -86,12 +90,7 @@ def get_valid_service_level_agreements(customer=None): ["Service Level Agreement", "default_service_level_agreement", "=", 1] ] - return [d.name for d in frappe.get_list("Service Level Agreement", or_filters=or_filters)] - -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") \ No newline at end of file + 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)] + } \ No newline at end of file From 558a5c199f9ff2ac6d6774a4bd5c5e83eafb58e6 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 24 Jun 2019 17:28:47 +0530 Subject: [PATCH 63/92] fix(price list): change the field name --- erpnext/manufacturing/doctype/bom/test_bom.py | 2 +- erpnext/stock/doctype/price_list/price_list.json | 16 +++++++++++++--- .../doctype/price_list/test_price_list_uom.js | 2 +- erpnext/stock/get_item_details.py | 4 ++-- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py index e230e59848..45a7b935d3 100644 --- a/erpnext/manufacturing/doctype/bom/test_bom.py +++ b/erpnext/manufacturing/doctype/bom/test_bom.py @@ -90,7 +90,7 @@ class TestBOM(unittest.TestCase): self.assertEqual(bom.base_total_cost, 486000) 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)): frappe.db.sql("delete from `tabItem Price` where price_list='_Test Price List' and item_code=%s", item_code) diff --git a/erpnext/stock/doctype/price_list/price_list.json b/erpnext/stock/doctype/price_list/price_list.json index 6b447ee883..56340fb05c 100644 --- a/erpnext/stock/doctype/price_list/price_list.json +++ b/erpnext/stock/doctype/price_list/price_list.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 1, @@ -22,6 +23,7 @@ "collapsible": 0, "columns": 0, "default": "1", + "fetch_if_empty": 0, "fieldname": "enabled", "fieldtype": "Check", "hidden": 0, @@ -53,6 +55,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sb_1", "fieldtype": "Section Break", "hidden": 0, @@ -83,6 +86,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "price_list_name", "fieldtype": "Data", "hidden": 0, @@ -116,6 +120,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "currency", "fieldtype": "Link", "hidden": 0, @@ -148,6 +153,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "buying", "fieldtype": "Check", "hidden": 0, @@ -179,6 +185,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "selling", "fieldtype": "Check", "hidden": 0, @@ -210,7 +217,8 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "price_not_uom_dependant", + "fetch_if_empty": 0, + "fieldname": "price_not_uom_dependent", "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, @@ -219,7 +227,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Price Not UOM Dependant", + "label": "Price Not UOM Dependent", "length": 0, "no_copy": 0, "permlevel": 0, @@ -242,6 +250,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_3", "fieldtype": "Column Break", "hidden": 0, @@ -272,6 +281,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "countries", "fieldtype": "Table", "hidden": 0, @@ -310,7 +320,7 @@ "issingle": 0, "istable": 0, "max_attachments": 1, - "modified": "2018-08-29 06:35:16.546274", + "modified": "2019-06-24 17:16:28.027302", "modified_by": "Administrator", "module": "Stock", "name": "Price List", diff --git a/erpnext/stock/doctype/price_list/test_price_list_uom.js b/erpnext/stock/doctype/price_list/test_price_list_uom.js index 526d0da97d..7fbce7d59d 100644 --- a/erpnext/stock/doctype/price_list/test_price_list_uom.js +++ b/erpnext/stock/doctype/price_list/test_price_list_uom.js @@ -7,7 +7,7 @@ QUnit.test("test price list with uom dependancy", function(assert) { () => 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); }, () => cur_frm.save(), diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 6ec5606be7..fe2e0a43f1 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -888,12 +888,12 @@ def get_price_list_currency(price_list): def get_price_list_uom_dependant(price_list): if 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: 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): From 78d6086739b246b27fcdb2cd083f3c1751d65dd5 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 24 Jun 2019 17:52:14 +0530 Subject: [PATCH 64/92] fix: Closed job opening disaplying in job applicant --- erpnext/hr/doctype/job_applicant/job_applicant.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/erpnext/hr/doctype/job_applicant/job_applicant.js b/erpnext/hr/doctype/job_applicant/job_applicant.js index 977702e314..05071e1974 100644 --- a/erpnext/hr/doctype/job_applicant/job_applicant.js +++ b/erpnext/hr/doctype/job_applicant/job_applicant.js @@ -25,5 +25,13 @@ frappe.ui.form.on("Job Applicant", { } } + frm.set_query("job_title", function() { + return { + filters: { + 'status': 'Open' + } + }; + }); + } }); \ No newline at end of file From e8d21cd8fa2210b54b241701ccdedd8b6df9dd79 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 24 Jun 2019 17:46:44 +0530 Subject: [PATCH 65/92] fix: Division by zero error fix in group similar item --- erpnext/controllers/accounts_controller.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 8f8cf4eecb..1b8dd57fa2 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -778,7 +778,12 @@ class AccountsController(TransactionBase): count += 1 item.qty = group_item_qty[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 del group_item_qty[item.item_code] else: From ab13192dd47abaef3685d9fefa6b5e48352c0176 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Mon, 24 Jun 2019 21:22:52 +0530 Subject: [PATCH 66/92] fix: Currency symbol fix for rounded total --- .../purchase_order/purchase_order.json | 3544 ++--------------- 1 file changed, 246 insertions(+), 3298 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index 13a097a0d7..dead1f030c 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -1,4076 +1,1052 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, "allow_import": 1, - "allow_rename": 0, "autoname": "naming_series:", - "beta": 0, "creation": "2013-05-21 16:16:39", - "custom": 0, - "docstatus": 0, "doctype": "DocType", "document_type": "Document", - "editable_grid": 0, + "engine": "InnoDB", + "field_order": [ + "supplier_section", + "title", + "naming_series", + "supplier", + "get_items_from_open_material_requests", + "supplier_name", + "company", + "column_break1", + "transaction_date", + "schedule_date", + "order_confirmation_no", + "order_confirmation_date", + "amended_from", + "drop_ship", + "customer", + "customer_name", + "column_break_19", + "customer_contact_person", + "customer_contact_display", + "customer_contact_mobile", + "customer_contact_email", + "section_addresses", + "supplier_address", + "contact_person", + "address_display", + "contact_display", + "contact_mobile", + "contact_email", + "col_break_address", + "shipping_address", + "shipping_address_display", + "currency_and_price_list", + "currency", + "conversion_rate", + "cb_price_list", + "buying_price_list", + "price_list_currency", + "plc_conversion_rate", + "ignore_pricing_rule", + "sec_warehouse", + "set_warehouse", + "col_break_warehouse", + "is_subcontracted", + "supplier_warehouse", + "items_section", + "scan_barcode", + "items", + "section_break_48", + "pricing_rules", + "raw_material_details", + "supplied_items", + "sb_last_purchase", + "total_qty", + "base_total", + "base_net_total", + "column_break_26", + "total", + "net_total", + "total_net_weight", + "taxes_section", + "taxes_and_charges", + "column_break_50", + "shipping_rule", + "section_break_52", + "taxes", + "sec_tax_breakup", + "other_charges_calculation", + "totals", + "base_taxes_and_charges_added", + "base_taxes_and_charges_deducted", + "base_total_taxes_and_charges", + "column_break_39", + "taxes_and_charges_added", + "taxes_and_charges_deducted", + "total_taxes_and_charges", + "discount_section", + "apply_discount_on", + "base_discount_amount", + "column_break_45", + "additional_discount_percentage", + "discount_amount", + "totals_section", + "base_grand_total", + "base_rounding_adjustment", + "base_in_words", + "base_rounded_total", + "column_break4", + "grand_total", + "rounding_adjustment", + "rounded_total", + "disable_rounded_total", + "in_words", + "advance_paid", + "payment_schedule_section", + "payment_terms_template", + "payment_schedule", + "terms_section_break", + "tc_name", + "terms", + "more_info", + "status", + "ref_sq", + "party_account_currency", + "inter_company_order_reference", + "column_break_74", + "per_received", + "per_billed", + "column_break5", + "letter_head", + "select_print_heading", + "column_break_86", + "group_same_items", + "language", + "subscription_section", + "from_date", + "to_date", + "column_break_97", + "auto_repeat", + "update_auto_repeat_reference" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "supplier_section", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "options": "fa fa-user", - "permlevel": 0, - "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 + "options": "fa fa-user" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "{supplier_name}", - "fetch_if_empty": 0, "fieldname": "title", "fieldtype": "Data", "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Title", - "length": 0, "no_copy": 1, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fetch_if_empty": 0, "fieldname": "naming_series", "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": "Series", - "length": 0, "no_copy": 1, "oldfieldname": "naming_series", "oldfieldtype": "Select", "options": "PUR-ORD-.YYYY.-", - "permlevel": 0, "print_hide": 1, - "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": 1, - "translatable": 0, - "unique": 0 + "set_only_once": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, - "description": "", - "fetch_if_empty": 0, "fieldname": "supplier", "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": 1, "label": "Supplier", - "length": 0, - "no_copy": 0, "oldfieldname": "supplier", "oldfieldtype": "Link", "options": "Supplier", - "permlevel": 0, "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "search_index": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:doc.supplier && doc.docstatus===0 && (!(doc.items && doc.items.length) || (doc.items.length==1 && !doc.items[0].item_code))", - "fetch_if_empty": 0, "fieldname": "get_items_from_open_material_requests", "fieldtype": "Button", - "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": "Get Items from Open Material Requests", - "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 + "label": "Get Items from Open Material Requests" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, "fetch_from": "supplier.supplier_name", - "fetch_if_empty": 0, "fieldname": "supplier_name", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Supplier Name", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fetch_if_empty": 0, "fieldname": "company", "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": 1, "label": "Company", - "length": 0, - "no_copy": 0, "oldfieldname": "company", "oldfieldtype": "Link", "options": "Company", - "permlevel": 0, "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, "remember_last_selected_value": 1, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "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_break1", "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, "oldfieldtype": "Column Break", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, "print_width": "50%", - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, "width": "50%" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "Today", - "fetch_if_empty": 0, "fieldname": "transaction_date", "fieldtype": "Date", - "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": "Date", - "length": 0, - "no_copy": 0, "oldfieldname": "transaction_date", "oldfieldtype": "Date", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "search_index": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fetch_if_empty": 0, "fieldname": "schedule_date", "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Reqd By 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 + "label": "Reqd By Date" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:doc.docstatus===1", - "fetch_if_empty": 0, "fieldname": "order_confirmation_no", "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": "Order Confirmation No", - "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 + "label": "Order Confirmation No" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:doc.order_confirmation_no", - "fetch_if_empty": 0, "fieldname": "order_confirmation_date", "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Order Confirmation 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 + "label": "Order Confirmation Date" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "amended_from", "fieldtype": "Link", - "hidden": 0, "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Amended From", - "length": 0, "no_copy": 1, "oldfieldname": "amended_from", "oldfieldtype": "Data", "options": "Purchase Order", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "collapsible_depends_on": "", - "columns": 0, - "fetch_if_empty": 0, "fieldname": "drop_ship", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Drop Ship", - "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 + "label": "Drop Ship" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "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": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, "fieldname": "customer_name", "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": "Customer Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "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_19", - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, "fieldname": "customer_contact_person", "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 Contact", - "length": 0, - "no_copy": 0, - "options": "Contact", - "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 + "options": "Contact" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "customer_contact_display", "fieldtype": "Small Text", "hidden": 1, - "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 Contact", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "customer_contact_mobile", "fieldtype": "Small Text", "hidden": 1, - "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 Mobile No", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "customer_contact_email", "fieldtype": "Code", "hidden": 1, - "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 Contact Email", - "length": 0, - "no_copy": 0, "options": "Email", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, "collapsible": 1, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "section_addresses", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Address and Contact", - "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 + "label": "Address and Contact" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "supplier_address", "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": "Select Supplier Address", - "length": 0, - "no_copy": 0, "options": "Address", - "permlevel": 0, - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "contact_person", "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": "Contact Person", - "length": 0, - "no_copy": 0, "options": "Contact", - "permlevel": 0, - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, "fieldname": "address_display", "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": "Address", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "contact_display", "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Contact", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "contact_mobile", "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": "Mobile No", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "contact_email", "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": "Contact Email", - "length": 0, - "no_copy": 0, - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "col_break_address", - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, "fieldname": "shipping_address", "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": "Select Shipping Address", - "length": 0, - "no_copy": 0, "options": "Address", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "shipping_address_display", "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": "Shipping Address", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, "collapsible": 1, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "currency_and_price_list", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Currency and Price List", - "length": 0, - "no_copy": 0, - "options": "fa fa-tag", - "permlevel": 0, - "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 + "options": "fa fa-tag" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "currency", "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": "Currency", - "length": 0, - "no_copy": 0, "oldfieldname": "currency", "oldfieldtype": "Select", "options": "Currency", - "permlevel": 0, "print_hide": 1, - "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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fetch_if_empty": 0, "fieldname": "conversion_rate", "fieldtype": "Float", - "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": "Exchange Rate", - "length": 0, - "no_copy": 0, "oldfieldname": "conversion_rate", "oldfieldtype": "Currency", - "permlevel": 0, "precision": "9", "print_hide": 1, - "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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "cb_price_list", - "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, - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "buying_price_list", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Price List", - "length": 0, - "no_copy": 0, "options": "Price List", - "permlevel": 0, - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "price_list_currency", "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": "Price List Currency", - "length": 0, - "no_copy": 0, "options": "Currency", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "plc_conversion_rate", "fieldtype": "Float", - "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": "Price List Exchange Rate", - "length": 0, - "no_copy": 0, - "permlevel": 0, "precision": "9", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, + "default": "0", "fieldname": "ignore_pricing_rule", "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Ignore Pricing Rule", - "length": 0, "no_copy": 1, "permlevel": 1, - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "sec_warehouse", - "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 + "fieldtype": "Section Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "set_warehouse", "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": "Set Target Warehouse", - "length": 0, - "no_copy": 0, "options": "Warehouse", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "col_break_warehouse", - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "No", - "fetch_if_empty": 0, "fieldname": "is_subcontracted", "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": 1, "label": "Supply Raw Materials", - "length": 0, - "no_copy": 0, "options": "No\nYes", - "permlevel": 0, - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:doc.is_subcontracted==\"Yes\"", - "fetch_if_empty": 0, "fieldname": "supplier_warehouse", "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": "Supplier Warehouse", - "length": 0, - "no_copy": 0, - "options": "Warehouse", - "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 + "options": "Warehouse" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "items_section", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, "oldfieldtype": "Section Break", - "options": "fa fa-shopping-cart", - "permlevel": 0, - "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 + "options": "fa fa-shopping-cart" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "scan_barcode", "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": "Scan Barcode", - "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 + "label": "Scan Barcode" }, { "allow_bulk_edit": 1, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "items", "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": "Items", - "length": 0, - "no_copy": 0, "oldfieldname": "po_details", "oldfieldtype": "Table", "options": "Purchase Order Item", - "permlevel": 0, - "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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, "collapsible": 1, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "section_break_48", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Pricing Rules", - "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 + "label": "Pricing Rules" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "collapsible_depends_on": "", - "columns": 0, - "fetch_if_empty": 0, "fieldname": "pricing_rules", "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": "Purchase Order Pricing Rule", - "length": 0, - "no_copy": 0, "options": "Pricing Rule Detail", - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, "collapsible_depends_on": "supplied_items", - "columns": 0, - "fetch_if_empty": 0, "fieldname": "raw_material_details", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Raw Materials Supplied", - "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 + "label": "Raw Materials Supplied" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, "fieldname": "supplied_items", "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": "Supplied Items", - "length": 0, - "no_copy": 0, "oldfieldname": "po_raw_material_details", "oldfieldtype": "Table", "options": "Purchase Order Item Supplied", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "sb_last_purchase", - "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, - "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 + "fieldtype": "Section Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "total_qty", "fieldtype": "Float", - "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": "Total Quantity", - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "base_total", "fieldtype": "Currency", - "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": "Total (Company Currency)", - "length": 0, - "no_copy": 0, "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "base_net_total", "fieldtype": "Currency", - "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": "Net Total (Company Currency)", - "length": 0, "no_copy": 1, "oldfieldname": "net_total", "oldfieldtype": "Currency", "options": "Company:company:default_currency", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "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_26", - "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, - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "total", "fieldtype": "Currency", - "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": "Total", - "length": 0, - "no_copy": 0, "options": "currency", - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "net_total", "fieldtype": "Currency", - "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": "Net Total", - "length": 0, - "no_copy": 0, "oldfieldname": "net_total_import", "oldfieldtype": "Currency", "options": "currency", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "total_net_weight", "fieldtype": "Float", - "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": "Total Net Weight", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "taxes_section", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, "oldfieldtype": "Section Break", - "options": "fa fa-money", - "permlevel": 0, - "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 + "options": "fa fa-money" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fetch_if_empty": 0, "fieldname": "taxes_and_charges", "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": "Taxes and Charges", - "length": 0, - "no_copy": 0, "oldfieldname": "purchase_other_charges", "oldfieldtype": "Link", "options": "Purchase Taxes and Charges Template", - "permlevel": 0, - "print_hide": 1, - "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 + "print_hide": 1 }, { - "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_50", - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "shipping_rule", "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": "Shipping Rule", - "length": 0, - "no_copy": 0, "options": "Shipping Rule", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "section_break_52", - "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 + "fieldtype": "Section Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "taxes", "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": "Purchase Taxes and Charges", - "length": 0, - "no_copy": 0, "oldfieldname": "purchase_tax_details", "oldfieldtype": "Table", - "options": "Purchase Taxes and Charges", - "permlevel": 0, - "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 + "options": "Purchase Taxes and Charges" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, "collapsible": 1, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "sec_tax_breakup", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Tax Breakup", - "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 + "label": "Tax Breakup" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "other_charges_calculation", "fieldtype": "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": "Taxes and Charges Calculation", - "length": 0, "no_copy": 1, "oldfieldtype": "HTML", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "totals", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, "oldfieldtype": "Section Break", - "options": "fa fa-money", - "permlevel": 0, - "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 + "options": "fa fa-money" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "base_taxes_and_charges_added", "fieldtype": "Currency", - "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": "Taxes and Charges Added (Company Currency)", - "length": 0, - "no_copy": 0, "oldfieldname": "other_charges_added", "oldfieldtype": "Currency", "options": "Company:company:default_currency", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "base_taxes_and_charges_deducted", "fieldtype": "Currency", - "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": "Taxes and Charges Deducted (Company Currency)", - "length": 0, - "no_copy": 0, "oldfieldname": "other_charges_deducted", "oldfieldtype": "Currency", "options": "Company:company:default_currency", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "base_total_taxes_and_charges", "fieldtype": "Currency", - "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": "Total Taxes and Charges (Company Currency)", - "length": 0, "no_copy": 1, "oldfieldname": "total_tax", "oldfieldtype": "Currency", "options": "Company:company:default_currency", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "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_39", - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "taxes_and_charges_added", "fieldtype": "Currency", - "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": "Taxes and Charges Added", - "length": 0, - "no_copy": 0, "oldfieldname": "other_charges_added_import", "oldfieldtype": "Currency", "options": "currency", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "taxes_and_charges_deducted", "fieldtype": "Currency", - "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": "Taxes and Charges Deducted", - "length": 0, - "no_copy": 0, "oldfieldname": "other_charges_deducted_import", "oldfieldtype": "Currency", "options": "currency", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "total_taxes_and_charges", "fieldtype": "Currency", - "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": "Total Taxes and Charges", - "length": 0, - "no_copy": 0, "options": "currency", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, "collapsible": 1, "collapsible_depends_on": "discount_amount", - "columns": 0, - "fetch_if_empty": 0, "fieldname": "discount_section", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Additional Discount", - "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 + "label": "Additional Discount" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "Grand Total", - "fetch_if_empty": 0, "fieldname": "apply_discount_on", "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": "Apply Additional Discount On", - "length": 0, - "no_copy": 0, "options": "\nGrand Total\nNet Total", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "base_discount_amount", "fieldtype": "Currency", - "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": "Additional Discount Amount (Company Currency)", - "length": 0, - "no_copy": 0, "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "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_45", - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "additional_discount_percentage", "fieldtype": "Float", - "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": "Additional Discount Percentage", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "discount_amount", "fieldtype": "Currency", - "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": "Additional Discount Amount", - "length": 0, - "no_copy": 0, "options": "currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "totals_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "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 + "fieldtype": "Section Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "base_grand_total", "fieldtype": "Currency", - "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": "Grand Total (Company Currency)", - "length": 0, "no_copy": 1, "oldfieldname": "grand_total", "oldfieldtype": "Currency", "options": "Company:company:default_currency", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "base_rounding_adjustment", "fieldtype": "Currency", - "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": "Rounding Adjustment (Company Currency)", - "length": 0, "no_copy": 1, "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "description": "In Words will be visible once you save the Purchase Order.", - "fetch_if_empty": 0, "fieldname": "base_in_words", "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": "In Words (Company Currency)", - "length": 0, - "no_copy": 0, "oldfieldname": "in_words", "oldfieldtype": "Data", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "base_rounded_total", "fieldtype": "Currency", - "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": "Rounded Total (Company Currency)", - "length": 0, - "no_copy": 0, "oldfieldname": "rounded_total", "oldfieldtype": "Currency", "options": "Company:company:default_currency", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "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_break4", "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, - "oldfieldtype": "Column Break", - "permlevel": 0, - "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 + "oldfieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "grand_total", "fieldtype": "Currency", - "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": "Grand Total", - "length": 0, - "no_copy": 0, "oldfieldname": "grand_total_import", "oldfieldtype": "Currency", "options": "currency", - "permlevel": 0, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "rounding_adjustment", "fieldtype": "Currency", - "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": "Rounding Adjustment", - "length": 0, "no_copy": 1, "options": "currency", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "rounded_total", "fieldtype": "Currency", - "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": "Rounded Total", - "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 + "options": "currency", + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, + "default": "0", "fieldname": "disable_rounded_total", "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Disable Rounded Total", - "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 + "label": "Disable Rounded Total" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "in_words", "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": "In Words", - "length": 0, - "no_copy": 0, "oldfieldname": "in_words_import", "oldfieldtype": "Data", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "advance_paid", "fieldtype": "Currency", - "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": "Advance Paid", - "length": 0, "no_copy": 1, "options": "party_account_currency", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "payment_schedule_section", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Terms", - "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 + "label": "Payment Terms" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "payment_terms_template", "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": "Payment Terms Template", - "length": 0, - "no_copy": 0, - "options": "Payment Terms Template", - "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 + "options": "Payment Terms Template" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "payment_schedule", "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": "Payment Schedule", - "length": 0, "no_copy": 1, "options": "Payment Schedule", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, "collapsible": 1, "collapsible_depends_on": "terms", - "columns": 0, - "fetch_if_empty": 0, "fieldname": "terms_section_break", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Terms and Conditions", - "length": 0, - "no_copy": 0, "oldfieldtype": "Section Break", - "options": "fa fa-legal", - "permlevel": 0, - "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 + "options": "fa fa-legal" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "tc_name", "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": "Terms", - "length": 0, - "no_copy": 0, "oldfieldname": "tc_name", "oldfieldtype": "Link", "options": "Terms and Conditions", - "permlevel": 0, - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "terms", "fieldtype": "Text Editor", - "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": "Terms and Conditions", - "length": 0, - "no_copy": 0, "oldfieldname": "terms", - "oldfieldtype": "Text Editor", - "permlevel": 0, - "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 + "oldfieldtype": "Text Editor" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, "collapsible": 1, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "more_info", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "More Information", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "permlevel": 0, - "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 + "oldfieldtype": "Section Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "Draft", - "fetch_if_empty": 0, "fieldname": "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": 1, "label": "Status", - "length": 0, "no_copy": 1, "oldfieldname": "status", "oldfieldtype": "Select", "options": "\nDraft\nOn Hold\nTo Receive and Bill\nTo Bill\nTo Receive\nCompleted\nCancelled\nClosed\nDelivered", - "permlevel": 0, "print_hide": 1, - "print_hide_if_no_value": 0, "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "search_index": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "ref_sq", "fieldtype": "Data", "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Ref SQ", - "length": 0, "no_copy": 1, "oldfieldname": "ref_sq", "oldfieldtype": "Data", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "party_account_currency", "fieldtype": "Link", "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Party Account Currency", - "length": 0, "no_copy": 1, "options": "Currency", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "inter_company_order_reference", "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": "Inter Company Order Reference", - "length": 0, - "no_copy": 0, - "options": "Sales Order", - "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 + "options": "Sales Order" }, { - "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_74", - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:!doc.__islocal", - "description": "", - "fetch_if_empty": 0, "fieldname": "per_received", "fieldtype": "Percent", - "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": "% Received", - "length": 0, "no_copy": 1, "oldfieldname": "per_received", "oldfieldtype": "Currency", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:!doc.__islocal", - "description": "", - "fetch_if_empty": 0, "fieldname": "per_billed", "fieldtype": "Percent", - "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": "% Billed", - "length": 0, "no_copy": 1, "oldfieldname": "per_billed", "oldfieldtype": "Currency", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, "collapsible": 1, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "column_break5", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Printing Settings", - "length": 0, - "no_copy": 0, "oldfieldtype": "Column Break", - "permlevel": 0, "print_hide": 1, - "print_hide_if_no_value": 0, "print_width": "50%", - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, "width": "50%" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "letter_head", "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": "Letter Head", - "length": 0, - "no_copy": 0, "oldfieldname": "letter_head", "oldfieldtype": "Select", "options": "Letter Head", - "permlevel": 0, - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "select_print_heading", "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": "Print Heading", - "length": 0, "no_copy": 1, "oldfieldname": "select_print_heading", "oldfieldtype": "Link", "options": "Print Heading", - "permlevel": 0, "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "report_hide": 1 }, { - "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_86", - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fetch_if_empty": 0, + "default": "0", "fieldname": "group_same_items", "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Group same items", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fetch_if_empty": 0, "fieldname": "language", "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": "Print Language", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "subscription_section", "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Subscription Section", - "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 + "label": "Subscription Section" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "description": "", - "fetch_if_empty": 0, "fieldname": "from_date", "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "From Date", - "length": 0, "no_copy": 1, - "permlevel": 0, - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "description": "", - "fetch_if_empty": 0, "fieldname": "to_date", "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "To Date", - "length": 0, "no_copy": 1, - "permlevel": 0, - "print_hide": 1, - "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 + "print_hide": 1 }, { - "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_97", - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "auto_repeat", "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": "Auto Repeat", - "length": 0, "no_copy": 1, "options": "Auto Repeat", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval: doc.auto_repeat", - "fetch_if_empty": 0, "fieldname": "update_auto_repeat_reference", "fieldtype": "Button", - "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": "Update Auto Repeat Reference", - "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 + "label": "Update Auto Repeat Reference" } ], - "has_web_view": 0, - "hide_toolbar": 0, "icon": "fa fa-file-text", "idx": 105, - "in_create": 0, "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-04-18 19:43:17.239390", + "modified": "2019-06-24 21:22:05.483429", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order", "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 0, "read": 1, "report": 1, - "role": "Stock User", - "set_user_permissions": 0, - "share": 0, - "submit": 0, - "write": 0 + "role": "Stock User" }, { "amend": 1, @@ -4078,15 +1054,10 @@ "create": 1, "delete": 1, "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "Purchase Manager", - "set_user_permissions": 0, "share": 1, "submit": 1, "write": 1 @@ -4097,48 +1068,25 @@ "create": 1, "delete": 1, "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "Purchase User", - "set_user_permissions": 0, "share": 1, "submit": 1, "write": 1 }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, "permlevel": 1, - "print": 0, "read": 1, - "report": 0, "role": "Purchase Manager", - "set_user_permissions": 0, - "share": 0, - "submit": 0, "write": 1 } ], - "quick_entry": 0, - "read_only": 0, "search_fields": "status, transaction_date, supplier,grand_total", "show_name_in_global_search": 1, "sort_field": "modified", "sort_order": "DESC", "timeline_field": "supplier", - "title_field": "title", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 + "title_field": "title" } \ No newline at end of file From a64e4037d29411e10278ee910675549b53b8b4d1 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 25 Jun 2019 07:08:59 +0530 Subject: [PATCH 67/92] fix: revert changes of bom recursion --- erpnext/manufacturing/doctype/bom/bom.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 4a3c121d65..75eb794386 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -383,10 +383,7 @@ class BOM(WebsiteGenerator): def check_recursion(self, bom_list=[]): """ Check whether recursion occurs in any bom""" - - if not bom_list: - bom_list = self.traverse_tree() - + bom_list = self.traverse_tree() bom_nos = frappe.get_all('BOM Item', fields=["bom_no"], filters={'parent': ('in', bom_list), 'parenttype': 'BOM'}) @@ -402,7 +399,7 @@ class BOM(WebsiteGenerator): raise_exception = True 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=[]): bom_list = self.traverse_tree(bom_list) @@ -415,8 +412,8 @@ class BOM(WebsiteGenerator): def traverse_tree(self, bom_list=None): def _get_children(bom_no): - return [cstr(d[0]) for d in frappe.db.sql("""select bom_no from `tabBOM Item` - where parent = %s and ifnull(bom_no, '') != '' and parenttype='BOM'""", bom_no)] + return frappe.db.sql_list("""select bom_no from `tabBOM Item` + where parent = %s and ifnull(bom_no, '') != '' and parenttype='BOM'""", bom_no) count = 0 if not bom_list: From 99d46844d51e056170a510e4bb591852a3f102be Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 25 Jun 2019 16:25:51 +0530 Subject: [PATCH 68/92] fix: minor patch fix --- erpnext/patches/v12_0/set_priority_for_support.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index e41b8b1bfc..fde4da3e65 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -12,7 +12,7 @@ def execute(): 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 not frappe.db.exists("Issue Priority", priority): + if priority and not frappe.db.exists("Issue Priority", priority): frappe.get_doc({ "doctype": "Issue Priority", "name": priority From 10562b67fc4c90fc4b7d579220dda17d0e3fcb3b Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Tue, 25 Jun 2019 17:07:41 +0530 Subject: [PATCH 69/92] fix(sales-funnel): Use frappe.Chart() instead of Chart() --- erpnext/selling/page/sales_funnel/sales_funnel.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/page/sales_funnel/sales_funnel.js b/erpnext/selling/page/sales_funnel/sales_funnel.js index f2e972adf8..6a98da8a5d 100644 --- a/erpnext/selling/page/sales_funnel/sales_funnel.js +++ b/erpnext/selling/page/sales_funnel/sales_funnel.js @@ -277,7 +277,7 @@ erpnext.SalesFunnel = class SalesFunnel { let chart_data = me.options.data ? me.options.data : null; const parent = me.elements.funnel_wrapper[0]; - this.chart = new Chart(parent, { + this.chart = new frappe.Chart(parent, { title: __("Sales Opportunities by Source"), height: 400, data: chart_data, @@ -298,7 +298,7 @@ erpnext.SalesFunnel = class SalesFunnel { let chart_data = me.options.data ? me.options.data : null; const parent = me.elements.funnel_wrapper[0]; - this.chart = new Chart(parent, { + this.chart = new frappe.Chart(parent, { title: __("Sales Pipeline by Stage"), height: 400, data: chart_data, From 2caaa1b03dffe85299389d3ee59fb7300f385647 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Tue, 25 Jun 2019 17:17:38 +0530 Subject: [PATCH 70/92] fix(sales-funnel): Remove duplicate code --- .../selling/page/sales_funnel/sales_funnel.js | 112 +++++------------- 1 file changed, 27 insertions(+), 85 deletions(-) diff --git a/erpnext/selling/page/sales_funnel/sales_funnel.js b/erpnext/selling/page/sales_funnel/sales_funnel.js index 6a98da8a5d..85c0cd8bf0 100644 --- a/erpnext/selling/page/sales_funnel/sales_funnel.js +++ b/erpnext/selling/page/sales_funnel/sales_funnel.js @@ -90,70 +90,31 @@ erpnext.SalesFunnel = class SalesFunnel { get_data(btn) { var me = this; - if (me.options.chart == 'sales_funnel'){ - frappe.call({ - method: "erpnext.selling.page.sales_funnel.sales_funnel.get_funnel_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_funnel(); - } + const method_map = { + "sales_funnel": "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", + "sales_pipeline": "erpnext.selling.page.sales_funnel.sales_funnel.get_pipeline_data" + }; + frappe.call({ + method: method_map[this.options.chart], + 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(); } } - }); - } 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() { @@ -161,9 +122,9 @@ erpnext.SalesFunnel = class SalesFunnel { if (me.options.chart == 'sales_funnel'){ me.render_funnel(); } 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'){ - me.render_pipeline(); + me.render_chart("Sales Pipeline by Stage"); } } @@ -270,7 +231,7 @@ erpnext.SalesFunnel = class SalesFunnel { context.fillText(__(title), width + 20, y_mid); } - render_opp_by_lead_source() { + render_chart(title) { let me = this; let currency = frappe.defaults.get_default("currency"); @@ -278,7 +239,7 @@ erpnext.SalesFunnel = class SalesFunnel { const parent = me.elements.funnel_wrapper[0]; this.chart = new frappe.Chart(parent, { - title: __("Sales Opportunities by Source"), + title: title, height: 400, data: chart_data, 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 frappe.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'] - }); - } }; From 9479f7f1ef1a7eaf054120627848286326f3e458 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 26 Jun 2019 10:37:00 +0530 Subject: [PATCH 71/92] fix: print message for insufficient stock --- erpnext/stock/doctype/stock_entry/stock_entry.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index ceb620709c..464101e672 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -376,10 +376,10 @@ class StockEntry(StockController): # 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")): - 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), format_time(self.posting_time), frappe.bold(d.item_code)) - + '

' + _("Available qty is {0}, you need {1}").format(frappe.bold(d.actual_qty), + + '

' + _("Available quantity is {0}, you need {1}").format(frappe.bold(d.actual_qty), frappe.bold(d.transfer_qty)), NegativeStockError, title=_('Insufficient Stock')) From 40d25f4010e632d20841f072ab0fd69c4473c3c8 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 26 Jun 2019 10:57:45 +0530 Subject: [PATCH 72/92] fix: Show close button if per_ordered is less than 99.999999 (#18067) --- erpnext/accounts/report/non_billed_report.py | 3 ++- erpnext/buying/doctype/purchase_order/purchase_order.js | 2 +- erpnext/selling/doctype/sales_order/sales_order.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/report/non_billed_report.py b/erpnext/accounts/report/non_billed_report.py index c238606443..a9e25bc25b 100644 --- a/erpnext/accounts/report/non_billed_report.py +++ b/erpnext/accounts/report/non_billed_report.py @@ -25,7 +25,8 @@ def get_ordered_to_be_billed_data(args): from `{parent_tab}`, `{child_tab}` 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 * ifnull(`{parent_tab}`.conversion_rate, 1), {precision}) < `{child_tab}`.base_amount order by diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index 1134b0479e..b2a2f01f44 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -107,7 +107,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend( if(doc.docstatus == 1) { if(!in_list(["Closed", "Delivered"], doc.status)) { 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") { this.frm.add_custom_button(__('Hold'), () => this.hold_purchase_order(), __("Status")); } else{ diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 1ded58da24..38b7b566aa 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -34,7 +34,7 @@ frappe.ui.form.on("Sales Order", { }, refresh: function(frm) { 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'), () => { erpnext.utils.update_child_items({ frm: frm, From 07aae76bbf4c0a1c3f61fc6aa317eb9108309fb7 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 26 Jun 2019 11:03:57 +0530 Subject: [PATCH 73/92] fix: change the department to tree view (#18057) --- erpnext/hooks.py | 2 +- erpnext/hr/doctype/department/department.js | 2 +- erpnext/hr/doctype/department/department.json | 19 +++++++++++++++++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index bd64023dc9..1d1dc62712 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -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_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 update_website_context = ["erpnext.shopping_cart.utils.update_website_context", "erpnext.education.doctype.education_settings.education_settings.update_website_context"] diff --git a/erpnext/hr/doctype/department/department.js b/erpnext/hr/doctype/department/department.js index 76bc932144..963f3615cc 100644 --- a/erpnext/hr/doctype/department/department.js +++ b/erpnext/hr/doctype/department/department.js @@ -4,7 +4,7 @@ frappe.ui.form.on('Department', { refresh: function(frm) { // read-only for root department - if(!frm.doc.parent_department) { + if(!frm.doc.parent_department && !frm.is_new()) { frm.set_read_only(); frm.set_intro(__("This is a root department and cannot be edited.")); } diff --git a/erpnext/hr/doctype/department/department.json b/erpnext/hr/doctype/department/department.json index aed7f42faf..3b400ce8d7 100644 --- a/erpnext/hr/doctype/department/department.json +++ b/erpnext/hr/doctype/department/department.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 1, @@ -19,6 +20,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "department_name", "fieldtype": "Data", "hidden": 0, @@ -52,6 +54,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "parent_department", "fieldtype": "Link", "hidden": 0, @@ -85,6 +88,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company", "fieldtype": "Link", "hidden": 0, @@ -118,6 +122,7 @@ "bold": 1, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "is_group", "fieldtype": "Check", "hidden": 0, @@ -150,6 +155,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "disabled", "fieldtype": "Check", "hidden": 0, @@ -182,6 +188,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_4", "fieldtype": "Section Break", "hidden": 0, @@ -214,6 +221,7 @@ "collapsible": 0, "columns": 0, "description": "Days for which Holidays are blocked for this department.", + "fetch_if_empty": 0, "fieldname": "leave_block_list", "fieldtype": "Link", "hidden": 0, @@ -246,6 +254,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "leave_section", "fieldtype": "Section Break", "hidden": 0, @@ -279,6 +288,7 @@ "collapsible": 0, "columns": 0, "description": "The first Leave Approver in the list will be set as the default Leave Approver.", + "fetch_if_empty": 0, "fieldname": "leave_approvers", "fieldtype": "Table", "hidden": 0, @@ -312,6 +322,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "expense_section", "fieldtype": "Section Break", "hidden": 0, @@ -345,6 +356,7 @@ "collapsible": 0, "columns": 0, "description": "The first Expense Approver in the list will be set as the default Expense Approver.", + "fetch_if_empty": 0, "fieldname": "expense_approvers", "fieldtype": "Table", "hidden": 0, @@ -378,6 +390,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "lft", "fieldtype": "Int", "hidden": 1, @@ -410,6 +423,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "rgt", "fieldtype": "Int", "hidden": 1, @@ -442,6 +456,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "old_parent", "fieldtype": "Data", "hidden": 1, @@ -479,7 +494,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-08-29 06:26:12.995703", + "modified": "2019-06-25 18:43:05.550387", "modified_by": "Administrator", "module": "HR", "name": "Department", @@ -543,7 +558,7 @@ "write": 1 } ], - "quick_entry": 1, + "quick_entry": 0, "read_only": 0, "read_only_onload": 0, "show_name_in_global_search": 1, From ea0574679f47355ae9a74d70601b5b219fa31bc6 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Wed, 26 Jun 2019 11:05:51 +0530 Subject: [PATCH 74/92] fix: Removed submitted status from Quotation (#18055) * fix: Change in list view and status updater * fix: Change status in doctype * fix: Patch for submitted status --- erpnext/controllers/status_updater.py | 2 +- erpnext/patches.txt | 3 +- erpnext/patches/v12_0/set_quotation_status.py | 7 + .../selling/doctype/quotation/quotation.json | 4230 ++++------------- .../doctype/quotation/quotation_list.js | 4 +- 5 files changed, 904 insertions(+), 3342 deletions(-) create mode 100644 erpnext/patches/v12_0/set_quotation_status.py diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index c52c0a6d75..42e0a43e6e 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -27,7 +27,7 @@ status_map = { ], "Quotation": [ ["Draft", None], - ["Submitted", "eval:self.docstatus==1"], + ["Open", "eval:self.docstatus==1"], ["Lost", "eval:self.status=='Lost'"], ["Ordered", "has_sales_order"], ["Cancelled", "eval:self.docstatus==2"], diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 747177a3a7..9c1f3eaf72 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -604,4 +604,5 @@ execute:frappe.delete_doc("Report", "Inactive Items") erpnext.patches.v11_1.delete_scheduling_tool erpnext.patches.v12_0.make_custom_fields_for_bank_remittance #14-06-2019 execute:frappe.delete_doc_if_exists("Page", "support-analytics") -erpnext.patches.v12_0.make_item_manufacturer \ No newline at end of file +erpnext.patches.v12_0.make_item_manufacturer +erpnext.patches.v12_0.set_quotation_status \ No newline at end of file diff --git a/erpnext/patches/v12_0/set_quotation_status.py b/erpnext/patches/v12_0/set_quotation_status.py new file mode 100644 index 0000000000..64a9080a8f --- /dev/null +++ b/erpnext/patches/v12_0/set_quotation_status.py @@ -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' """) \ No newline at end of file diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json index 7332eba92b..ef5abdb67f 100644 --- a/erpnext/selling/doctype/quotation/quotation.json +++ b/erpnext/selling/doctype/quotation/quotation.json @@ -1,3474 +1,1028 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 0, - "autoname": "naming_series:", - "beta": 0, - "creation": "2013-05-24 19:29:08", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Document", - "editable_grid": 1, + "allow_import": 1, + "autoname": "naming_series:", + "creation": "2013-05-24 19:29:08", + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "customer_section", + "title", + "naming_series", + "quotation_to", + "customer", + "lead", + "customer_name", + "column_break1", + "amended_from", + "company", + "transaction_date", + "valid_till", + "order_type", + "contact_section", + "customer_address", + "address_display", + "contact_person", + "contact_display", + "contact_mobile", + "contact_email", + "col_break98", + "shipping_address_name", + "shipping_address", + "customer_group", + "territory", + "currency_and_price_list", + "currency", + "conversion_rate", + "column_break2", + "selling_price_list", + "price_list_currency", + "plc_conversion_rate", + "ignore_pricing_rule", + "items_section", + "items", + "pricing_rule_details", + "pricing_rules", + "sec_break23", + "total_qty", + "base_total", + "base_net_total", + "column_break_28", + "total", + "net_total", + "total_net_weight", + "taxes_section", + "tax_category", + "column_break_34", + "shipping_rule", + "section_break_36", + "taxes_and_charges", + "taxes", + "sec_tax_breakup", + "other_charges_calculation", + "section_break_39", + "base_total_taxes_and_charges", + "column_break_42", + "total_taxes_and_charges", + "section_break_44", + "apply_discount_on", + "base_discount_amount", + "column_break_46", + "additional_discount_percentage", + "discount_amount", + "totals", + "base_grand_total", + "base_rounding_adjustment", + "base_in_words", + "base_rounded_total", + "column_break3", + "grand_total", + "rounding_adjustment", + "rounded_total", + "in_words", + "payment_schedule_section", + "payment_terms_template", + "payment_schedule", + "terms_section_break", + "tc_name", + "terms", + "print_settings", + "letter_head", + "group_same_items", + "column_break_73", + "select_print_heading", + "language", + "subscription_section", + "auto_repeat", + "update_auto_repeat_reference", + "more_info", + "campaign", + "source", + "order_lost_reason", + "column_break4", + "status", + "enq_det", + "supplier_quotation", + "opportunity", + "lost_reasons" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "customer_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "options": "fa fa-user", - "permlevel": 0, - "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 - }, + "fieldname": "customer_section", + "fieldtype": "Section Break", + "options": "fa fa-user" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "{customer_name}", - "fieldname": "title", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Title", - "length": 0, - "no_copy": 1, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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_on_submit": 1, + "default": "{customer_name}", + "fieldname": "title", + "fieldtype": "Data", + "hidden": 1, + "label": "Title", + "no_copy": 1, + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fieldname": "naming_series", - "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": "Series", - "length": 0, - "no_copy": 1, - "oldfieldname": "naming_series", - "oldfieldtype": "Select", - "options": "SAL-QTN-.YYYY.-", - "permlevel": 0, - "print_hide": 1, - "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": 1, - "translatable": 0, - "unique": 0 - }, + "fieldname": "naming_series", + "fieldtype": "Select", + "label": "Series", + "no_copy": 1, + "oldfieldname": "naming_series", + "oldfieldtype": "Select", + "options": "SAL-QTN-.YYYY.-", + "print_hide": 1, + "reqd": 1, + "set_only_once": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Customer", - "fieldname": "quotation_to", - "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": "Quotation To", - "length": 0, - "no_copy": 0, - "oldfieldname": "quotation_to", - "oldfieldtype": "Select", - "options": "\nLead\nCustomer", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "default": "Customer", + "fieldname": "quotation_to", + "fieldtype": "Select", + "label": "Quotation To", + "oldfieldname": "quotation_to", + "oldfieldtype": "Select", + "options": "\nLead\nCustomer", + "print_hide": 1, + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.quotation_to == \"Customer\"", - "fieldname": "customer", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "Customer", - "length": 0, - "no_copy": 0, - "oldfieldname": "customer", - "oldfieldtype": "Link", - "options": "Customer", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "bold": 1, + "depends_on": "eval:doc.quotation_to == \"Customer\"", + "fieldname": "customer", + "fieldtype": "Link", + "in_global_search": 1, + "in_standard_filter": 1, + "label": "Customer", + "oldfieldname": "customer", + "oldfieldtype": "Link", + "options": "Customer", + "print_hide": 1, + "search_index": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.quotation_to == \"Lead\"", - "fieldname": "lead", - "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": 1, - "label": "Lead", - "length": 0, - "no_copy": 0, - "oldfieldname": "lead", - "oldfieldtype": "Link", - "options": "Lead", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "bold": 1, + "depends_on": "eval:doc.quotation_to == \"Lead\"", + "fieldname": "lead", + "fieldtype": "Link", + "in_standard_filter": 1, + "label": "Lead", + "oldfieldname": "lead", + "oldfieldtype": "Link", + "options": "Lead", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "fetch_from": "customer.customer_name", - "fieldname": "customer_name", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Customer Name", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "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 - }, + "bold": 1, + "fetch_from": "customer.customer_name", + "fieldname": "customer_name", + "fieldtype": "Data", + "hidden": 1, + "in_global_search": 1, + "label": "Customer Name", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break1", - "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, - "oldfieldtype": "Column Break", - "permlevel": 0, - "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, + "fieldname": "column_break1", + "fieldtype": "Column Break", + "oldfieldtype": "Column Break", "width": "50%" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amended_from", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Amended From", - "length": 0, - "no_copy": 1, - "oldfieldname": "amended_from", - "oldfieldtype": "Data", - "options": "Quotation", - "permlevel": 0, - "print_hide": 1, - "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, + "fieldname": "amended_from", + "fieldtype": "Link", + "ignore_user_permissions": 1, + "label": "Amended From", + "no_copy": 1, + "oldfieldname": "amended_from", + "oldfieldtype": "Data", + "options": "Quotation", + "print_hide": 1, + "read_only": 1, "width": "150px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "company", - "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": "Company", - "length": 0, - "no_copy": 0, - "oldfieldname": "company", - "oldfieldtype": "Link", - "options": "Company", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 1, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0, + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "oldfieldname": "company", + "oldfieldtype": "Link", + "options": "Company", + "print_hide": 1, + "remember_last_selected_value": 1, + "reqd": 1, "width": "150px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Today", - "fieldname": "transaction_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Date", - "length": 0, - "no_copy": 1, - "oldfieldname": "transaction_date", - "oldfieldtype": "Date", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0, + "default": "Today", + "fieldname": "transaction_date", + "fieldtype": "Date", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Date", + "no_copy": 1, + "oldfieldname": "transaction_date", + "oldfieldtype": "Date", + "reqd": 1, + "search_index": 1, "width": "100px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "valid_till", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Valid Till", - "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 - }, + "fieldname": "valid_till", + "fieldtype": "Date", + "label": "Valid Till" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Sales", - "fieldname": "order_type", - "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": 1, - "label": "Order Type", - "length": 0, - "no_copy": 0, - "oldfieldname": "order_type", - "oldfieldtype": "Select", - "options": "\nSales\nMaintenance\nShopping Cart", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "default": "Sales", + "fieldname": "order_type", + "fieldtype": "Select", + "in_standard_filter": 1, + "label": "Order Type", + "oldfieldname": "order_type", + "oldfieldtype": "Select", + "options": "\nSales\nMaintenance\nShopping Cart", + "print_hide": 1, + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "collapsible_depends_on": "", - "columns": 0, - "depends_on": "eval:(doc.customer || doc.lead)", - "fieldname": "contact_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Address and Contact", - "length": 0, - "no_copy": 0, - "options": "fa fa-bullhorn", - "permlevel": 0, - "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 - }, + "collapsible": 1, + "depends_on": "eval:(doc.customer || doc.lead)", + "fieldname": "contact_section", + "fieldtype": "Section Break", + "label": "Address and Contact", + "options": "fa fa-bullhorn" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "customer_address", - "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 Address", - "length": 0, - "no_copy": 0, - "options": "Address", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "customer_address", + "fieldtype": "Link", + "label": "Customer Address", + "options": "Address", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "address_display", - "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": "Address", - "length": 0, - "no_copy": 0, - "oldfieldname": "customer_address", - "oldfieldtype": "Small Text", - "permlevel": 0, - "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 - }, + "fieldname": "address_display", + "fieldtype": "Small Text", + "label": "Address", + "oldfieldname": "customer_address", + "oldfieldtype": "Small Text", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.customer", - "fieldname": "contact_person", - "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": "Contact Person", - "length": 0, - "no_copy": 0, - "oldfieldname": "contact_person", - "oldfieldtype": "Link", - "options": "Contact", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "depends_on": "eval:doc.customer", + "fieldname": "contact_person", + "fieldtype": "Link", + "label": "Contact Person", + "oldfieldname": "contact_person", + "oldfieldtype": "Link", + "options": "Contact", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "contact_display", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Contact", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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 - }, + "fieldname": "contact_display", + "fieldtype": "Small Text", + "in_global_search": 1, + "label": "Contact", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "contact_mobile", - "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": "Mobile No", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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 - }, + "fieldname": "contact_mobile", + "fieldtype": "Small Text", + "label": "Mobile No", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "contact_email", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Contact Email", - "length": 0, - "no_copy": 0, - "options": "Email", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "contact_email", + "fieldtype": "Data", + "hidden": 1, + "label": "Contact Email", + "options": "Email", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "customer", - "fieldname": "col_break98", - "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, - "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, + "depends_on": "customer", + "fieldname": "col_break98", + "fieldtype": "Column Break", "width": "50%" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "shipping_address_name", - "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": "Shipping Address", - "length": 0, - "no_copy": 0, - "options": "Address", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "shipping_address_name", + "fieldtype": "Link", + "label": "Shipping Address", + "options": "Address", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "shipping_address", - "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": "Shipping Address", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "shipping_address", + "fieldtype": "Small Text", + "label": "Shipping Address", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "customer", - "description": "", - "fieldname": "customer_group", - "fieldtype": "Link", - "hidden": 1, - "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 Group", - "length": 0, - "no_copy": 0, - "oldfieldname": "customer_group", - "oldfieldtype": "Link", - "options": "Customer Group", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "depends_on": "customer", + "fieldname": "customer_group", + "fieldtype": "Link", + "hidden": 1, + "label": "Customer Group", + "oldfieldname": "customer_group", + "oldfieldtype": "Link", + "options": "Customer Group", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "territory", - "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": "Territory", - "length": 0, - "no_copy": 0, - "options": "Territory", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "territory", + "fieldtype": "Link", + "label": "Territory", + "options": "Territory", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "currency_and_price_list", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Currency and Price List", - "length": 0, - "no_copy": 0, - "options": "fa fa-tag", - "permlevel": 0, - "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 - }, + "collapsible": 1, + "fieldname": "currency_and_price_list", + "fieldtype": "Section Break", + "label": "Currency and Price List", + "options": "fa fa-tag" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "currency", - "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": "Currency", - "length": 0, - "no_copy": 0, - "oldfieldname": "currency", - "oldfieldtype": "Select", - "options": "Currency", - "permlevel": 0, - "print_hide": 1, - "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, + "fieldname": "currency", + "fieldtype": "Link", + "label": "Currency", + "oldfieldname": "currency", + "oldfieldtype": "Select", + "options": "Currency", + "print_hide": 1, + "reqd": 1, "width": "100px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Rate at which customer's currency is converted to company's base currency", - "fieldname": "conversion_rate", - "fieldtype": "Float", - "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": "Exchange Rate", - "length": 0, - "no_copy": 0, - "oldfieldname": "conversion_rate", - "oldfieldtype": "Currency", - "permlevel": 0, - "precision": "9", - "print_hide": 1, - "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, + "description": "Rate at which customer's currency is converted to company's base currency", + "fieldname": "conversion_rate", + "fieldtype": "Float", + "label": "Exchange Rate", + "oldfieldname": "conversion_rate", + "oldfieldtype": "Currency", + "precision": "9", + "print_hide": 1, + "reqd": 1, "width": "100px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break2", - "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, - "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, + "fieldname": "column_break2", + "fieldtype": "Column Break", "width": "50%" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "selling_price_list", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Price List", - "length": 0, - "no_copy": 0, - "oldfieldname": "price_list_name", - "oldfieldtype": "Select", - "options": "Price List", - "permlevel": 0, - "print_hide": 1, - "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, + "fieldname": "selling_price_list", + "fieldtype": "Link", + "label": "Price List", + "oldfieldname": "price_list_name", + "oldfieldtype": "Select", + "options": "Price List", + "print_hide": 1, + "reqd": 1, "width": "100px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "price_list_currency", - "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": "Price List Currency", - "length": 0, - "no_copy": 0, - "options": "Currency", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "price_list_currency", + "fieldtype": "Link", + "label": "Price List Currency", + "options": "Currency", + "print_hide": 1, + "read_only": 1, + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Rate at which Price list currency is converted to company's base currency", - "fieldname": "plc_conversion_rate", - "fieldtype": "Float", - "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": "Price List Exchange Rate", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "9", - "print_hide": 1, - "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 - }, + "description": "Rate at which Price list currency is converted to company's base currency", + "fieldname": "plc_conversion_rate", + "fieldtype": "Float", + "label": "Price List Exchange Rate", + "precision": "9", + "print_hide": 1, + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "ignore_pricing_rule", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Ignore Pricing Rule", - "length": 0, - "no_copy": 1, - "permlevel": 1, - "print_hide": 1, - "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 - }, + "default": "0", + "fieldname": "ignore_pricing_rule", + "fieldtype": "Check", + "label": "Ignore Pricing Rule", + "no_copy": 1, + "permlevel": 1, + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "items_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "options": "fa fa-shopping-cart", - "permlevel": 0, - "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 - }, + "fieldname": "items_section", + "fieldtype": "Section Break", + "oldfieldtype": "Section Break", + "options": "fa fa-shopping-cart" + }, { - "allow_bulk_edit": 1, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "items", - "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": "Items", - "length": 0, - "no_copy": 0, - "oldfieldname": "quotation_details", - "oldfieldtype": "Table", - "options": "Quotation Item", - "permlevel": 0, - "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": 1, + "fieldname": "items", + "fieldtype": "Table", + "label": "Items", + "oldfieldname": "quotation_details", + "oldfieldtype": "Table", + "options": "Quotation Item", + "reqd": 1, "width": "40px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "pricing_rule_details", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Pricing Rules", - "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 - }, + "fieldname": "pricing_rule_details", + "fieldtype": "Section Break", + "label": "Pricing Rules" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "pricing_rules", - "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": "Pricing Rule Detail", - "length": 0, - "no_copy": 0, - "options": "Pricing Rule Detail", - "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 - }, + "fieldname": "pricing_rules", + "fieldtype": "Table", + "label": "Pricing Rule Detail", + "options": "Pricing Rule Detail", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sec_break23", - "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, - "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 - }, + "fieldname": "sec_break23", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "total_qty", - "fieldtype": "Float", - "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": "Total Quantity", - "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 - }, + "fieldname": "total_qty", + "fieldtype": "Float", + "label": "Total Quantity", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_total", - "fieldtype": "Currency", - "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": "Total (Company Currency)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 - }, + "fieldname": "base_total", + "fieldtype": "Currency", + "label": "Total (Company Currency)", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_net_total", - "fieldtype": "Currency", - "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": "Net Total (Company Currency)", - "length": 0, - "no_copy": 0, - "oldfieldname": "net_total", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 1, - "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, + "fieldname": "base_net_total", + "fieldtype": "Currency", + "label": "Net Total (Company Currency)", + "oldfieldname": "net_total", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1, "width": "100px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_28", - "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, - "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 - }, + "fieldname": "column_break_28", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "total", - "fieldtype": "Currency", - "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": "Total", - "length": 0, - "no_copy": 0, - "options": "currency", - "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 - }, + "fieldname": "total", + "fieldtype": "Currency", + "label": "Total", + "options": "currency", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "net_total", - "fieldtype": "Currency", - "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": "Net Total", - "length": 0, - "no_copy": 0, - "options": "currency", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "net_total", + "fieldtype": "Currency", + "label": "Net Total", + "options": "currency", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "total_net_weight", - "fieldtype": "Float", - "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": "Total Net Weight", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 - }, + "fieldname": "total_net_weight", + "fieldtype": "Float", + "label": "Total Net Weight", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "taxes_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Taxes and Charges", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "options": "fa fa-money", - "permlevel": 0, - "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 - }, + "fieldname": "taxes_section", + "fieldtype": "Section Break", + "label": "Taxes and Charges", + "oldfieldtype": "Section Break", + "options": "fa fa-money" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "tax_category", - "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": "Tax Category", - "length": 0, - "no_copy": 0, - "options": "Tax Category", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 - }, + "fieldname": "tax_category", + "fieldtype": "Link", + "label": "Tax Category", + "options": "Tax Category", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_34", - "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, - "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 - }, + "fieldname": "column_break_34", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "shipping_rule", - "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": "Shipping Rule", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Button", - "options": "Shipping Rule", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "shipping_rule", + "fieldtype": "Link", + "label": "Shipping Rule", + "oldfieldtype": "Button", + "options": "Shipping Rule", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_36", - "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, - "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 - }, + "fieldname": "section_break_36", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "taxes_and_charges", - "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": "Sales Taxes and Charges Template", - "length": 0, - "no_copy": 0, - "oldfieldname": "charge", - "oldfieldtype": "Link", - "options": "Sales Taxes and Charges Template", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "taxes_and_charges", + "fieldtype": "Link", + "label": "Sales Taxes and Charges Template", + "oldfieldname": "charge", + "oldfieldtype": "Link", + "options": "Sales Taxes and Charges Template", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "taxes", - "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": "Sales Taxes and Charges", - "length": 0, - "no_copy": 0, - "oldfieldname": "other_charges", - "oldfieldtype": "Table", - "options": "Sales Taxes and Charges", - "permlevel": 0, - "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 - }, + "fieldname": "taxes", + "fieldtype": "Table", + "label": "Sales Taxes and Charges", + "oldfieldname": "other_charges", + "oldfieldtype": "Table", + "options": "Sales Taxes and Charges" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "sec_tax_breakup", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Tax Breakup", - "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 - }, + "collapsible": 1, + "fieldname": "sec_tax_breakup", + "fieldtype": "Section Break", + "label": "Tax Breakup" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "other_charges_calculation", - "fieldtype": "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": "Taxes and Charges Calculation", - "length": 0, - "no_copy": 1, - "oldfieldtype": "HTML", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "other_charges_calculation", + "fieldtype": "Text", + "label": "Taxes and Charges Calculation", + "no_copy": 1, + "oldfieldtype": "HTML", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_39", - "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, - "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 - }, + "fieldname": "section_break_39", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_total_taxes_and_charges", - "fieldtype": "Currency", - "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": "Total Taxes and Charges (Company Currency)", - "length": 0, - "no_copy": 0, - "oldfieldname": "other_charges_total", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "base_total_taxes_and_charges", + "fieldtype": "Currency", + "label": "Total Taxes and Charges (Company Currency)", + "oldfieldname": "other_charges_total", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_42", - "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, - "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 - }, + "fieldname": "column_break_42", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "total_taxes_and_charges", - "fieldtype": "Currency", - "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": "Total Taxes and Charges", - "length": 0, - "no_copy": 0, - "options": "currency", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "total_taxes_and_charges", + "fieldtype": "Currency", + "label": "Total Taxes and Charges", + "options": "currency", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "collapsible_depends_on": "discount_amount", - "columns": 0, - "fieldname": "section_break_44", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Additional Discount", - "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 - }, + "collapsible": 1, + "collapsible_depends_on": "discount_amount", + "fieldname": "section_break_44", + "fieldtype": "Section Break", + "label": "Additional Discount" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Grand Total", - "fieldname": "apply_discount_on", - "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": "Apply Additional Discount On", - "length": 0, - "no_copy": 0, - "options": "\nGrand Total\nNet Total", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 - }, + "default": "Grand Total", + "fieldname": "apply_discount_on", + "fieldtype": "Select", + "label": "Apply Additional Discount On", + "options": "\nGrand Total\nNet Total", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_discount_amount", - "fieldtype": "Currency", - "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": "Additional Discount Amount (Company Currency)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 - }, + "fieldname": "base_discount_amount", + "fieldtype": "Currency", + "label": "Additional Discount Amount (Company Currency)", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_46", - "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 - }, + "fieldname": "column_break_46", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "additional_discount_percentage", - "fieldtype": "Float", - "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": "Additional Discount Percentage", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 - }, + "fieldname": "additional_discount_percentage", + "fieldtype": "Float", + "label": "Additional Discount Percentage", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "discount_amount", - "fieldtype": "Currency", - "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": "Additional Discount Amount", - "length": 0, - "no_copy": 0, - "options": "currency", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "discount_amount", + "fieldtype": "Currency", + "label": "Additional Discount Amount", + "options": "currency", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "totals", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "options": "fa fa-money", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "totals", + "fieldtype": "Section Break", + "oldfieldtype": "Section Break", + "options": "fa fa-money", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_grand_total", - "fieldtype": "Currency", - "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": "Grand Total (Company Currency)", - "length": 0, - "no_copy": 0, - "oldfieldname": "grand_total", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 1, - "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, + "fieldname": "base_grand_total", + "fieldtype": "Currency", + "label": "Grand Total (Company Currency)", + "oldfieldname": "grand_total", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1, "width": "200px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_rounding_adjustment", - "fieldtype": "Currency", - "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": "Rounding Adjustment (Company Currency)", - "length": 0, - "no_copy": 1, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 - }, + "fieldname": "base_rounding_adjustment", + "fieldtype": "Currency", + "label": "Rounding Adjustment (Company Currency)", + "no_copy": 1, + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "In Words will be visible once you save the Quotation.", - "fieldname": "base_in_words", - "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": "In Words (Company Currency)", - "length": 0, - "no_copy": 0, - "oldfieldname": "in_words", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 1, - "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, + "description": "In Words will be visible once you save the Quotation.", + "fieldname": "base_in_words", + "fieldtype": "Data", + "label": "In Words (Company Currency)", + "oldfieldname": "in_words", + "oldfieldtype": "Data", + "print_hide": 1, + "read_only": 1, "width": "200px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "base_rounded_total", - "fieldtype": "Currency", - "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": "Rounded Total (Company Currency)", - "length": 0, - "no_copy": 0, - "oldfieldname": "rounded_total", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 1, - "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, + "fieldname": "base_rounded_total", + "fieldtype": "Currency", + "label": "Rounded Total (Company Currency)", + "oldfieldname": "rounded_total", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1, "width": "200px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break3", - "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, - "oldfieldtype": "Column Break", - "permlevel": 0, - "print_hide": 1, - "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, + "fieldname": "column_break3", + "fieldtype": "Column Break", + "oldfieldtype": "Column Break", + "print_hide": 1, "width": "50%" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "grand_total", - "fieldtype": "Currency", - "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": "Grand Total", - "length": 0, - "no_copy": 0, - "oldfieldname": "grand_total_export", - "oldfieldtype": "Currency", - "options": "currency", - "permlevel": 0, - "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, + "fieldname": "grand_total", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Grand Total", + "oldfieldname": "grand_total_export", + "oldfieldtype": "Currency", + "options": "currency", + "read_only": 1, "width": "200px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "rounding_adjustment", - "fieldtype": "Currency", - "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": "Rounding Adjustment", - "length": 0, - "no_copy": 1, - "options": "currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 - }, + "fieldname": "rounding_adjustment", + "fieldtype": "Currency", + "label": "Rounding Adjustment", + "no_copy": 1, + "options": "currency", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "fieldname": "rounded_total", - "fieldtype": "Currency", - "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": "Rounded Total", - "length": 0, - "no_copy": 0, - "oldfieldname": "rounded_total_export", - "oldfieldtype": "Currency", - "options": "currency", - "permlevel": 0, - "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, + "bold": 1, + "fieldname": "rounded_total", + "fieldtype": "Currency", + "label": "Rounded Total", + "oldfieldname": "rounded_total_export", + "oldfieldtype": "Currency", + "options": "currency", + "read_only": 1, "width": "200px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "in_words", - "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": "In Words", - "length": 0, - "no_copy": 0, - "oldfieldname": "in_words_export", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 1, - "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, + "fieldname": "in_words", + "fieldtype": "Data", + "label": "In Words", + "oldfieldname": "in_words_export", + "oldfieldtype": "Data", + "print_hide": 1, + "read_only": 1, "width": "200px" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "collapsible_depends_on": "", - "columns": 0, - "depends_on": "", - "fieldname": "payment_schedule_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payment Terms", - "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 - }, + "fieldname": "payment_schedule_section", + "fieldtype": "Section Break", + "label": "Payment Terms" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_terms_template", - "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": "Payment Terms Template", - "length": 0, - "no_copy": 0, - "options": "Payment Terms Template", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 - }, + "fieldname": "payment_terms_template", + "fieldtype": "Link", + "label": "Payment Terms Template", + "options": "Payment Terms Template", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_schedule", - "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": "Payment Schedule", - "length": 0, - "no_copy": 1, - "options": "Payment Schedule", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 - }, + "fieldname": "payment_schedule", + "fieldtype": "Table", + "label": "Payment Schedule", + "no_copy": 1, + "options": "Payment Schedule", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "collapsible_depends_on": "terms", - "columns": 0, - "fieldname": "terms_section_break", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Terms and Conditions", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "options": "fa fa-legal", - "permlevel": 0, - "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 - }, + "collapsible": 1, + "collapsible_depends_on": "terms", + "fieldname": "terms_section_break", + "fieldtype": "Section Break", + "label": "Terms and Conditions", + "oldfieldtype": "Section Break", + "options": "fa fa-legal" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "tc_name", - "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": "Terms", - "length": 0, - "no_copy": 0, - "oldfieldname": "tc_name", - "oldfieldtype": "Link", - "options": "Terms and Conditions", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "tc_name", + "fieldtype": "Link", + "label": "Terms", + "oldfieldname": "tc_name", + "oldfieldtype": "Link", + "options": "Terms and Conditions", + "print_hide": 1, + "report_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "terms", - "fieldtype": "Text Editor", - "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": "Term Details", - "length": 0, - "no_copy": 0, - "oldfieldname": "terms", - "oldfieldtype": "Text Editor", - "permlevel": 0, - "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 - }, + "fieldname": "terms", + "fieldtype": "Text Editor", + "label": "Term Details", + "oldfieldname": "terms", + "oldfieldtype": "Text Editor" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "print_settings", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Print Settings", - "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 - }, + "collapsible": 1, + "fieldname": "print_settings", + "fieldtype": "Section Break", + "label": "Print Settings" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "letter_head", - "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": "Letter Head", - "length": 0, - "no_copy": 0, - "oldfieldname": "letter_head", - "oldfieldtype": "Select", - "options": "Letter Head", - "permlevel": 0, - "print_hide": 1, - "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_on_submit": 1, + "fieldname": "letter_head", + "fieldtype": "Link", + "label": "Letter Head", + "oldfieldname": "letter_head", + "oldfieldtype": "Select", + "options": "Letter Head", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "group_same_items", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Group same items", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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_on_submit": 1, + "default": "0", + "fieldname": "group_same_items", + "fieldtype": "Check", + "label": "Group same items", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_73", - "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 - }, + "fieldname": "column_break_73", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "select_print_heading", - "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": "Print Heading", - "length": 0, - "no_copy": 1, - "oldfieldname": "select_print_heading", - "oldfieldtype": "Link", - "options": "Print Heading", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "select_print_heading", + "fieldtype": "Link", + "label": "Print Heading", + "no_copy": 1, + "oldfieldname": "select_print_heading", + "oldfieldtype": "Link", + "options": "Print Heading", + "print_hide": 1, + "report_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "language", - "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": "Print Language", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 - }, + "fieldname": "language", + "fieldtype": "Data", + "label": "Print Language", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "subscription_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Auto Repeat Section", - "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 - }, + "fieldname": "subscription_section", + "fieldtype": "Section Break", + "label": "Auto Repeat Section" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "auto_repeat", - "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": "Auto Repeat", - "length": 0, - "no_copy": 1, - "options": "Auto Repeat", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 - }, + "fieldname": "auto_repeat", + "fieldtype": "Link", + "label": "Auto Repeat", + "no_copy": 1, + "options": "Auto Repeat", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval: doc.auto_repeat", - "fieldname": "update_auto_repeat_reference", - "fieldtype": "Button", - "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": "Update Auto Repeat Reference", - "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_on_submit": 1, + "depends_on": "eval: doc.auto_repeat", + "fieldname": "update_auto_repeat_reference", + "fieldtype": "Button", + "label": "Update Auto Repeat Reference" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "more_info", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "More Information", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "options": "fa fa-file-text", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "collapsible": 1, + "fieldname": "more_info", + "fieldtype": "Section Break", + "label": "More Information", + "oldfieldtype": "Section Break", + "options": "fa fa-file-text", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "campaign", - "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": "Campaign", - "length": 0, - "no_copy": 0, - "oldfieldname": "campaign", - "oldfieldtype": "Link", - "options": "Campaign", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "campaign", + "fieldtype": "Link", + "label": "Campaign", + "oldfieldname": "campaign", + "oldfieldtype": "Link", + "options": "Campaign", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "source", - "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": "Source", - "length": 0, - "no_copy": 0, - "oldfieldname": "source", - "oldfieldtype": "Select", - "options": "Lead Source", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "source", + "fieldtype": "Link", + "label": "Source", + "oldfieldname": "source", + "oldfieldtype": "Select", + "options": "Lead Source", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.status===\"Lost\"", - "fieldname": "order_lost_reason", - "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": "Detailed Reason", - "length": 0, - "no_copy": 1, - "oldfieldname": "order_lost_reason", - "oldfieldtype": "Small Text", - "permlevel": 0, - "print_hide": 1, - "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_on_submit": 1, + "depends_on": "eval:doc.status===\"Lost\"", + "fieldname": "order_lost_reason", + "fieldtype": "Small Text", + "label": "Detailed Reason", + "no_copy": 1, + "oldfieldname": "order_lost_reason", + "oldfieldtype": "Small Text", + "print_hide": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break4", - "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, - "oldfieldtype": "Column Break", - "permlevel": 0, - "print_hide": 1, - "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, + "fieldname": "column_break4", + "fieldtype": "Column Break", + "oldfieldtype": "Column Break", + "print_hide": 1, "width": "50%" - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Draft", - "fieldname": "status", - "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": "Status", - "length": 0, - "no_copy": 1, - "oldfieldname": "status", - "oldfieldtype": "Select", - "options": "Draft\nSubmitted\nOrdered\nLost\nCancelled\nOpen\nReplied", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Draft", + "fieldname": "status", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Status", + "no_copy": 1, + "oldfieldname": "status", + "oldfieldtype": "Select", + "options": "Draft\nOpen\nReplied\nOrdered\nLost\nCancelled", + "print_hide": 1, + "read_only": 1, + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "enq_det", - "fieldtype": "Text", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Opportunity Item", - "length": 0, - "no_copy": 0, - "oldfieldname": "enq_det", - "oldfieldtype": "Text", - "permlevel": 0, - "print_hide": 1, - "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 - }, + "fieldname": "enq_det", + "fieldtype": "Text", + "hidden": 1, + "label": "Opportunity Item", + "oldfieldname": "enq_det", + "oldfieldtype": "Text", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "supplier_quotation", - "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": "Supplier Quotation", - "length": 0, - "no_copy": 0, - "options": "Supplier Quotation", - "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 - }, + "fieldname": "supplier_quotation", + "fieldtype": "Link", + "label": "Supplier Quotation", + "options": "Supplier Quotation" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "opportunity", - "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": "Opportunity", - "length": 0, - "no_copy": 0, - "options": "Opportunity", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 - }, + "fieldname": "opportunity", + "fieldtype": "Link", + "label": "Opportunity", + "options": "Opportunity", + "print_hide": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "lost_reasons", - "fieldtype": "Table MultiSelect", - "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": "Lost Reasons", - "length": 0, - "no_copy": 0, - "options": "Lost Reason Detail", - "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_on_submit": 1, + "fieldname": "lost_reasons", + "fieldtype": "Table MultiSelect", + "label": "Lost Reasons", + "options": "Lost Reason Detail", + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-shopping-cart", - "idx": 82, - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 1, - "menu_index": 0, - "modified": "2019-02-13 01:00:21.545591", - "modified_by": "Administrator", - "module": "Selling", - "name": "Quotation", - "owner": "Administrator", + ], + "icon": "fa fa-shopping-cart", + "idx": 82, + "is_submittable": 1, + "max_attachments": 1, + "modified": "2019-06-25 16:03:17.603222", + "modified_by": "Administrator", + "module": "Selling", + "name": "Quotation", + "owner": "Administrator", "permissions": [ { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Sales User", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Sales User", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "match": "", - "permlevel": 1, - "print": 0, - "read": 1, - "report": 1, - "role": "Sales User", - "set_user_permissions": 0, - "share": 0, - "submit": 0, - "write": 0 - }, + "permlevel": 1, + "read": 1, + "report": 1, + "role": "Sales User" + }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "match": "", - "permlevel": 1, - "print": 0, - "read": 1, - "report": 1, - "role": "Sales Manager", - "set_user_permissions": 0, - "share": 0, - "submit": 0, + "permlevel": 1, + "read": 1, + "report": 1, + "role": "Sales Manager", "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 1, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Sales Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "import": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Sales Manager", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Maintenance Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Maintenance Manager", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "match": "", - "permlevel": 1, - "print": 0, - "read": 1, - "report": 1, - "role": "Maintenance Manager", - "set_user_permissions": 0, - "share": 0, - "submit": 0, - "write": 0 - }, + "permlevel": 1, + "read": 1, + "report": 1, + "role": "Maintenance Manager" + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Maintenance User", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Maintenance User", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "match": "", - "permlevel": 1, - "print": 0, - "read": 1, - "report": 1, - "role": "Maintenance User", - "set_user_permissions": 0, - "share": 0, - "submit": 0, - "write": 0 + "permlevel": 1, + "read": 1, + "report": 1, + "role": "Maintenance User" } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 1, - "search_fields": "status,transaction_date,customer,lead,order_type", - "show_name_in_global_search": 1, - "sort_field": "modified", - "sort_order": "DESC", - "timeline_field": "customer", - "title_field": "title", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 -} + ], + "search_fields": "status,transaction_date,customer,lead,order_type", + "show_name_in_global_search": 1, + "sort_field": "modified", + "sort_order": "DESC", + "timeline_field": "customer", + "title_field": "title" +} \ No newline at end of file diff --git a/erpnext/selling/doctype/quotation/quotation_list.js b/erpnext/selling/doctype/quotation/quotation_list.js index 8baf9b2518..aa6038cbc8 100644 --- a/erpnext/selling/doctype/quotation/quotation_list.js +++ b/erpnext/selling/doctype/quotation/quotation_list.js @@ -2,11 +2,11 @@ frappe.listview_settings['Quotation'] = { add_fields: ["customer_name", "base_grand_total", "status", "company", "currency", 'valid_till'], get_indicator: function(doc) { - if(doc.status==="Submitted") { + if(doc.status==="Open") { if (doc.valid_till && doc.valid_till < frappe.datetime.nowdate()) { return [__("Expired"), "darkgrey", "valid_till,<," + frappe.datetime.nowdate()]; } else { - return [__("Submitted"), "blue", "status,=,Submitted"]; + return [__("Open"), "orange", "status,=,Open"]; } } else if(doc.status==="Ordered") { return [__("Ordered"), "green", "status,=,Ordered"]; From 8c621ab90c13d073b2a6072bc12d33a56fefc8c0 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 26 Jun 2019 11:10:17 +0530 Subject: [PATCH 75/92] fix: precision for certain calculations in buying controller (#18008) * fix: precision for certain numbers * fix: check precision of the received_qty * Update buying_controller.py --- erpnext/controllers/buying_controller.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index fed1fdd01f..2c46db0935 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -428,8 +428,9 @@ class BuyingController(StockController): elif not flt(d.rejected_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 - 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)) def validate_negative_quantity(self, item_row, field_list): From d48b2ac1265e816661bb2b3ee04e81b876154689 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 26 Jun 2019 11:37:49 +0530 Subject: [PATCH 76/92] fix: attendance gantt fix --- erpnext/hr/doctype/attendance/attendance_calendar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/hr/doctype/attendance/attendance_calendar.js b/erpnext/hr/doctype/attendance/attendance_calendar.js index b21afe5eae..104f09d69f 100644 --- a/erpnext/hr/doctype/attendance/attendance_calendar.js +++ b/erpnext/hr/doctype/attendance/attendance_calendar.js @@ -2,8 +2,8 @@ // For license information, please see license.txt frappe.views.calendar["Attendance"] = { field_map: { - "start": "date", - "end": "date", + "start": "attendance_date", + "end": "attendance_date", "id": "name", "docstatus": 1 }, From 8a6255078b92825c08498698c694a758467de859 Mon Sep 17 00:00:00 2001 From: Anurag Mishra Date: Fri, 21 Jun 2019 18:43:52 +0530 Subject: [PATCH 77/92] fix: wrong Casual Leave opening --- .../report/employee_leave_balance/employee_leave_balance.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py index 95cb30b791..5d781dba94 100644 --- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py +++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py @@ -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_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", filters = { "status": "Active", "company": filters.company}, fields = ["name", "employee_name", "department", "user_id"]) @@ -51,7 +54,8 @@ def get_data(filters, leave_types): filters.from_date, filters.to_date) # 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 = get_leave_balance_on(employee.name, leave_type, filters.to_date, From 0181eb0652e53e432c05d3034f996f9bdd504c81 Mon Sep 17 00:00:00 2001 From: Anurag Mishra Date: Wed, 26 Jun 2019 13:26:50 +0530 Subject: [PATCH 78/92] fix: removed unused function --- .../doctype/leave_application/leave_application.py | 13 ------------- .../employee_leave_balance.py | 2 +- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py index f542fa1e5c..113dcad8ae 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.py +++ b/erpnext/hr/doctype/leave_application/leave_application.py @@ -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)) -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): leave_applications = frappe.db.sql(""" select name, employee, leave_type, from_date, to_date, total_leave_days diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py index 5d781dba94..1843176852 100644 --- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py +++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _ 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): From fbc861320fa3f5f248aa34728b6f09f57ffa395f Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 26 Jun 2019 13:31:31 +0530 Subject: [PATCH 79/92] fix: Don't append None values in against_account (#18031) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 503f4f4dbc..e166fa22e8 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -485,7 +485,7 @@ class SalesInvoice(SellingController): """Set against account for debit to account""" against_acc = [] 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) self.against_income_account = ','.join(against_acc) From 2ab8d3ebcc95d5579dcfd5e8280ef2c72ad04a83 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 26 Jun 2019 13:32:41 +0530 Subject: [PATCH 80/92] fix: Move links to appropriate section (#17999) * fix: Move links to appropriate section * fix: New section Accounting Entries --- erpnext/config/accounting.py | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/erpnext/config/accounting.py b/erpnext/config/accounting.py index 0ab1f52e29..9a9ee7e963 100644 --- a/erpnext/config/accounting.py +++ b/erpnext/config/accounting.py @@ -40,17 +40,6 @@ def get_data(): "description": _("Tree of financial accounts."), "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", "description": _("Payment Request"), }, - { - "type": "doctype", - "name": "Payment Entry", - "description": _("Bank/Cash transactions against party or for internal transfer") - }, { "type": "doctype", "name": "Payment Term", @@ -179,6 +163,26 @@ def get_data(): "name": "Accounting Dimension", "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.") + }, ] }, { From 387ee8f5118f77e4e497b2542e1c86737e819484 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Wed, 26 Jun 2019 13:40:27 +0530 Subject: [PATCH 81/92] fix: returned qty issue while making sales invoice from dn if same item added multiple times (#18076) --- erpnext/stock/doctype/delivery_note/delivery_note.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index f54991b920..863a8109f8 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -448,7 +448,12 @@ def make_sales_invoice(source_name, target_doc=None): def get_pending_qty(item_row): 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: + 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 >= pending_qty: pending_qty = 0 @@ -456,6 +461,7 @@ def make_sales_invoice(source_name, target_doc=None): else: pending_qty -= returned_qty returned_qty = 0 + return pending_qty, returned_qty doc = get_mapped_doc("Delivery Note", source_name, { From 51c600696e28d76dac6f6ec7ae64ebe3e567f516 Mon Sep 17 00:00:00 2001 From: Karthikeyan S Date: Wed, 26 Jun 2019 13:41:00 +0530 Subject: [PATCH 82/92] fix(README): broken link to 'Report Security Vulnerabilities' (#18063) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cf3804f830..64f8d67d8e 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ The ERPNext code is licensed as GNU General Public License (v3) and the Document ## Contributing 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. [Translations](https://translate.erpnext.com) 1. [Chart of Accounts](https://charts.erpnext.com) From 48535e95e675d844f0dd3dfaf155ce53fb182f21 Mon Sep 17 00:00:00 2001 From: Karthikeyan S Date: Wed, 26 Jun 2019 13:41:49 +0530 Subject: [PATCH 83/92] Fix(integrations): Adding Error Logs for Woocommerce (#18061) (cherry picked from commit ae255d6328b70b148d28d9a88a695932656bf276) --- .../connectors/woocommerce_connection.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py index 4700202213..0b6ea8cc7c 100644 --- a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py +++ b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py @@ -22,7 +22,16 @@ def verify_request(): frappe.set_user(woocommerce_settings.creation_user) @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") if frappe.flags.woocomm_test_order_data: fd = frappe.flags.woocomm_test_order_data From df7a6520b905a8f15aa6dea60a5f35e04d4f6c26 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 26 Jun 2019 16:57:33 +0530 Subject: [PATCH 84/92] fix: Allow Rename in Issue Type --- .../doctype/issue_type/issue_type.json | 149 ++++++------------ 1 file changed, 45 insertions(+), 104 deletions(-) diff --git a/erpnext/support/doctype/issue_type/issue_type.json b/erpnext/support/doctype/issue_type/issue_type.json index ee7add8c7c..d10a0e4bf2 100644 --- a/erpnext/support/doctype/issue_type/issue_type.json +++ b/erpnext/support/doctype/issue_type/issue_type.json @@ -1,115 +1,56 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 0, - "autoname": "Prompt", - "beta": 0, - "creation": "2017-10-06 12:53:34.714153", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Setup", - "editable_grid": 1, - "engine": "InnoDB", + "allow_import": 1, + "allow_rename": 1, + "autoname": "Prompt", + "creation": "2017-10-06 12:53:34.714153", + "doctype": "DocType", + "document_type": "Setup", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "description" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "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 + "fieldname": "description", + "fieldtype": "Small Text", + "label": "Description" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2017-11-15 17:27:19.796807", - "modified_by": "Administrator", - "module": "Support", - "name": "Issue Type", - "name_case": "Title Case", - "owner": "Administrator", + ], + "modified": "2019-06-26 16:56:39.863392", + "modified_by": "Administrator", + "module": "Support", + "name": "Issue Type", + "name_case": "Title Case", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, "write": 1 - }, + }, { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Support Team", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Support Team", + "share": 1, "write": 1 } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "search_fields": "", - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "", - "track_changes": 1, - "track_seen": 0 + ], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file From 6de3ed5416c003c0010e90bfb02c4b226244a962 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 26 Jun 2019 21:57:03 +0530 Subject: [PATCH 85/92] fix: dn test cases --- .../stock/doctype/delivery_note/delivery_note.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 863a8109f8..1e522b834e 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -419,6 +419,8 @@ def get_returned_qty_map(delivery_note): @frappe.whitelist() def make_sales_invoice(source_name, target_doc=None): doc = frappe.get_doc('Delivery Note', source_name) + + to_make_invoice_qty_map = {} returned_qty_map = get_returned_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)) def update_item(source_doc, target_doc, source_parent): - target_doc.qty, returned_qty = get_pending_qty(source_doc) - returned_qty_map[source_doc.item_code] = returned_qty + target_doc.qty = to_make_invoice_qty_map[source_doc.name] if source_doc.serial_no and source_parent.per_billed > 0: target_doc.serial_no = get_delivery_note_serial_no(source_doc.item_code, @@ -450,7 +451,7 @@ def make_sales_invoice(source_name, target_doc=None): pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0) returned_qty = 0 - if returned_qty_map.get(item_row.item_code) > 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 @@ -462,7 +463,9 @@ def make_sales_invoice(source_name, target_doc=None): pending_qty -= returned_qty 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, { "Delivery Note": { @@ -482,7 +485,7 @@ def make_sales_invoice(source_name, target_doc=None): "cost_center": "cost_center" }, "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": { "doctype": "Sales Taxes and Charges", From 24b9d1e5a639414699cb8c18796d30bcb9772578 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 27 Jun 2019 01:29:00 +0530 Subject: [PATCH 86/92] fix: patch fixes --- .../patches/v12_0/set_priority_for_support.py | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/erpnext/patches/v12_0/set_priority_for_support.py b/erpnext/patches/v12_0/set_priority_for_support.py index fde4da3e65..cc290396f8 100644 --- a/erpnext/patches/v12_0/set_priority_for_support.py +++ b/erpnext/patches/v12_0/set_priority_for_support.py @@ -35,16 +35,17 @@ def set_priorities_service_level(): frappe.reload_doc("support", "doctype", "service_level") for service_level in service_level_priorities: - 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) + 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") @@ -57,20 +58,21 @@ def set_priorities_service_level_agreement(): frappe.reload_doc("support", "doctype", "service_level_agreement") for service_level_agreement in service_level_agreement_priorities: - doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name) + 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 + 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) + 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") \ No newline at end of file From 3b60fac3b7d7e0158bf6f07393145aa53b8af47e Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 27 Jun 2019 11:41:17 +0530 Subject: [PATCH 87/92] fix: open department in tree view via awesome bar --- erpnext/public/js/conf.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/public/js/conf.js b/erpnext/public/js/conf.js index 047922f366..ec71df3351 100644 --- a/erpnext/public/js/conf.js +++ b/erpnext/public/js/conf.js @@ -38,7 +38,8 @@ $.extend(frappe.create_routes, { "Item Group": "Tree/Item Group", "Sales Person": "Tree/Sales Person", "Account": "Tree/Account", - "Cost Center": "Tree/Cost Center" + "Cost Center": "Tree/Cost Center", + "Department": "Tree/Department", }); // preferred modules for breadcrumbs From bc777b17321e8cecb7ba5ae8ec46dbe7933ab91a Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 27 Jun 2019 12:43:39 +0530 Subject: [PATCH 88/92] fix: styling for sort selector --- erpnext/stock/page/stock_balance/stock_balance.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/page/stock_balance/stock_balance.js b/erpnext/stock/page/stock_balance/stock_balance.js index 85ea5b19be..fc869892e9 100644 --- a/erpnext/stock/page/stock_balance/stock_balance.js +++ b/erpnext/stock/page/stock_balance/stock_balance.js @@ -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() { page.item_dashboard = new erpnext.stock.ItemDashboard({ From e1aec5519b8cee6c66da272fc631e403f5966973 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 27 Jun 2019 13:14:41 +0530 Subject: [PATCH 89/92] fix(ui): better message after creating serial numbers --- erpnext/stock/doctype/serial_no/serial_no.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index c1aef95216..2df3d984e6 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -352,6 +352,7 @@ def get_auto_serial_nos(serial_no_series, qty): def auto_make_serial_nos(args): serial_nos = get_serial_nos(args.get('serial_no')) + created_numbers = [] for serial_no in serial_nos: if frappe.db.exists("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.save(ignore_permissions=True) 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:
{0}").format(', '.join(created_numbers))) def get_item_details(item_code): 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.save() - frappe.msgprint(_("Serial No {0} created").format(sr.name)) return sr.name def update_serial_nos_after_submit(controller, parentfield): From 468d5563c6c919f5c5ae8e308ee7f20e43652392 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 27 Jun 2019 14:13:54 +0530 Subject: [PATCH 90/92] fix: set serial numbers as data field --- erpnext/stock/report/stock_ledger/stock_ledger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py index 70da5b5980..a810ddd931 100644 --- a/erpnext/stock/report/stock_ledger/stock_ledger.py +++ b/erpnext/stock/report/stock_ledger/stock_ledger.py @@ -56,7 +56,7 @@ def get_columns(): {"label": _("Voucher Type"), "fieldname": "voucher_type", "width": 110}, {"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": _("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": _("Company"), "fieldname": "company", "fieldtype": "Link", "options": "Company", "width": 110} ] From be0001ece66bcbf20506cca7bfbd461d8a7ba97c Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 27 Jun 2019 22:59:52 +0530 Subject: [PATCH 91/92] fix: change to link field --- erpnext/support/web_form/issues/issues.json | 215 +++++++++++--------- 1 file changed, 116 insertions(+), 99 deletions(-) diff --git a/erpnext/support/web_form/issues/issues.json b/erpnext/support/web_form/issues/issues.json index 6d89d1180b..652114f738 100644 --- a/erpnext/support/web_form/issues/issues.json +++ b/erpnext/support/web_form/issues/issues.json @@ -1,111 +1,128 @@ { - "accept_payment": 0, - "allow_comments": 1, - "allow_delete": 1, - "allow_edit": 1, - "allow_incomplete": 0, - "allow_multiple": 1, - "allow_print": 0, - "amount": 0.0, - "amount_based_on_field": 0, - "breadcrumbs": "[{\"label\":_(\"Issues\"), \"route\":\"issues\"}]", - "creation": "2016-06-24 15:50:33.186483", - "doc_type": "Issue", - "docstatus": 0, - "doctype": "Web Form", - "idx": 0, - "introduction_text": "", - "is_standard": 1, - "login_required": 1, - "max_attachment_size": 0, - "modified": "2018-07-20 13:08:43.797886", - "modified_by": "Administrator", - "module": "Support", - "name": "issues", - "owner": "Administrator", - "published": 1, - "route": "issues", - "show_sidebar": 1, - "sidebar_items": [], - "success_message": "", - "success_url": "/issues", - "title": "Issue", + "accept_payment": 0, + "allow_comments": 1, + "allow_delete": 1, + "allow_edit": 1, + "allow_incomplete": 0, + "allow_multiple": 1, + "allow_print": 0, + "amount": 0.0, + "amount_based_on_field": 0, + "breadcrumbs": "[{\"label\":_(\"Issues\"), \"route\":\"issues\"}]", + "creation": "2016-06-24 15:50:33.186483", + "doc_type": "Issue", + "docstatus": 0, + "doctype": "Web Form", + "idx": 0, + "introduction_text": "", + "is_standard": 1, + "login_required": 1, + "max_attachment_size": 0, + "modified": "2019-06-27 22:58:49.609672", + "modified_by": "Administrator", + "module": "Support", + "name": "issues", + "owner": "Administrator", + "published": 1, + "route": "issues", + "route_to_success_link": 0, + "show_attachments": 0, + "show_in_grid": 0, + "show_sidebar": 1, + "sidebar_items": [], + "success_message": "", + "success_url": "/issues", + "title": "Issue", "web_form_fields": [ { - "fieldname": "subject", - "fieldtype": "Data", - "hidden": 0, - "label": "Subject", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 1 - }, + "allow_read_on_all_link_options": 0, + "fieldname": "subject", + "fieldtype": "Data", + "hidden": 0, + "label": "Subject", + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 1, + "show_in_filter": 0 + }, { - "default": "Open", - "fieldname": "status", - "fieldtype": "Select", - "hidden": 0, - "label": "Status", - "max_length": 0, - "max_value": 0, - "options": "Open\nReplied\nHold\nClosed", - "read_only": 1, - "reqd": 0 - }, + "allow_read_on_all_link_options": 0, + "default": "Open", + "fieldname": "status", + "fieldtype": "Select", + "hidden": 0, + "label": "Status", + "max_length": 0, + "max_value": 0, + "options": "Open\nReplied\nHold\nClosed", + "read_only": 1, + "reqd": 0, + "show_in_filter": 0 + }, { - "fieldname": "customer", - "fieldtype": "Data", - "hidden": 0, - "label": "Customer", - "max_length": 0, - "max_value": 0, - "options": "Customer", - "read_only": 1, - "reqd": 0 - }, + "allow_read_on_all_link_options": 0, + "fieldname": "customer", + "fieldtype": "Data", + "hidden": 0, + "label": "Customer", + "max_length": 0, + "max_value": 0, + "options": "Customer", + "read_only": 1, + "reqd": 0, + "show_in_filter": 0 + }, { - "fieldname": "description", - "fieldtype": "Text", - "hidden": 0, - "label": "Description", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 0 - }, + "allow_read_on_all_link_options": 0, + "fieldname": "description", + "fieldtype": "Text", + "hidden": 0, + "label": "Description", + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 0, + "show_in_filter": 0 + }, { - "fieldname": "attachment", - "fieldtype": "Attach", - "hidden": 0, - "label": "Attachment", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 0 - }, + "allow_read_on_all_link_options": 0, + "fieldname": "attachment", + "fieldtype": "Attach", + "hidden": 0, + "label": "Attachment", + "max_length": 0, + "max_value": 0, + "read_only": 0, + "reqd": 0, + "show_in_filter": 0 + }, { - "default": "Medium", - "fieldname": "priority", - "fieldtype": "Select", - "hidden": 0, - "label": "Priority", - "max_length": 0, - "max_value": 0, - "options": "Low\nMedium\nHigh", - "read_only": 0, - "reqd": 1 - }, + "allow_read_on_all_link_options": 0, + "default": "Medium", + "fieldname": "priority", + "fieldtype": "Link", + "hidden": 0, + "label": "Priority", + "max_length": 0, + "max_value": 0, + "options": "Issue Priority", + "read_only": 0, + "reqd": 1, + "show_in_filter": 0 + }, { - "default": "1", - "fieldname": "via_customer_portal", - "fieldtype": "Check", - "hidden": 1, - "label": "Via Customer Portal", - "max_length": 0, - "max_value": 0, - "read_only": 1, - "reqd": 0 + "allow_read_on_all_link_options": 0, + "default": "1", + "fieldname": "via_customer_portal", + "fieldtype": "Check", + "hidden": 1, + "label": "Via Customer Portal", + "max_length": 0, + "max_value": 0, + "read_only": 1, + "reqd": 0, + "show_in_filter": 0 } ] } \ No newline at end of file From 43e3dacba2c25915e0938c10af83572a3b8bac77 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 28 Jun 2019 00:00:48 +0530 Subject: [PATCH 92/92] fix: remove whitelisted method --- erpnext/support/doctype/issue/issue.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 0f6dd72f04..70430b16bb 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -173,7 +173,6 @@ class Issue(Document): self.response_by_variance = round(time_diff_in_hours(self.response_by, now_datetime())) self.resolution_by_variance = round(time_diff_in_hours(self.resolution_by, now_datetime())) - @frappe.whitelist() 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)