@@ -24,6 +24,8 @@ def docs_link_exists(body): | |||
parts = parsed_url.path.split('/') | |||
if len(parts) == 5 and parts[1] == "frappe" and parts[2] in docs_repos: | |||
return True | |||
if parsed_url.netloc in ["docs.erpnext.com", "frappeframework.com"]: | |||
return True | |||
if __name__ == "__main__": | |||
@@ -0,0 +1,50 @@ | |||
{ | |||
"actions": [], | |||
"creation": "2021-08-23 17:21:28.345841", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"title", | |||
"color", | |||
"custom" | |||
], | |||
"fields": [ | |||
{ | |||
"fieldname": "title", | |||
"fieldtype": "Data", | |||
"in_list_view": 1, | |||
"label": "Title", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"default": "Blue", | |||
"fieldname": "color", | |||
"fieldtype": "Select", | |||
"in_list_view": 1, | |||
"label": "Color", | |||
"options": "Blue\nCyan\nGray\nGreen\nLight Blue\nOrange\nPink\nPurple\nRed\nYellow", | |||
"reqd": 1 | |||
}, | |||
{ | |||
"default": "0", | |||
"fieldname": "custom", | |||
"fieldtype": "Check", | |||
"hidden": 1, | |||
"label": "Custom" | |||
} | |||
], | |||
"index_web_pages_for_search": 1, | |||
"istable": 1, | |||
"links": [], | |||
"modified": "2021-12-14 14:14:55.716378", | |||
"modified_by": "Administrator", | |||
"module": "Core", | |||
"name": "DocType State", | |||
"owner": "Administrator", | |||
"permissions": [], | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"states": [], | |||
"track_changes": 1 | |||
} |
@@ -0,0 +1,8 @@ | |||
# Copyright (c) 2021, Frappe Technologies and contributors | |||
# For license information, please see license.txt | |||
# import frappe | |||
from frappe.model.document import Document | |||
class DocTypeState(Document): | |||
pass |
@@ -114,6 +114,7 @@ frappe.ui.form.on("Customize Form", { | |||
frm.page.clear_icons(); | |||
if (frm.doc.doc_type) { | |||
frm.page.set_title(__('Customize Form - {0}', [frm.doc.doc_type])); | |||
frappe.customize_form.set_primary_action(frm); | |||
frm.add_custom_button( | |||
@@ -276,6 +277,21 @@ frappe.ui.form.on("DocType Action", { | |||
} | |||
}); | |||
// can't delete standard states | |||
frappe.ui.form.on("DocType State", { | |||
before_states_remove: function(frm, doctype, name) { | |||
let row = frappe.get_doc(doctype, name); | |||
if (!(row.custom || row.__islocal)) { | |||
frappe.msgprint(__("Cannot delete standard document state.")); | |||
throw "cannot delete standard document state"; | |||
} | |||
}, | |||
states_add: function(frm, cdt, cdn) { | |||
let f = frappe.model.get_doc(cdt, cdn); | |||
f.custom = 1; | |||
} | |||
}); | |||
frappe.customize_form.set_primary_action = function(frm) { | |||
frm.page.set_primary_action(__("Update"), function() { | |||
if (frm.doc.doc_type) { | |||
@@ -41,6 +41,8 @@ | |||
"actions", | |||
"document_links_section", | |||
"links", | |||
"document_states_section", | |||
"states", | |||
"section_break_8", | |||
"sort_field", | |||
"column_break_10", | |||
@@ -280,6 +282,20 @@ | |||
"fieldname": "autoname", | |||
"fieldtype": "Data", | |||
"label": "Auto Name" | |||
}, | |||
{ | |||
"collapsible": 1, | |||
"collapsible_depends_on": "states", | |||
"depends_on": "doc_type", | |||
"fieldname": "document_states_section", | |||
"fieldtype": "Section Break", | |||
"label": "Document States" | |||
}, | |||
{ | |||
"fieldname": "states", | |||
"fieldtype": "Table", | |||
"label": "States", | |||
"options": "DocType State" | |||
} | |||
], | |||
"hide_toolbar": 1, | |||
@@ -288,10 +304,11 @@ | |||
"index_web_pages_for_search": 1, | |||
"issingle": 1, | |||
"links": [], | |||
"modified": "2021-06-21 19:01:06.920663", | |||
"modified": "2021-12-14 16:45:04.308690", | |||
"modified_by": "Administrator", | |||
"module": "Custom", | |||
"name": "Customize Form", | |||
"naming_rule": "Expression (old style)", | |||
"owner": "Administrator", | |||
"permissions": [ | |||
{ | |||
@@ -308,5 +325,6 @@ | |||
"search_fields": "doc_type", | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"states": [], | |||
"track_changes": 1 | |||
} |
@@ -72,7 +72,7 @@ class CustomizeForm(Document): | |||
new_d[prop] = d.get(prop) | |||
self.append("fields", new_d) | |||
for fieldname in ('links', 'actions'): | |||
for fieldname in ('links', 'actions', 'states'): | |||
for d in meta.get(fieldname): | |||
self.append(fieldname, d) | |||
@@ -258,7 +258,8 @@ class CustomizeForm(Document): | |||
''' | |||
for doctype, fieldname, field_map in ( | |||
('DocType Link', 'links', doctype_link_properties), | |||
('DocType Action', 'actions', doctype_action_properties) | |||
('DocType Action', 'actions', doctype_action_properties), | |||
('DocType State', 'states', doctype_state_properties), | |||
): | |||
has_custom = False | |||
items = [] | |||
@@ -568,6 +569,11 @@ doctype_action_properties = { | |||
'hidden': 'Check' | |||
} | |||
doctype_state_properties = { | |||
'title': 'Data', | |||
'color': 'Select' | |||
} | |||
ALLOWED_FIELDTYPE_CHANGE = ( | |||
('Currency', 'Float', 'Percent'), | |||
@@ -37,7 +37,7 @@ | |||
"in_list_view": 1, | |||
"in_standard_filter": 1, | |||
"label": "Applied On", | |||
"options": "\nDocField\nDocType\nDocType Link\nDocType Action", | |||
"options": "\nDocField\nDocType\nDocType Link\nDocType Action\nDocType State", | |||
"read_only_depends_on": "eval:!doc.__islocal", | |||
"reqd": 1 | |||
}, | |||
@@ -109,7 +109,7 @@ | |||
"idx": 1, | |||
"index_web_pages_for_search": 1, | |||
"links": [], | |||
"modified": "2021-09-04 12:46:17.860769", | |||
"modified": "2021-12-14 14:15:41.929071", | |||
"modified_by": "Administrator", | |||
"module": "Custom", | |||
"name": "Property Setter", | |||
@@ -141,5 +141,6 @@ | |||
"search_fields": "doc_type,property", | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"states": [], | |||
"track_changes": 1 | |||
} |
@@ -1,155 +1,55 @@ | |||
{ | |||
"allow_copy": 0, | |||
"allow_import": 0, | |||
"allow_rename": 0, | |||
"beta": 0, | |||
"creation": "2016-10-19 12:26:42.569185", | |||
"custom": 0, | |||
"docstatus": 0, | |||
"doctype": "DocType", | |||
"document_type": "", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"actions": [], | |||
"creation": "2016-10-19 12:26:42.569185", | |||
"doctype": "DocType", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"field_order": [ | |||
"column_name", | |||
"status", | |||
"indicator", | |||
"order" | |||
], | |||
"fields": [ | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "column_name", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 1, | |||
"in_standard_filter": 0, | |||
"label": "Column Name", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"remember_last_selected_value": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
"fieldname": "column_name", | |||
"fieldtype": "Data", | |||
"in_list_view": 1, | |||
"label": "Column Name" | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"default": "Active", | |||
"fieldname": "status", | |||
"fieldtype": "Select", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 1, | |||
"in_standard_filter": 0, | |||
"label": "Status", | |||
"length": 0, | |||
"no_copy": 0, | |||
"options": "Active\nArchived", | |||
"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 | |||
}, | |||
"default": "Active", | |||
"fieldname": "status", | |||
"fieldtype": "Select", | |||
"in_list_view": 1, | |||
"label": "Status", | |||
"options": "Active\nArchived" | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"default": "darkgrey", | |||
"fieldname": "indicator", | |||
"fieldtype": "Select", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 1, | |||
"in_standard_filter": 0, | |||
"label": "Indicator", | |||
"length": 0, | |||
"no_copy": 0, | |||
"options": "blue\norange\nred\ngreen\ndarkgrey\npurple\nyellow\nlightblue", | |||
"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 | |||
}, | |||
"default": "Gray", | |||
"fieldname": "indicator", | |||
"fieldtype": "Select", | |||
"in_list_view": 1, | |||
"label": "Indicator", | |||
"options": "Blue\nCyan\nGray\nGreen\nLight Blue\nOrange\nPink\nPurple\nRed\nRed\nYellow" | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "order", | |||
"fieldtype": "Code", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Order", | |||
"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": "order", | |||
"fieldtype": "Code", | |||
"label": "Order" | |||
} | |||
], | |||
"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": "2017-01-17 15:23:43.520379", | |||
"modified_by": "Administrator", | |||
"module": "Desk", | |||
"name": "Kanban Board Column", | |||
"name_case": "", | |||
"owner": "Administrator", | |||
"permissions": [], | |||
"quick_entry": 1, | |||
"read_only": 0, | |||
"read_only_onload": 0, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"track_changes": 1, | |||
"track_seen": 0 | |||
], | |||
"istable": 1, | |||
"links": [], | |||
"modified": "2021-12-14 13:13:38.804259", | |||
"modified_by": "Administrator", | |||
"module": "Desk", | |||
"name": "Kanban Board Column", | |||
"owner": "Administrator", | |||
"permissions": [], | |||
"quick_entry": 1, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"states": [], | |||
"track_changes": 1 | |||
} |
@@ -338,7 +338,7 @@ class BaseDocument(object): | |||
return self.meta.get_field(fieldname).options | |||
except AttributeError: | |||
if self.doctype == 'DocType': | |||
return dict(links='DocType Link', actions='DocType Action').get(fieldname) | |||
return dict(links='DocType Link', actions='DocType Action', states='DocType State').get(fieldname) | |||
raise | |||
def get_parentfield_of_doctype(self, doctype): | |||
@@ -66,7 +66,7 @@ def load_doctype_from_file(doctype): | |||
class Meta(Document): | |||
_metaclass = True | |||
default_fields = list(default_fields)[1:] | |||
special_doctypes = ("DocField", "DocPerm", "DocType", "Module Def", 'DocType Action', 'DocType Link') | |||
special_doctypes = ("DocField", "DocPerm", "DocType", "Module Def", 'DocType Action', 'DocType Link', 'DocType State') | |||
def __init__(self, doctype): | |||
self._fields = {} | |||
@@ -184,7 +184,8 @@ class Meta(Document): | |||
"fields": "DocField", | |||
"permissions": "DocPerm", | |||
"actions": "DocType Action", | |||
'links': 'DocType Link' | |||
"links": "DocType Link", | |||
"states": "DocType State", | |||
}.get(fieldname) | |||
def get_field(self, fieldname): | |||
@@ -343,8 +344,14 @@ class Meta(Document): | |||
d.set(ps.property, cast(ps.property_type, ps.value)) | |||
break | |||
elif ps.doctype_or_field=='DocType State': | |||
for d in self.states: | |||
if d.name == ps.row_name: | |||
d.set(ps.property, cast(ps.property_type, ps.value)) | |||
break | |||
def add_custom_links_and_actions(self): | |||
for doctype, fieldname in (('DocType Link', 'links'), ('DocType Action', 'actions')): | |||
for doctype, fieldname in (('DocType Link', 'links'), ('DocType Action', 'actions'), ('DocType State', 'states')): | |||
# ignore_ddl because the `custom` column was added later via a patch | |||
for d in frappe.get_all(doctype, fields='*', filters=dict(parent=self.name, custom=1), ignore_ddl=True): | |||
self.append(fieldname, d) | |||
@@ -571,6 +578,7 @@ DOCTYPE_TABLE_FIELDS = [ | |||
frappe._dict({"fieldname": "permissions", "options": "DocPerm"}), | |||
frappe._dict({"fieldname": "actions", "options": "DocType Action"}), | |||
frappe._dict({"fieldname": "links", "options": "DocType Link"}), | |||
frappe._dict({"fieldname": "states", "options": "DocType State"}), | |||
] | |||
####### | |||
@@ -30,7 +30,7 @@ def sync_for(app_name, force=0, reset_permissions=False): | |||
FRAPPE_PATH = frappe.get_app_path("frappe") | |||
for core_module in ["docfield", "docperm", "doctype_action", "doctype_link", "role", "has_role", "doctype"]: | |||
for core_module in ["docfield", "docperm", "doctype_action", "doctype_link", "doctype_state", "role", "has_role", "doctype"]: | |||
files.append(os.path.join(FRAPPE_PATH, "core", "doctype", core_module, f"{core_module}.json")) | |||
for custom_module in ["custom_field", "property_setter"]: | |||
@@ -8,7 +8,7 @@ import frappe | |||
from frappe.model.base_document import get_controller | |||
from frappe.modules import get_module_path, scrub_dt_dn | |||
from frappe.query_builder import DocType | |||
from frappe.utils import get_datetime_str, now | |||
from frappe.utils import get_datetime, now | |||
def caclulate_hash(path: str) -> str: | |||
@@ -109,7 +109,9 @@ def import_file_by_path(path: str,force: bool = False,data_import: bool = False, | |||
# modified timestamp in db, none if doctype's first import | |||
db_modified_timestamp = frappe.db.get_value(doc["doctype"], doc["name"], "modified") | |||
is_db_timestamp_latest = db_modified_timestamp and doc.get("modified") <= get_datetime_str(db_modified_timestamp) | |||
is_db_timestamp_latest = db_modified_timestamp and ( | |||
get_datetime(doc.get("modified")) <= get_datetime(db_modified_timestamp) | |||
) | |||
if not force or db_modified_timestamp: | |||
try: | |||
@@ -120,11 +122,11 @@ def import_file_by_path(path: str,force: bool = False,data_import: bool = False, | |||
# if hash exists and is equal no need to update | |||
if stored_hash and stored_hash == calculated_hash: | |||
return False | |||
continue | |||
# if hash doesn't exist, check if db timestamp is same as json timestamp, add hash if from doctype | |||
if is_db_timestamp_latest and doc["doctype"] != "DocType": | |||
return False | |||
continue | |||
import_doc( | |||
docdict=doc, | |||
@@ -161,7 +163,7 @@ def import_file_by_path(path: str,force: bool = False,data_import: bool = False, | |||
def is_timestamp_changed(doc): | |||
# check if timestamps match | |||
db_modified = frappe.db.get_value(doc["doctype"], doc["name"], "modified") | |||
return not (db_modified and doc.get("modified") == get_datetime_str(db_modified)) | |||
return not (db_modified and get_datetime(doc.get("modified")) == get_datetime(db_modified)) | |||
def read_doc_from_file(path): | |||
@@ -187,3 +187,4 @@ frappe.patches.v14_0.copy_mail_data #08.03.21 | |||
frappe.patches.v14_0.update_workspace2 # 20.09.2021 | |||
frappe.patches.v14_0.update_github_endpoints #08-11-2021 | |||
frappe.patches.v14_0.remove_db_aggregation | |||
frappe.patches.v14_0.update_color_names_in_kanban_board_column |
@@ -0,0 +1,22 @@ | |||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
from __future__ import unicode_literals | |||
import frappe | |||
def execute(): | |||
frappe.reload_doc("desk", "doctype", "kanban_board_column") | |||
indicator_map = { | |||
'blue': 'Blue', | |||
'orange': 'Orange', | |||
'red': 'Red', | |||
'green': 'Green', | |||
'darkgrey': 'Gray', | |||
'gray': 'Gray', | |||
'purple': 'Purple', | |||
'yellow': 'Yellow', | |||
'lightblue': 'Light Blue', | |||
} | |||
for d in frappe.db.get_all('Kanban Board Column', fields=['name', 'indicator']): | |||
color_name = indicator_map.get(d.indicator, 'Gray') | |||
frappe.db.set_value('Kanban Board Column', d.name, 'indicator', color_name) |
@@ -312,7 +312,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { | |||
let $check_all_checkbox = this.$checkbox_actions.find(".list-check-all"); | |||
if ($check_all_checkbox.prop("checked") && target && !target.prop("checked")) { | |||
$check_all_checkbox.prop("checked", false); | |||
$check_all_checkbox.prop("checked", false); | |||
} | |||
$check_all_checkbox.prop("checked", this.$checks.length === this.data.length); | |||
@@ -10,6 +10,8 @@ frappe.has_indicator = function(doctype) { | |||
} else if(frappe.meta.has_field(doctype, 'enabled') | |||
|| frappe.meta.has_field(doctype, 'disabled')) { | |||
return true; | |||
} else if (frappe.meta.has_field(doctype, 'status') && frappe.get_meta(doctype).states.length) { | |||
return true; | |||
} | |||
return false; | |||
} | |||
@@ -21,6 +23,7 @@ frappe.get_indicator = function(doc, doctype) { | |||
if(!doctype) doctype = doc.doctype; | |||
let meta = frappe.get_meta(doctype); | |||
var workflow = frappe.workflow.workflows[doctype]; | |||
var without_workflow = workflow ? workflow['override_status'] : true; | |||
@@ -61,6 +64,13 @@ frappe.get_indicator = function(doc, doctype) { | |||
return [__("Cancelled"), "red", "docstatus,=,2"]; | |||
} | |||
// based on document state | |||
if (doc.status && meta && meta.states && meta.states.find(d => d.title === doc.status)) { | |||
let state = meta.states.find(d => d.title === doc.status); | |||
let color_class = frappe.scrub(state.color, '-'); | |||
return [__(doc.status), color_class, "status,=," + doc.status]; | |||
} | |||
if(settings.get_indicator) { | |||
var indicator = settings.get_indicator(doc); | |||
if(indicator) return indicator; | |||
@@ -467,7 +467,7 @@ frappe.provide("frappe.views"); | |||
'kanban_column', { | |||
title: column.title, | |||
doctype: store.getState().doctype, | |||
indicator: column.indicator | |||
indicator: frappe.scrub(column.indicator, '-') | |||
})).appendTo(wrapper); | |||
self.$kanban_cards = self.$kanban_column.find('.kanban-cards'); | |||
} | |||
@@ -581,13 +581,12 @@ frappe.provide("frappe.views"); | |||
} | |||
}); | |||
get_column_indicators(function(indicators) { | |||
var html = '<li class="button-group">'; | |||
html += indicators.reduce(function(prev, curr) { | |||
return prev + '<div \ | |||
data-action="indicator" data-indicator="'+curr+'"\ | |||
class="btn btn-default btn-xs indicator-pill ' + curr + '"></div>'; | |||
}, ""); | |||
html += '</li>'; | |||
let html = `<li class="button-group">${ | |||
indicators.map(indicator => { | |||
let classname = frappe.scrub(indicator, '-'); | |||
return `<div data-action="indicator" data-indicator="${indicator}" class="btn btn-default btn-xs indicator-pill ${classname}"></div>` | |||
}).join('') | |||
}</li>`; | |||
self.$kanban_column.find(".column-options .dropdown-menu") | |||
.append(html); | |||
}); | |||
@@ -352,6 +352,7 @@ class ShortcutDialog extends WidgetDialog { | |||
label: __("Color"), | |||
options: ["Grey", "Green", "Red", "Orange", "Pink", "Yellow", "Blue", "Cyan"], | |||
default: "Grey", | |||
input_class: "color-select", | |||
onchange: () => { | |||
let color = this.dialog.fields_dict.color.value.toLowerCase(); | |||
let $select = this.dialog.fields_dict.color.$input; | |||
@@ -119,7 +119,7 @@ input[type="checkbox"] { | |||
} | |||
.frappe-control[data-fieldtype="Select"].frappe-control[data-fieldname="color"] { | |||
select { | |||
.color-select { | |||
padding-left: 40px; | |||
} | |||
@@ -163,9 +163,13 @@ | |||
@include indicator-pill-color('purple'); | |||
} | |||
.indicator-pill.lightblue, | |||
.indicator-pill-right.lightblue, | |||
.indicator-pill-round.lightblue { | |||
.indicator.light-blue { | |||
@include indicator-color('light-blue'); | |||
} | |||
.indicator-pill.light-blue, | |||
.indicator-pill-right.light-blue, | |||
.indicator-pill-round.light-blue { | |||
@include indicator-pill-color('light-blue'); | |||
} | |||
@@ -9,6 +9,7 @@ def before_install(): | |||
frappe.reload_doc("core", "doctype", "docperm") | |||
frappe.reload_doc("core", "doctype", "doctype_action") | |||
frappe.reload_doc("core", "doctype", "doctype_link") | |||
frappe.reload_doc("core", "doctype", "doctype_state") | |||
frappe.reload_doc("desk", "doctype", "form_tour_step") | |||
frappe.reload_doc("desk", "doctype", "form_tour") | |||
frappe.reload_doc("core", "doctype", "doctype") | |||