diff --git a/frappe/core/doctype/custom_field/custom_field.py b/frappe/core/doctype/custom_field/custom_field.py index e4660955a2..e83c7df6ad 100644 --- a/frappe/core/doctype/custom_field/custom_field.py +++ b/frappe/core/doctype/custom_field/custom_field.py @@ -26,6 +26,9 @@ class CustomField(Document): if not self.idx: self.idx = len(frappe.get_meta(self.dt).get("fields")) + 1 + if not self.fieldname: + frappe.throw(_("Fieldname not set for Custom Field")) + def on_update(self): # validate field from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype @@ -38,9 +41,10 @@ class CustomField(Document): self.create_property_setter() # update the schema - from frappe.model.db_schema import updatedb - updatedb(self.dt) - + if not frappe.flags.in_test: + from frappe.model.db_schema import updatedb + updatedb(self.dt) + def on_trash(self): # delete property setter entries frappe.db.sql("""\ diff --git a/frappe/core/doctype/custom_field/test_records.json b/frappe/core/doctype/custom_field/test_records.json new file mode 100644 index 0000000000..f2ba4d8c90 --- /dev/null +++ b/frappe/core/doctype/custom_field/test_records.json @@ -0,0 +1,11 @@ +[ + { + "dt": "User", + "label": "Test Custom Field", + "description": "A Custom Field for Testing", + "fieldtype": "Select", + "in_list_view": 1, + "options": "\nCustom 1\nCustom 2\nCustom 3", + "default": "Custom 3" + } +] \ No newline at end of file diff --git a/frappe/core/doctype/customize_form/customize_form.js b/frappe/core/doctype/customize_form/customize_form.js index 2b95d6ba6e..fbe186376e 100644 --- a/frappe/core/doctype/customize_form/customize_form.js +++ b/frappe/core/doctype/customize_form/customize_form.js @@ -4,7 +4,6 @@ frappe.provide("frappe.customize_form"); frappe.ui.form.on("Customize Form", "onload", function(frm) { - frm.fields_dict.fields.grid.cannot_add_rows = true; frappe.customize_form.add_fields_help(frm); frm.set_query("doc_type", function() { @@ -215,7 +214,7 @@ frappe.customize_form.add_fields_help = function(frm) { \ \ Press Esc to close\ \ \ @@ -227,7 +226,7 @@ frappe.customize_form.add_fields_help = function(frm) { d.show(); - frm.fields_help_dialog = d; + frappe.customize_form.fields_help_dialog = d; }); } diff --git a/frappe/core/doctype/customize_form/customize_form.json b/frappe/core/doctype/customize_form/customize_form.json index 568d2e9074..5db77d1bbf 100644 --- a/frappe/core/doctype/customize_form/customize_form.json +++ b/frappe/core/doctype/customize_form/customize_form.json @@ -98,7 +98,7 @@ "permlevel": 0 }, { - "fieldname": "fields", + "fieldname": "customize_form_fields", "fieldtype": "Table", "label": "Fields", "no_copy": 0, @@ -111,7 +111,7 @@ "icon": "icon-glass", "idx": 1, "issingle": 1, - "modified": "2014-01-15 16:16:24.000000", + "modified": "2014-01-15 16:16:22.000000", "modified_by": "Administrator", "module": "Core", "name": "Customize Form", diff --git a/frappe/core/doctype/customize_form/customize_form.py b/frappe/core/doctype/customize_form/customize_form.py index 1fe5007cd2..675e60be92 100644 --- a/frappe/core/doctype/customize_form/customize_form.py +++ b/frappe/core/doctype/customize_form/customize_form.py @@ -7,56 +7,52 @@ from __future__ import unicode_literals Thus providing a better UI from user perspective """ import frappe, json +from frappe import _ from frappe.utils import cstr from frappe.model.document import Document +from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype class CustomizeForm(Document): - doctype_properties = ( - 'search_fields', - 'default_print_format', - 'read_only_onload', - 'allow_print', - 'allow_email', - 'allow_copy', - 'allow_attach', - 'max_attachments' - ) + doctype_properties = { + 'search_fields': 'Data', + 'default_print_format': 'Data', + 'read_only_onload': 'Check', + 'allow_print': 'Check', + 'allow_email': 'Check', + 'allow_copy': 'Check', + 'allow_attach': 'Check', + 'max_attachments': 'Int' + } - docfield_properties = ( - 'idx', - 'label', - 'fieldtype', - 'fieldname', - 'options', - 'permlevel', - 'width', - 'print_width', - 'reqd', - 'ignore_restrictions', - 'in_filter', - 'in_list_view', - 'hidden', - 'print_hide', - 'report_hide', - 'allow_on_submit', - 'depends_on', - 'description', - 'default', - 'name', - ) + docfield_properties = { + 'idx': 'Int', + 'label': 'Data', + 'fieldtype': 'Select', + 'options': 'Text', + 'permlevel': 'Int', + 'width': 'Data', + 'print_width': 'Data', + 'reqd': 'Check', + 'ignore_restrictions': 'Check', + 'in_filter': 'Check', + 'in_list_view': 'Check', + 'hidden': 'Check', + 'print_hide': 'Check', + 'report_hide': 'Check', + 'allow_on_submit': 'Check', + 'depends_on': 'Data', + 'description': 'Text', + 'default': 'Text' + } allowed_fieldtype_change = (('Currency', 'Float'), ('Small Text', 'Data'), ('Text', 'Text Editor', 'Code')) - # property_restrictions = { - # 'fieldtype': (('Currency', 'Float'), ('Small Text', 'Data'), ('Text', 'Text Editor', 'Code')), - # } - def on_update(self): frappe.db.sql("delete from tabSingles where doctype='Customize Form'") frappe.db.sql("delete from `tabCustomize Form Field`") - + def fetch_to_customize(self): self.clear_existing_doc() if not self.doc_type: @@ -65,14 +61,14 @@ class CustomizeForm(Document): meta = frappe.get_meta(self.doc_type) # doctype properties - for fieldname in self.doctype_properties: - self.set(fieldname, meta.get(fieldname)) + for property in self.doctype_properties: + self.set(property, meta.get(property)) for d in meta.get("fields"): - new_d = {} - for fieldname in self.docfield_properties: - new_d[fieldname] = d.get(fieldname) - self.append("fields", new_d) + new_d = {"fieldname": d.fieldname, "is_custom_field": d.get("is_custom_field"), "name": d.name} + for property in self.docfield_properties: + new_d[property] = d.get(property) + self.append("customize_form_fields", new_d) # NOTE doc is sent to clientside by run_method @@ -91,9 +87,150 @@ class CustomizeForm(Document): def save_customization(self): if not self.doc_type: return - + + self.set_property_setters() + self.update_custom_fields() + self.set_idx_property_setter() + validate_fields_for_doctype(self.doc_type) + + frappe.msgprint("{}: {} {}.".format(_("DocType"), _(self.doc_type), _("updated"))) frappe.clear_cache(doctype=self.doc_type) self.fetch_to_customize() + + def set_property_setters(self): + meta = frappe.get_meta(self.doc_type) + # doctype property setters + for property in self.doctype_properties: + if self.get(property) != meta.get(property): + self.make_property_setter(property=property, value=self.get(property), + property_type=self.doctype_properties[property]) + + for df in self.get("customize_form_fields"): + if df.get("__islocal"): + continue + + meta_df = meta.get("fields", {"fieldname": df.fieldname}) + + if not meta_df or meta_df[0].get("is_custom_field"): + continue + + for property in self.docfield_properties: + if df.get(property) != meta_df[0].get(property): + if property == "fieldtype": + self.validate_fieldtype_change(df, meta_df[0].get(property), df.get(property)) + + self.make_property_setter(property=property, value=df.get(property), + property_type=self.docfield_properties[property], fieldname=df.fieldname) + + def update_custom_fields(self): + for df in self.get("customize_form_fields"): + if df.get("__islocal"): + self.add_custom_field(df) + else: + self.update_in_custom_field(df) + + self.delete_custom_fields() + + def add_custom_field(self, df): + d = frappe.new_doc("Custom Field") + d.dt = self.doc_type + for property in self.docfield_properties: + d.set(property, df.get(property)) + d.insert() + df.fieldname = d.fieldname + + def update_in_custom_field(self, df): + meta = frappe.get_meta(self.doc_type) + meta_df = meta.get("fields", {"fieldname": df.fieldname}) + if not (meta_df and meta_df[0].get("is_custom_field")): + return + + custom_field = frappe.get_doc("Custom Field", meta_df[0].name) + changed = False + for property in self.docfield_properties: + if df.get(property) != custom_field.get(property): + if property == "fieldtype": + self.validate_fieldtype_change(df, meta_df[0].get(property), df.get(property)) + + custom_field.set(property, df.get(property)) + changed = True + + if changed: + custom_field.save() + + def delete_custom_fields(self): + meta = frappe.get_meta(self.doc_type) + fields_to_remove = (set([df.fieldname for df in meta.get("fields")]) + - set(df.fieldname for df in self.get("customize_form_fields"))) + + for fieldname in fields_to_remove: + df = meta.get("fields", {"fieldname": fieldname})[0] + if df.get("is_custom_field"): + frappe.delete_doc("Custom Field", df.name) + + def set_idx_property_setter(self): + meta = frappe.get_meta(self.doc_type) + field_order_has_changed = [df.fieldname for df in meta.get("fields")] != \ + [d.fieldname for d in self.get("customize_form_fields")] + + if field_order_has_changed: + _idx = [] + for df in sorted(self.get("customize_form_fields"), key=lambda x: x.idx): + _idx.append(df.fieldname) + + self.make_property_setter(property="_idx", value=json.dumps(_idx), property_type="Text") + + def make_property_setter(self, property, value, property_type, fieldname=None): + self.delete_existing_property_setter(property, fieldname) + + property_value = self.get_existing_property_value(property, fieldname) + + if property_value==value: + return + + # create a new property setter + frappe.make_property_setter({ + "doctype": self.doc_type, + "doctype_or_field": "DocField" if fieldname else "DocType", + "fieldname": fieldname, + "property": property, + "value": value, + "property_type": property_type + }) + + def delete_existing_property_setter(self, property, fieldname=None): + # first delete existing property setter + existing_property_setter = frappe.db.get_value("Property Setter", {"doc_type": self.doc_type, + "property": property, "field_name['']": fieldname or ''}) + + if existing_property_setter: + frappe.delete_doc("Property Setter", existing_property_setter) + + def get_existing_property_value(self, property, fieldname=None): + # check if there is any need to make property setter! + if fieldname: + property_value = frappe.db.get_value("DocField", {"parent": self.doc_type, + "fieldname": fieldname}, property) + else: + try: + property_value = frappe.db.get_value("DocType", self.doc_type, property) + except Exception, e: + if e.args[0]==1054: + property_value = None + else: + raise + + return property_value + + def validate_fieldtype_change(self, df, old_value, new_value): + for allowed_changes in self.allowed_fieldtype_change: + if ((old_value in allowed_changes and new_value in allowed_changes) + or (old_value not in allowed_changes and new_value not in allowed_changes)): + continue + else: + frappe.throw("{row} # {num}, {label}: {msg} {allowed_changes}".format( + row=_("Row"), num=df.idx, label=_(df.label), msg=_("Field Type can be one of"), + allowed_changes=", ".join([_(fieldtype) for fieldtype in allowed_changes]))) def reset_to_defaults(self): if not self.doc_type: @@ -102,208 +239,5 @@ class CustomizeForm(Document): frappe.db.sql("""delete from `tabProperty Setter` where doc_type=%s""", self.doc_type) frappe.clear_cache(doctype=self.doc_type) self.fetch_to_customize() - - def post(self): - """ - Save diff between Customize Form Bean and DocType Bean as property setter entries - """ - if self.doc_type: - from frappe.model import doc - from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype - - this_doclist = self - ref_doclist = frappe.get_meta(self.doc_type) - dt_doclist = frappe.get_doc('DocType', self.doc_type) - - # get a list of property setter docs - self.idx_dirty = False - diff_list = self.diff(this_doclist, ref_doclist, dt_doclist) - - if self.idx_dirty: - self.make_idx_property_setter(this_doclist, diff_list) - - self.set_properties(diff_list) - - validate_fields_for_doctype(self.doc_type) - - frappe.clear_cache(doctype=self.doc_type) - frappe.msgprint("Updated") - - - def diff(self, new_dl, ref_dl, dt_dl): - """ - Get difference between new_dl doclist and ref_dl doclist - then check how it differs from dt_dl i.e. default doclist - """ - import re - self.defaults = self.get_defaults() - diff_list = [] - for new_d in new_dl: - for ref_d in ref_dl: - if ref_d.doctype == 'DocField' and new_d.name == ref_d.name: - for prop in self.docfield_properties: - # do not set forbidden properties like idx - if prop=="idx": - if ref_d.idx != new_d.idx: - self.idx_dirty = True - continue - - # check if its custom field: - if ref_d.get("__custom_field"): - # update custom field - if self.has_property_changed(ref_d, new_d, prop): - # using set_value not doc because validations are called - # in the end anyways - frappe.db.set_value("Custom Field", ref_d.name, prop, new_d.get(prop)) - else: - d = self.prepare_to_set(prop, new_d, ref_d, dt_dl) - if d: diff_list.append(d) - break - - elif ref_d.doctype == 'DocType' and new_d.doctype == 'Customize Form': - for prop in self.doctype_properties: - d = self.prepare_to_set(prop, new_d, ref_d, dt_dl) - if d: diff_list.append(d) - break - - return diff_list - - - def get_defaults(self): - """ - Get fieldtype and default value for properties of a field - """ - df_defaults = frappe.db.sql(""" - SELECT fieldname, fieldtype, `default`, label - FROM `tabDocField` - WHERE parent='DocField' or parent='DocType'""", as_dict=1) - - defaults = {} - for d in df_defaults: - defaults[d['fieldname']] = d - defaults['idx'] = {'fieldname' : 'idx', 'fieldtype' : 'Int', 'default' : 1, 'label' : 'idx'} - defaults['previous_field'] = {'fieldname' : 'previous_field', 'fieldtype' : 'Data', 'default' : None, 'label' : 'Previous Field'} - return defaults - - - def has_property_changed(self, ref_d, new_d, prop): - return new_d.get(prop) != ref_d.get(prop) \ - and not \ - ( \ - new_d.get(prop) in [None, 0] \ - and ref_d.get(prop) in [None, 0] \ - ) and not \ - ( \ - new_d.get(prop) in [None, ''] \ - and ref_d.get(prop) in [None, ''] \ - ) - - def prepare_to_set(self, prop, new_d, ref_d, dt_doclist, delete=0): - """ - Prepares docs of property setter - sets delete property if it is required to be deleted - """ - # Check if property has changed compared to when it was loaded - if self.has_property_changed(ref_d, new_d, prop): - #frappe.msgprint("new: " + str(new_d.get(prop)) + " | old: " + str(ref_d.get(prop))) - # Check if the new property is same as that in original doctype - # If yes, we need to delete the property setter entry - for dt_d in dt_doclist: - if dt_d.name == ref_d.name \ - and (new_d.get(prop) == dt_d.get(prop) \ - or \ - ( \ - new_d.get(prop) in [None, 0] \ - and dt_d.get(prop) in [None, 0] \ - ) or \ - ( \ - new_d.get(prop) in [None, ''] \ - and dt_d.get(prop) in [None, ''] \ - )): - delete = 1 - break - - value = new_d.get(prop) - - if prop in self.property_restrictions: - allow_change = False - for restrict_list in self.property_restrictions.get(prop): - if value in restrict_list and \ - ref_d.get(prop) in restrict_list: - allow_change = True - break - if not allow_change: - frappe.msgprint("""\ - You cannot change '%s' of '%s' from '%s' to '%s'. - %s can only be changed among %s. - Ignoring this change and saving.""" % \ - (self.defaults.get(prop, {}).get("label") or prop, - new_d.get("label") or new_d.get("idx"), - ref_d.get(prop), value, - self.defaults.get(prop, {}).get("label") or prop, - " -or- ".join([", ".join(r) for r in \ - self.property_restrictions.get(prop)])), raise_exception=True) - return None - - # If the above conditions are fulfilled, - # create a property setter doc, but dont save it yet. - d = frappe.get_doc('Property Setter') - d.doctype_or_field = ref_d.doctype=='DocField' and 'DocField' or 'DocType' - d.doc_type = self.doc_type - d.field_name = ref_d.fieldname - d.property = prop - d.value = value - d.property_type = self.defaults[prop]['fieldtype'] - #d.default_value = self.defaults[prop]['default'] - if delete: d.delete = 1 - - if d.select_item: - d.select_item = self.remove_forbidden(d.select_item) - - # return the property setter doc - return d - - else: return None - - - def make_idx_property_setter(self, doclist, diff_list): - fields = [] - doclist.sort(lambda a, b: a.idx < b.idx) - for d in doclist: - if d.doctype=="Customize Form Field": - fields.append(d.fieldname) - - d = frappe.get_doc('Property Setter') - d.doctype_or_field = 'DocType' - d.doc_type = self.doc_type - d.property = "_idx" - d.value = json.dumps(fields) - d.property_type = "Text" - diff_list.append(d) - - def set_properties(self, ps_doclist): - """ - * Delete a property setter entry - + if it already exists - + if marked for deletion - * Save the property setter doc in the list - """ - for d in ps_doclist: - # Delete existing property setter entry - if not d.get("field_name"): - frappe.db.sql(""" - DELETE FROM `tabProperty Setter` - WHERE doc_type = %(doc_type)s - AND property = %(property)s""", d.as_dict()) - else: - frappe.db.sql(""" - DELETE FROM `tabProperty Setter` - WHERE doc_type = %(doc_type)s - AND field_name = %(field_name)s - AND property = %(property)s""", d.as_dict()) - - # Save the property setter doc if not marked for deletion i.e. delete=0 - if not d.delete: - d.insert() \ No newline at end of file diff --git a/frappe/core/doctype/customize_form/test_customize_form.py b/frappe/core/doctype/customize_form/test_customize_form.py new file mode 100644 index 0000000000..32f5ee0380 --- /dev/null +++ b/frappe/core/doctype/customize_form/test_customize_form.py @@ -0,0 +1,145 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# MIT License. See license.txt + +from __future__ import unicode_literals +import frappe, unittest, json +from frappe.test_runner import make_test_records_for_doctype + +test_dependencies = ["Custom Field", "Property Setter"] +class TestCustomizeForm(unittest.TestCase): + def setUp(self): + frappe.clear_cache(doctype="User") + + def tearDown(self): + frappe.clear_cache(doctype="User") + + def get_customize_form(self, doctype=None): + d = frappe.get_doc("Customize Form") + if doctype: + d.doc_type = doctype + d.run_method("fetch_to_customize") + return d + + def test_fetch_to_customize(self): + d = self.get_customize_form() + self.assertEquals(d.doc_type, None) + self.assertEquals(len(d.get("customize_form_fields")), 0) + + d = self.get_customize_form("Event") + self.assertEquals(d.doc_type, "Event") + self.assertEquals(len(d.get("customize_form_fields")), 30) + + d = self.get_customize_form("User") + self.assertEquals(d.doc_type, "User") + self.assertEquals(len(d.get("customize_form_fields")), 53) + self.assertEquals(d.get("customize_form_fields")[-1].fieldname, "test_custom_field") + self.assertEquals(d.get("customize_form_fields", {"fieldname": "location"})[0].in_list_view, 1) + + return d + + def test_save_customization_idx(self): + d = self.get_customize_form("User") + original_sequence = [df.fieldname for df in d.get("customize_form_fields")] + + # move field to last + location_field = d.get("customize_form_fields", {"fieldname": "location"})[0] + d.get("customize_form_fields").remove(location_field) + d.append("customize_form_fields", location_field) + d.run_method("save_customization") + frappe.clear_cache(doctype=d.doc_type) + + property_setter_name, _idx = frappe.db.get_value("Property Setter", + {"doc_type": d.doc_type, "property": "_idx"}, ("name", "value")) + self.assertTrue(_idx) + + _idx = json.loads(_idx) + for i, df in enumerate(frappe.get_meta(d.doc_type).get("fields")): + self.assertEquals(_idx[i], df.fieldname) + + frappe.delete_doc("Property Setter", property_setter_name) + frappe.clear_cache(doctype=d.doc_type) + + for i, df in enumerate(frappe.get_meta(d.doc_type).get("fields")): + self.assertEquals(original_sequence[i], df.fieldname) + + def test_save_customization_property(self): + d = self.get_customize_form("User") + self.assertEquals(frappe.db.get_value("Property Setter", + {"doc_type": "User", "property": "allow_copy"}, "value"), None) + + d.allow_copy = 1 + d.run_method("save_customization") + self.assertEquals(frappe.db.get_value("Property Setter", + {"doc_type": "User", "property": "allow_copy"}, "value"), '1') + + d.allow_copy = 0 + d.run_method("save_customization") + self.assertEquals(frappe.db.get_value("Property Setter", + {"doc_type": "User", "property": "allow_copy"}, "value"), None) + + def test_save_customization_field_property(self): + d = self.get_customize_form("User") + self.assertEquals(frappe.db.get_value("Property Setter", + {"doc_type": "User", "property": "reqd", "field_name": "location"}, "value"), None) + + location_field = d.get("customize_form_fields", {"fieldname": "location"})[0] + location_field.reqd = 1 + d.run_method("save_customization") + self.assertEquals(frappe.db.get_value("Property Setter", + {"doc_type": "User", "property": "reqd", "field_name": "location"}, "value"), '1') + + location_field = d.get("customize_form_fields", {"fieldname": "location"})[0] + location_field.reqd = 0 + d.run_method("save_customization") + self.assertEquals(frappe.db.get_value("Property Setter", + {"doc_type": "User", "property": "reqd", "field_name": "location"}, "value"), '0') + + def test_save_customization_custom_field_property(self): + d = self.get_customize_form("User") + self.assertEquals(frappe.db.get_value("Custom Field", "User-test_custom_field", "reqd"), None) + + custom_field = d.get("customize_form_fields", {"fieldname": "test_custom_field"})[0] + custom_field.reqd = 1 + d.run_method("save_customization") + self.assertEquals(frappe.db.get_value("Custom Field", "User-test_custom_field", "reqd"), 1) + + custom_field = d.get("customize_form_fields", {"is_custom_field": True})[0] + custom_field.reqd = 0 + d.run_method("save_customization") + self.assertEquals(frappe.db.get_value("Custom Field", "User-test_custom_field", "reqd"), 0) + + def test_save_customization_new_field(self): + d = self.get_customize_form("User") + d.append("customize_form_fields", { + "label": "Test Add Custom Field Via Customize Form", + "fieldtype": "Data", + "__islocal": 1 + }) + d.run_method("save_customization") + self.assertEquals(frappe.db.get_value("Custom Field", + "User-test_add_custom_field_via_customize_form", "fieldtype"), "Data") + + frappe.delete_doc("Custom Field", "User-test_add_custom_field_via_customize_form") + self.assertEquals(frappe.db.get_value("Custom Field", + "User-test_add_custom_field_via_customize_form"), None) + + def test_save_customization_remove_field(self): + d = self.get_customize_form("User") + custom_field = d.get("customize_form_fields", {"fieldname": "test_custom_field"})[0] + d.get("customize_form_fields").remove(custom_field) + d.run_method("save_customization") + + self.assertEquals(frappe.db.get_value("Custom Field", custom_field.name), None) + + frappe.local.test_objects["Custom Field"] = [] + make_test_records_for_doctype("Custom Field") + + def test_reset_to_defaults(self): + d = frappe.get_doc("Customize Form") + d.doc_type = "User" + d.run_method('reset_to_defaults') + + self.assertEquals(d.get("customize_form_fields", {"fieldname": "location"})[0].in_list_view, None) + + frappe.local.test_objects["Property Setter"] = [] + make_test_records_for_doctype("Property Setter") diff --git a/frappe/core/doctype/property_setter/property_setter.json b/frappe/core/doctype/property_setter/property_setter.json index e3322f198d..3606bc325a 100644 --- a/frappe/core/doctype/property_setter/property_setter.json +++ b/frappe/core/doctype/property_setter/property_setter.json @@ -45,7 +45,7 @@ "label": "DocType", "options": "DocType", "permlevel": 0, - "reqd": 0, + "reqd": 1, "search_index": 1 }, { diff --git a/frappe/core/doctype/property_setter/test_records.json b/frappe/core/doctype/property_setter/test_records.json new file mode 100644 index 0000000000..3c084b424e --- /dev/null +++ b/frappe/core/doctype/property_setter/test_records.json @@ -0,0 +1,10 @@ +[ + { + "doc_type": "User", + "doctype_or_field": "DocField", + "field_name": "location", + "property": "in_list_view", + "property_type": "Check", + "value": "1" + } +] \ No newline at end of file diff --git a/frappe/model/meta.py b/frappe/model/meta.py index 512fa31336..67122247cc 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -23,6 +23,7 @@ class Meta(Document): _metaclass = True default_fields = default_fields[1:] special_doctypes = ("DocField", "DocPerm", "Role", "DocType", "Module Def") + def __init__(self, doctype): self._fields = {} super(Meta, self).__init__("DocType", doctype) @@ -98,7 +99,8 @@ class Meta(Document): def add_custom_fields(self): try: self.extend("fields", frappe.db.sql("""SELECT * FROM `tabCustom Field` - WHERE dt = %s AND docstatus < 2""", (self.name,), as_dict=1)) + WHERE dt = %s AND docstatus < 2""", (self.name,), as_dict=1, + update={"is_custom_field": True})) except Exception, e: if e.args[0]==1146: return diff --git a/frappe/test_runner.py b/frappe/test_runner.py index e3f3ca80c9..79aecc4bb9 100644 --- a/frappe/test_runner.py +++ b/frappe/test_runner.py @@ -133,8 +133,14 @@ def make_test_records_for_doctype(doctype, verbose=0): elif hasattr(test_module, "test_records"): frappe.local.test_objects[doctype] += make_test_objects(doctype, test_module.test_records, verbose) - elif verbose: - print_mandatory_fields(doctype) + + else: + test_records = frappe.get_test_records(doctype) + if test_records: + frappe.local.test_objects[doctype] += make_test_objects(doctype, test_records, verbose) + + elif verbose: + print_mandatory_fields(doctype) def make_test_objects(doctype, test_records, verbose=None):