diff --git a/core/doctype/custom_field/custom_field.py b/core/doctype/custom_field/custom_field.py
index d158da9b31..526deb66e5 100644
--- a/core/doctype/custom_field/custom_field.py
+++ b/core/doctype/custom_field/custom_field.py
@@ -24,44 +24,25 @@
from __future__ import unicode_literals
import webnotes
-from webnotes.utils import cint, cstr, flt, formatdate, now
+from webnotes.utils import cint, cstr
from webnotes.model.doc import Document
-from webnotes import msgprint, errprint
+from webnotes import msgprint
-
-# -----------------------------------------------------------------------------------------
class DocType:
def __init__(self, d, dl):
self.doc, self.doclist = d, dl
-# *************************** Validate *******************************
def set_fieldname(self):
if not self.doc.fieldname:
# remove special characters from fieldname
self.doc.fieldname = filter(lambda x: x.isdigit() or x.isalpha() or '_', cstr(self.doc.label).lower().replace(' ','_'))
-
- def validate_field(self, doctype_doclist):
- exists = any(d for d in doctype_doclist if d.doctype == 'DocField' and
- (d.fields.get('label') == self.doc.label or
- d.fields.get('fieldname') == self.doc.fieldname))
- if self.doc.fields.get('__islocal') and exists:
- msgprint("%s field already exists in Document : %s" % (self.doc.label, self.doc.dt))
- raise Exception
-
- if self.doc.fieldtype=='Link' and self.doc.options:
- if not webnotes.conn.sql("select name from tabDocType where name=%s", self.doc.options):
- msgprint("%s is not a valid Document" % self.doc.options)
- raise Exception
-
def validate(self):
+ from webnotes.model.doctype import get
self.set_fieldname()
- from webnotes.model.doctype import get
temp_doclist = get(self.doc.dt, form=0)
-
- self.validate_field(temp_doclist)
-
+
# set idx
if not self.doc.idx:
from webnotes.utils import cint
@@ -69,6 +50,14 @@ class DocType:
self.doc.idx = cint(max_idx) + 1
def on_update(self):
+ # validate field
+ from webnotes.utils.cache import CacheItem
+ from core.doctype.doctype.doctype import validate_fields_for_doctype
+
+ validate_fields_for_doctype(self.doc.dt)
+
+ CacheItem(self.doc.dt).clear()
+
# update the schema
from webnotes.model.db_schema import updatedb
updatedb(self.doc.dt)
@@ -76,9 +65,6 @@ class DocType:
# create property setter to emulate insert after
self.create_property_setter()
- from webnotes.utils.cache import CacheItem
- CacheItem(self.doc.dt).clear()
-
def on_trash(self):
# delete property setter entries
webnotes.conn.sql("""\
@@ -102,17 +88,18 @@ class DocType:
WHERE doc_type = %s
AND field_name = %s
AND property = 'previous_field'""", (self.doc.dt, self.doc.fieldname))
- ps = Document('Property Setter', fielddata = {
+
+ webnotes.model_wrapper([{
+ 'doctype': "Property Setter",
'doctype_or_field': 'DocField',
'doc_type': self.doc.dt,
'field_name': self.doc.fieldname,
'property': 'previous_field',
'value': prev_field,
'property_type': 'Data',
- 'select_doctype': self.doc.dt
- })
- ps.save(1)
-
+ 'select_doctype': self.doc.dt,
+ '__islocal': 1
+ }]).save()
@webnotes.whitelist()
def get_fields_label(dt=None, form=1):
diff --git a/core/doctype/customize_form/customize_form.js b/core/doctype/customize_form/customize_form.js
index 2fa24b44fb..18530a71b2 100644
--- a/core/doctype/customize_form/customize_form.js
+++ b/core/doctype/customize_form/customize_form.js
@@ -38,7 +38,7 @@ cur_frm.cscript.refresh = function(doc, dt, dn) {
if(cur_frm.fields_dict['doc_type'].value) {
$c_obj(make_doclist(dt, dn), 'post', '', function(r, rt) {
if(r.exc) {
- msgprint(r.exc);
+ //msgprint(r.exc);
} else {
if(r.server_messages) { cur_frm.cscript.doc_type(doc, doc.doctype, doc.name); }
cur_frm.frm_head.set_label(['Saved', 'label-success']);
diff --git a/core/doctype/customize_form/customize_form.py b/core/doctype/customize_form/customize_form.py
index 36770830ec..95f4d6f651 100644
--- a/core/doctype/customize_form/customize_form.py
+++ b/core/doctype/customize_form/customize_form.py
@@ -144,6 +144,7 @@ class DocType:
if self.doc.doc_type:
from webnotes.model import doc
from webnotes.model.doctype import get
+ from core.doctype.doctype.doctype import validate_fields_for_doctype
this_doclist = [self.doc] + self.doclist
ref_doclist = self.get_ref_doclist()
@@ -154,6 +155,8 @@ class DocType:
self.set_properties(diff_list)
+ validate_fields_for_doctype(self.doc.doc_type)
+
from webnotes.utils.cache import CacheItem
CacheItem(self.doc.doc_type).clear()
CacheItem('tags-' + self.doc.doc_type).clear()
diff --git a/core/doctype/doctype/doctype.py b/core/doctype/doctype/doctype.py
index e84b7fc076..32c5df1bf3 100644
--- a/core/doctype/doctype/doctype.py
+++ b/core/doctype/doctype/doctype.py
@@ -68,40 +68,10 @@ class DocType:
if used_in:
msgprint('Series already in use: The series "%s" is already used in "%s"' % (prefix, used_in[0][0]), raise_exception=1)
- #
- # field validations
- #
- def validate_fields(self):
- "validates fields for incorrect properties and double entries"
- fieldnames = {}
- illegal = ['.', ',', ' ', '-', '&', '%', '=', '"', "'", '*', '$']
- for d in self.doclist:
- if not d.permlevel: d.permlevel = 0
- if d.parent and d.fieldtype and d.parent == self.doc.name:
- # check if not double
- if d.fieldname:
- if fieldnames.get(d.fieldname):
- webnotes.msgprint('Fieldname %s appears twice (rows %s and %s). Please rectify' \
- % (d.fieldname, str(d.idx + 1), str(fieldnames[d.fieldname] + 1)), raise_exception=1)
- fieldnames[d.fieldname] = d.idx
-
- # check bad characters
- for c in illegal:
- if c in d.fieldname:
- webnotes.msgprint('"%s" not allowed in fieldname' % c)
-
- else:
- webnotes.msgprint("Fieldname is mandatory in row %s" % str(d.idx+1), raise_exception=1)
-
- # check illegal mandatory
- if d.fieldtype in ('HTML', 'Button', 'Section Break', 'Column Break') and d.reqd:
- webnotes.msgprint('%(lable)s [%(fieldtype)s] cannot be mandatory', raise_exception=1)
-
-
def validate(self):
self.validate_series()
self.scrub_field_names()
- self.validate_fields()
+ validate_fields(filter(lambda d: d.doctype=="DocField", self.doclist))
self.set_version()
def on_update(self):
@@ -194,4 +164,42 @@ class DocType:
new.save()
max_idx += 1
+def validate_fields_for_doctype(doctype):
+ from webnotes.model.doctype import get
+ validate_fields(filter(lambda d: d.doctype=="DocField" and d.parent==doctype,
+ get(doctype)))
+def validate_fields(fields):
+ def check_illegal_characters(fieldname):
+ for c in ['.', ',', ' ', '-', '&', '%', '=', '"', "'", '*', '$',
+ '(', ')', '[', ']']:
+ if c in fieldname:
+ webnotes.msgprint("'%s' not allowed in fieldname (%s)" % (c, fieldname))
+
+ def check_unique_fieldname(fieldname):
+ duplicates = filter(None, map(lambda df: df.fieldname==fieldname and str(df.idx) or None, fields))
+ if len(duplicates) > 1:
+ webnotes.msgprint('Fieldname %s appears more than once in rows (%s). Please rectify' \
+ % (fieldname, ', '.join(duplicates)), raise_exception=1)
+
+ def check_illegal_mandatory(d):
+ if d.fieldtype in ('HTML', 'Button', 'Section Break', 'Column Break') and d.reqd:
+ webnotes.msgprint('%(label)s [%(fieldtype)s] cannot be mandatory' % d.fields,
+ raise_exception=1)
+
+ def check_link_table_options(d):
+ if d.fieldtype in ("Link", "Table"):
+ if not d.options:
+ webnotes.msgprint("""#%(idx)s %(label)s: Options must be specified for Link and Table type fields""" % d.fields, raise_exception=1)
+ if not webnotes.conn.exists("DocType", d.options):
+ webnotes.msgprint("""#%(idx)s %(label)s: Options %(options)s must be a valid "DocType" for Link and Table type fields""" % d.fields, raise_exception=1)
+
+ for d in fields:
+ if not d.permlevel: d.permlevel = 0
+ if not d.fieldname:
+ webnotes.msgprint("Fieldname is mandatory in row %s" % d.idx, raise_exception=1)
+ check_illegal_characters(d.fieldname)
+ check_unique_fieldname(d.fieldname)
+ check_illegal_mandatory(d)
+ check_link_table_options(d)
+
\ No newline at end of file
diff --git a/core/doctype/property_setter/property_setter.py b/core/doctype/property_setter/property_setter.py
index 3f6c3fa3b2..c4e67e83bd 100644
--- a/core/doctype/property_setter/property_setter.py
+++ b/core/doctype/property_setter/property_setter.py
@@ -50,4 +50,8 @@ class DocType:
return webnotes.conn.sql("select * from `tabDocType` where name=%s", self.doc.doc_type, as_dict = 1)[0]
else:
return webnotes.conn.sql("select * from `tabDocField` where fieldname=%s and parent=%s",
- (self.doc.field_name, self.doc.doc_type), as_dict = 1)[0]
\ No newline at end of file
+ (self.doc.field_name, self.doc.doc_type), as_dict = 1)[0]
+
+ def on_update(self):
+ from core.doctype.doctype.doctype import validate_fields_for_doctype
+ validate_fields_for_doctype(self.doc.doc_type)
\ No newline at end of file
diff --git a/webnotes/__init__.py b/webnotes/__init__.py
index 335d4aa649..a6d5accfd9 100644
--- a/webnotes/__init__.py
+++ b/webnotes/__init__.py
@@ -260,3 +260,7 @@ def generate_hash():
"""Generates random hash for session id"""
import hashlib, time
return hashlib.sha224(str(time.time())).hexdigest()
+
+def model_wrapper(doctype, name=None):
+ from webnotes.model.doclist import DocList
+ return DocList(doctype, name)
\ No newline at end of file
diff --git a/webnotes/model/doctype.py b/webnotes/model/doctype.py
index 509a2da172..bcc3fc73d6 100644
--- a/webnotes/model/doctype.py
+++ b/webnotes/model/doctype.py
@@ -37,17 +37,16 @@ class _DocType:
def __init__(self, name):
self.name = name
- def make_doclist(self, form=1):
+ def make_doclist(self, form=1, force=False):
"""
"""
# do not load from cache if auto cache clear is enabled
import conf
- from_cache = True
if hasattr(conf, 'auto_cache_clear'):
- from_cache = not conf.auto_cache_clear
+ force = not conf.auto_cache_clear
- if form and from_cache:
+ if form and not force:
cached_doclist = self.load_from_cache()
if cached_doclist: return cached_doclist
@@ -371,13 +370,13 @@ class _DocType:
json_doclist = json.dumps([d.fields for d in doclist])
CacheItem(self.name).set(json_doclist)
-def get(dt, form=1):
+def get(dt, form=1, force=False):
"""
Load "DocType" - called by form builder, report buider and from code.py (when there is no cache)
"""
if not dt: return []
- doclist = _DocType(dt).make_doclist(form)
+ doclist = _DocType(dt).make_doclist(form, force)
return doclist
# Deprecate after import_docs rewrite