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