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):