@@ -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): | |||
@@ -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']); | |||
@@ -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() | |||
@@ -68,40 +68,10 @@ class DocType: | |||
if used_in: | |||
msgprint('<b>Series already in use:</b> 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 <b>%s</b> 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 <b>%s</b> 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) | |||
@@ -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] | |||
(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) |
@@ -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) |
@@ -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 | |||