소스 검색

fixes to doctype save

version-14
Rushabh Mehta 11 년 전
부모
커밋
ecce41e97b
6개의 변경된 파일325개의 추가작업 그리고 180개의 파일을 삭제
  1. +70
    -62
      frappe/core/doctype/doctype/doctype.py
  2. +118
    -4
      frappe/core/doctype/module_def/module_def.json
  3. +22
    -2
      frappe/core/doctype/module_def/module_def.py
  4. +50
    -48
      frappe/model/base_document.py
  5. +37
    -37
      frappe/model/meta.py
  6. +28
    -27
      frappe/public/js/frappe/model/create_new.js

+ 70
- 62
frappe/core/doctype/doctype/doctype.py 파일 보기

@@ -1,5 +1,5 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt
# MIT License. See license.txt

from __future__ import unicode_literals

@@ -18,6 +18,8 @@ class DocType(Document):
for c in [".", "/", "#", "&", "=", ":", "'", '"']:
if c in self.name:
frappe.msgprint(c + " not allowed in name", raise_exception=1)
for d in self.get("fields"):
d.parent = self.name
self.validate_series()
self.scrub_field_names()
self.validate_title_field()
@@ -29,7 +31,7 @@ class DocType(Document):
def change_modified_of_parent(self):
if frappe.flags.in_import:
return
parent_list = frappe.db.sql("""SELECT parent
parent_list = frappe.db.sql("""SELECT parent
from tabDocField where fieldtype="Table" and options=%s""", self.name)
for p in parent_list:
frappe.db.sql('UPDATE tabDocType SET modified=%s WHERE `name`=%s', (now(), p[0]))
@@ -38,28 +40,28 @@ class DocType(Document):
restricted = ('name','parent','idx','owner','creation','modified','modified_by',
'parentfield','parenttype',"file_list")
for d in self.get("fields"):
if d.parent and d.fieldtype:
if (not d.fieldname):
if d.fieldtype:
if (not getattr(d, "fieldname", None)):
if d.label:
d.fieldname = d.label.strip().lower().replace(' ','_')
if d.fieldname in restricted:
d.fieldname = d.fieldname + '1'
else:
d.fieldname = d.fieldtype.lower().replace(" ","_") + "_" + str(d.idx)
def validate_title_field(self):
if self.title_field and \
self.title_field not in [d.fieldname for d in self.get("fields")]:
frappe.throw(_("Title field must be a valid fieldname"))
def validate_series(self, autoname=None, name=None):
if not autoname: autoname = self.autoname
if not name: name = self.name
if not autoname and self.get("fields", {"fieldname":"naming_series"}):
self.autoname = "naming_series:"
if autoname and (not autoname.startswith('field:')) and (not autoname.startswith('eval:')) \
and (not autoname=='Prompt') and (not autoname.startswith('naming_series:')):
prefix = autoname.split('.')[0]
@@ -73,12 +75,12 @@ class DocType(Document):

self.change_modified_of_parent()
make_module_and_roles(self)
from frappe import conf
if (not frappe.flags.in_import) and conf.get('developer_mode') or 0:
self.export_doc()
self.make_controller_template()
# update index
if not getattr(self, "custom", False):
from frappe.modules import load_doctype_module
@@ -99,29 +101,29 @@ class DocType(Document):
frappe.db.sql("delete from `tabCustom Script` where dt = %s", self.name)
frappe.db.sql("delete from `tabProperty Setter` where doc_type = %s", self.name)
frappe.db.sql("delete from `tabReport` where ref_doctype=%s", self.name)
def before_rename(self, old, new, merge=False):
if merge:
frappe.throw(_("DocType can not be merged"))
def after_rename(self, old, new, merge=False):
if self.issingle:
frappe.db.sql("""update tabSingles set doctype=%s where doctype=%s""", (new, old))
else:
frappe.db.sql("rename table `tab%s` to `tab%s`" % (old, new))
def export_doc(self):
from frappe.modules.export_file import export_to_files
export_to_files(record_list=[['DocType', self.name]])
def import_doc(self):
from frappe.modules.import_module import import_from_files
import_from_files(record_list=[[self.module, 'doctype', self.name]])
import_from_files(record_list=[[self.module, 'doctype', self.name]])

def make_controller_template(self):
from frappe.modules import get_doc_path, get_module_path, scrub
pypath = os.path.join(get_doc_path(self.module,
pypath = os.path.join(get_doc_path(self.module,
self.doctype, self.name), scrub(self.name) + '.py')

if not os.path.exists(pypath):
@@ -130,18 +132,18 @@ class DocType(Document):
if not app:
frappe.throw("App not found!")
app_publisher = frappe.get_hooks(hook="app_publisher", app_name=app)[0]
with open(pypath, 'w') as pyfile:
with open(os.path.join(get_module_path("core"), "doctype", "doctype",
with open(os.path.join(get_module_path("core"), "doctype", "doctype",
"doctype_template.py"), 'r') as srcfile:
pyfile.write(srcfile.read().format(app_publisher=app_publisher, classname=self.name.replace(" ", "")))
def make_amendable(self):
"""
if is_submittable is set, add amended_from docfields
"""
if self.is_submittable:
if not frappe.db.sql("""select name from tabDocField
if not frappe.db.sql("""select name from tabDocField
where fieldname = 'amended_from' and parent = %s""", self.name):
self.append("fields", {
"label": "Amended From",
@@ -152,43 +154,43 @@ class DocType(Document):
"print_hide": 1,
"no_copy": 1
})
def get_max_idx(self):
max_idx = frappe.db.sql("""select max(idx) from `tabDocField` where parent = %s""",
max_idx = frappe.db.sql("""select max(idx) from `tabDocField` where parent = %s""",
self.name)
return max_idx and max_idx[0][0] or 0

def validate_fields_for_doctype(doctype):
validate_fields(frappe.get_meta(doctype).get("fields"))
def validate_fields(fields):
def check_illegal_characters(fieldname):
for c in ['.', ',', ' ', '-', '&', '%', '=', '"', "'", '*', '$',
for c in ['.', ',', ' ', '-', '&', '%', '=', '"', "'", '*', '$',
'(', ')', '[', ']', '/']:
if c in fieldname:
frappe.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:
frappe.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:
print d.fieldname, d.reqd
frappe.msgprint('%(parent)s, %(label)s [%(fieldtype)s] cannot be mandatory' % d.as_dict(),
frappe.msgprint('%(parent)s, %(label)s [%(fieldtype)s] cannot be mandatory' % d.as_dict(),
raise_exception=1)
def check_link_table_options(d):
if d.fieldtype in ("Link", "Table"):
if not d.options:
frappe.msgprint("""#%(idx)s %(label)s: Options must be specified for Link and Table type fields""" % d.as_dict(),
frappe.msgprint("""#%(idx)s %(label)s: Options must be specified for Link and Table type fields""" % d.as_dict(),
raise_exception=1)
if d.options=="[Select]":
if d.options=="[Select]" or d.options==d.parent:
return
if d.options != d.parent and not frappe.db.exists("DocType", d.options):
frappe.msgprint("""#%(idx)s %(label)s: Options %(options)s must be a valid "DocType" for Link and Table type fields""" % d.as_dict(),
frappe.msgprint("""#%(idx)s %(label)s: Options %(options)s must be a valid "DocType" for Link and Table type fields""" % d.as_dict(),
raise_exception=1)

def check_hidden_and_mandatory(d):
@@ -200,7 +202,7 @@ def validate_fields(fields):
if len(filter(lambda d: d.in_list_view, fields))==0:
for d in fields[:5]:
d.in_list_view = 1
def check_width(d):
if d.fieldtype == "Currency" and cint(d.width) < 100:
frappe.msgprint("Minimum width for FieldType 'Currency' is 100px", raise_exception=1)
@@ -224,46 +226,52 @@ def validate_fields(fields):

def validate_permissions_for_doctype(doctype, for_remove=False):
validate_permissions(frappe.get_meta(doctype, cached=False).get("permissions"), for_remove)
def validate_permissions(permissions, for_remove=False):
doctype = permissions and permissions[0].parent
issingle = issubmittable = isimportable = False
if doctype and not doctype.startswith("New DocType"):
values = frappe.db.get_value("DocType", doctype,
["issingle", "is_submittable", "allow_import"], as_dict=True)
values = frappe.db.get_value("DocType", doctype,
["issingle", "is_submittable", "allow_import"], as_dict=True)
if values:
issingle = cint(values.issingle)
issubmittable = cint(values.is_submittable)
isimportable = cint(values.allow_import)

def get_txt(d):
return "For %s (level %s) in %s, row #%s:" % (d.role, d.permlevel, d.parent, d.idx)
def check_atleast_one_set(d):
if not d.read and not d.write and not d.submit and not d.cancel and not d.create:
frappe.msgprint(get_txt(d) + " Atleast one of Read, Write, Create, Submit, Cancel must be set.",
raise_exception=True)
def check_double(d):
similar = permissions.get({
"role":d.role,
"permlevel":d.permlevel,
"match": d.match
})
if len(similar) > 1:
frappe.msgprint(get_txt(d) + " Only one rule allowed for a particular Role and Level.",
has_similar = False
for p in permissions:
if p.role==d.role and p.permlevel==d.permlevel and p.match==d.match and p!=d:
has_similar = True
break
if has_similar:
frappe.msgprint(get_txt(d) + " Only one rule allowed for a particular Role and Level.",
raise_exception=True)
def check_level_zero_is_set(d):
if cint(d.permlevel) > 0 and d.role != 'All':
if not permissions.get({"role": d.role, "permlevel": 0}):
has_zero_perm = False
for p in permissions:
if p.role==d.role and (p.permlevel or 0)==0 and p!=d:
has_zero_perm = True
break

if not has_zero_perm:
frappe.msgprint(get_txt(d) + " Higher level permissions are meaningless if level 0 permission is not set.",
raise_exception=True)
if d.create or d.submit or d.cancel or d.amend or d.match:
if d.create or d.submit or d.cancel or d.amend or d.match:
frappe.msgprint("Create, Submit, Cancel, Amend, Match has no meaning at level " + d.permlevel,
raise_exception=True)
def check_permission_dependency(d):
if d.cancel and not d.submit:
frappe.msgprint(get_txt(d) + " Cannot set Cancel permission if Submit is not set.",
@@ -280,23 +288,23 @@ def validate_permissions(permissions, for_remove=False):
if d.get("import") and not d.create:
frappe.msgprint(get_txt(d) + " Cannot set Import if Create is not set.",
raise_exception=True)
def remove_rights_for_single(d):
if not issingle:
return
if d.report:
frappe.msgprint("{doctype} {meaningless}".format(doctype=doctype,
meaningless=_("is a single DocType, permission of type Report is meaningless.")))
d.report = 0
d.set("import", 0)
d.set("export", 0)
if d.restrict:
frappe.msgprint("{doctype} {meaningless}".format(doctype=doctype,
meaningless=_("is a single DocType, permission of type Restrict is meaningless.")))
d.restrict = 0
def check_if_submittable(d):
if d.submit and not issubmittable:
frappe.msgprint(doctype + " is not Submittable, cannot assign submit rights.",
@@ -304,14 +312,14 @@ def validate_permissions(permissions, for_remove=False):
elif d.amend and not issubmittable:
frappe.msgprint(doctype + " is not Submittable, cannot assign amend rights.",
raise_exception=True)
def check_if_importable(d):
if d.get("import") and not isimportable:
frappe.throw("{doctype}: {not_importable}".format(doctype=doctype,
not_importable=_("is not allowed to be imported, cannot assign import rights.")))
for d in permissions:
if not d.permlevel:
if not d.permlevel:
d.permlevel=0
check_atleast_one_set(d)
if not for_remove:
@@ -328,10 +336,10 @@ def make_module_and_roles(doc, perm_fieldname="permissions"):
m = frappe.get_doc({"doctype": "Module Def", "module_name": doc.module})
m.ignore_mandatory = m.ignore_permissions = True
m.insert()
default_roles = ["Administrator", "Guest", "All"]
roles = [p.role for p in doc.get("permissions") or []] + default_roles
for role in list(set(roles)):
if not frappe.db.exists("Role", role):
r = frappe.get_doc({"doctype": "Role", "role_name": role})


+ 118
- 4
frappe/core/doctype/module_def/module_def.json 파일 보기

@@ -1,26 +1,107 @@
{
"_last_update": null,
"_user_tags": null,
"allow_attach": null,
"allow_copy": null,
"allow_email": null,
"allow_import": null,
"allow_print": null,
"allow_rename": 1,
"allow_trash": null,
"autoname": "field:module_name",
"creation": "2013-01-10 16:34:03.000000",
"change_log": null,
"client_script": null,
"client_script_core": null,
"client_string": null,
"colour": null,
"creation": "2013-01-10 16:34:03",
"custom": null,
"default_print_format": null,
"description": null,
"docstatus": 0,
"doctype": "DocType",
"document_type": null,
"dt_template": null,
"fields": [
{
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "module_name",
"fieldtype": "Data",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": 1,
"label": "Module Name",
"no_column": null,
"no_copy": null,
"oldfieldname": "module_name",
"oldfieldtype": "Data",
"permlevel": 0
"options": null,
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
},
{
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "app_name",
"fieldtype": "Data",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": 1,
"label": "App Name",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": null,
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": 1,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
}
],
"hide_heading": null,
"hide_toolbar": null,
"icon": "icon-sitemap",
"idx": 1,
"modified": "2014-02-18 15:32:49.000000",
"in_create": null,
"in_dialog": null,
"is_submittable": null,
"is_transaction_doc": null,
"issingle": null,
"istable": null,
"max_attachments": null,
"menu_index": null,
"modified": "2014-04-07 12:47:20.781686",
"modified_by": "Administrator",
"module": "Core",
"name": "Module Def",
"name_case": null,
"owner": "Administrator",
"parent": null,
"parent_node": null,
"parentfield": null,
"parenttype": null,
"permissions": [
{
"amend": 0,
@@ -28,21 +109,54 @@
"create": 1,
"delete": 1,
"email": 1,
"export": null,
"import": null,
"match": null,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"restrict": null,
"restricted": null,
"role": "Administrator",
"submit": 0,
"write": 1
},
{
"amend": null,
"cancel": null,
"create": 1,
"delete": 1,
"email": null,
"export": null,
"import": null,
"match": null,
"permlevel": 0,
"print": null,
"read": 1,
"report": null,
"restrict": null,
"restricted": null,
"role": "System Manager",
"submit": null,
"write": 1
}
]
],
"plugin": null,
"print_outline": null,
"read_only": null,
"read_only_onload": null,
"search_fields": null,
"section_style": null,
"server_code": null,
"server_code_compiled": null,
"server_code_core": null,
"server_code_error": null,
"show_in_menu": null,
"smallicon": null,
"subject": null,
"tag_fields": null,
"title_field": null,
"use_template": null,
"version": null
}

+ 22
- 2
frappe/core/doctype/module_def/module_def.py 파일 보기

@@ -2,9 +2,29 @@
# MIT License. See license.txt

from __future__ import unicode_literals
import frappe
import frappe, os

from frappe.model.document import Document

class ModuleDef(Document):
pass
def validate(self):
if not frappe.local.module_app.get(self.name):
with open(frappe.get_app_path(self.app_name, "modules.txt"), "r") as f:
content = f.read()
if not frappe.scrub(self.name) in content.splitlines():
content += "\n" + frappe.scrub(self.name)

with open(frappe.get_app_path(self.app_name, "modules.txt"), "w") as f:
f.write(content)

frappe.clear_cache()
frappe.setup_module_map()

module_path = frappe.get_app_path(self.app_name, self.name)
if not os.path.exists(module_path):
os.mkdir(module_path)
with open(os.path.join(module_path, "__init__.py"), "w") as f:
f.write("")




+ 50
- 48
frappe/model/base_document.py 파일 보기

@@ -1,5 +1,5 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt
# MIT License. See license.txt

from __future__ import unicode_literals
import frappe
@@ -10,7 +10,7 @@ from frappe.model.naming import set_new_name

class BaseDocument(object):
ignore_in_getter = ("doctype", "_meta", "meta", "_table_fields", "_valid_columns")
def __init__(self, d):
self.update(d)

@@ -18,7 +18,7 @@ class BaseDocument(object):
def meta(self):
if not hasattr(self, "_meta"):
self._meta = frappe.get_meta(self.doctype)
return self._meta

def update(self, d):
@@ -26,17 +26,17 @@ class BaseDocument(object):
self.set("doctype", d.get("doctype"))
for key, value in d.iteritems():
self.set(key, value)
def update_if_missing(self, d):
if isinstance(d, BaseDocument):
d = d.get_valid_dict()
if "doctype" in d:
self.set("doctype", d.get("doctype"))
for key, value in d.iteritems():
if self.get(key) is None:
self.set(key, value)
def get_db_value(self, key):
return frappe.db.get_value(self.doctype, self.name, key)

@@ -53,26 +53,26 @@ class BaseDocument(object):
value = self.__dict__.get(key, default)
else:
value = self.__dict__.get(key, default)
if value is None and key not in self.ignore_in_getter \
and key in (d.fieldname for d in self.meta.get_table_fields()):
self.set(key, [])
value = self.__dict__.get(key)
return value
else:
return self.__dict__

def getone(self, key, filters=None):
return self.get(key, filters=filters, limit=1)[0]
def set(self, key, value):
if isinstance(value, list):
self.__dict__[key] = []
self.extend(key, value)
else:
self.__dict__[key] = value
def append(self, key, value=None):
if value==None:
value={}
@@ -84,17 +84,17 @@ class BaseDocument(object):
return value
else:
raise ValueError
def extend(self, key, value):
if isinstance(value, list):
for v in value:
self.append(key, v)
else:
raise ValueError
def remove(self, doc):
self.get(doc.parentfield).remove(doc)
def _init_child(self, value, key):
if not self.doctype:
return value
@@ -105,7 +105,7 @@ class BaseDocument(object):
raise AttributeError, key
value = BaseDocument(value)
value.init_valid_columns()
value.parent = self.name
value.parenttype = self.doctype
value.parentfield = key
@@ -119,22 +119,24 @@ class BaseDocument(object):
for fieldname in self.meta.get_valid_columns():
d[fieldname] = self.get(fieldname)
return d
def init_valid_columns(self):
for key in default_fields:
if key not in self.__dict__:
self.__dict__[key] = None
if getattr(self, "_metaclass", False) or self.doctype in ("DocType", "DocField", "DocPerm"):
return
for key in self.meta.get_valid_columns():
valid = frappe.db.get_table_columns(self.doctype)
else:
valid = self.meta.get_valid_columns()

for key in valid:
if key not in self.__dict__:
self.__dict__[key] = None
def is_new(self):
return self.get("__islocal")
def as_dict(self):
doc = self.get_valid_dict()
doc["doctype"] = self.doctype
@@ -142,19 +144,19 @@ class BaseDocument(object):
children = self.get(df.fieldname) or []
doc[df.fieldname] = [d.as_dict() for d in children]
return doc
def get_table_field_doctype(self, fieldname):
return self.meta.get_field(fieldname).options
def get_parentfield_of_doctype(self, doctype):
fieldname = [df.fieldname for df in self.meta.get_table_fields() if df.options==doctype]
return fieldname[0] if fieldname else None
def db_insert(self):
set_new_name(self)
d = self.get_valid_dict()
columns = d.keys()
frappe.db.sql("""insert into `tab{doctype}`
frappe.db.sql("""insert into `tab{doctype}`
({columns}) values ({values})""".format(
doctype = self.doctype,
columns = ", ".join(["`"+c+"`" for c in columns]),
@@ -166,69 +168,69 @@ class BaseDocument(object):
if self.get("__islocal") or not self.name:
self.db_insert()
return
d = self.get_valid_dict()
columns = d.keys()
frappe.db.sql("""update `tab{doctype}`
frappe.db.sql("""update `tab{doctype}`
set {values} where name=%s""".format(
doctype = self.doctype,
values = ", ".join(["`"+c+"`=%s" for c in columns])
), d.values() + [d.get("name")])
def _fix_numeric_types(self):
for df in self.meta.get("fields"):
if df.fieldtype in ("Int", "Check"):
self.set(df.fieldname, cint(self.get(df.fieldname)))
elif df.fieldtype in ("Float", "Currency"):
self.set(df.fieldname, flt(self.get(df.fieldname)))
if self.docstatus is not None:
if self.docstatus is not None:
self.docstatus = cint(self.docstatus)
def _get_missing_mandatory_fields(self):
"""Get mandatory fields that do not have any values"""
def get_msg(df):
if df.fieldtype == "Table":
return "{}: {}: {}".format(_("Error"), _("Data missing in table"), _(df.label))
elif self.parentfield:
return "{}: {} #{}: {}: {}".format(_("Error"), _("Row"), self.idx,
_("Value missing for"), _(df.label))

else:
return "{}: {}: {}".format(_("Error"), _("Value missing for"), _(df.label))
missing = []
for df in self.meta.get("fields", {"reqd": 1}):
if self.get(df.fieldname) in (None, []):
missing.append((df.fieldname, get_msg(df)))
return missing
def get_invalid_links(self):
def get_msg(df, docname):
if self.parentfield:
return "{} #{}: {}: {}".format(_("Row"), self.idx, _(df.label), docname)
else:
return "{}: {}".format(_(df.label), docname)
invalid_links = []
for df in self.meta.get_link_fields():
doctype = df.options
if not doctype:
frappe.throw("Options not set for link field: {}".format(df.fieldname))
elif doctype.lower().startswith("link:"):
doctype = doctype[5:]
docname = self.get(df.fieldname)
if docname and not frappe.db.get_value(doctype, docname):
invalid_links.append((df.fieldname, docname, get_msg(df, docname)))
return invalid_links
def _validate_constants(self):
if frappe.flags.in_import:
return
@@ -239,8 +241,8 @@ class BaseDocument(object):

for fieldname in constants:
if self.get(fieldname) != values.get(fieldname):
frappe.throw("{0}: {1}".format(_("Value cannot be changed for"),
_(self.meta.get_label(fieldname))),
frappe.throw("{0}: {1}".format(_("Value cannot be changed for"),
_(self.meta.get_label(fieldname))),
frappe.CannotChangeConstantError)

def _filter(data, filters, limit=None):
@@ -250,12 +252,12 @@ def _filter(data, filters, limit=None):
"key" : True (exists), "key": False (does not exist) }"""

out = []
for d in data:
add = True
for f in filters:
fval = filters[f]
if fval is True:
fval = ("not None", fval)
elif fval is False:
@@ -265,7 +267,7 @@ def _filter(data, filters, limit=None):
fval = ("^", fval[1:])
else:
fval = ("=", fval)
if not frappe.compare(getattr(d, f, None), fval[0], fval[1]):
add = False
break
@@ -274,5 +276,5 @@ def _filter(data, filters, limit=None):
out.append(d)
if limit and (len(out)-1)==limit:
break
return out

+ 37
- 37
frappe/model/meta.py 파일 보기

@@ -1,5 +1,5 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt
# MIT License. See license.txt

# metadata

@@ -23,12 +23,12 @@ 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)
self.process()
def load_from_db(self):
try:
super(Meta, self).load_from_db()
@@ -37,34 +37,34 @@ class Meta(Document):
fname = frappe.scrub(self.name)
with open(frappe.get_app_path("frappe", "core", "doctype", fname, fname + ".json"), "r") as f:
txt = json.loads(f.read())
for d in txt.get("fields", []):
d["doctype"] = "DocField"
for d in txt.get("permissions", []):
d["doctype"] = "DocPerm"
self.__dict__.update(txt)
self.fields = [BaseDocument(d) for d in self.fields]
if hasattr(self, "permissions"):
self.permissions = [BaseDocument(d) for d in self.permissions]
else:
raise
def get_link_fields(self):
tmp = self.get("fields", {"fieldtype":"Link", "options":["!=", "[Select]"]})
for df in self.get("fields", {"fieldtype":"Select", "options": "^link:"}):
tmp.append(frappe._dict({"fieldname":df.fieldname, "label":df.label,
tmp.append(frappe._dict({"fieldname":df.fieldname, "label":df.label,
"fieldtype":"Link", "options": df.options[5:]}))
return tmp
def get_table_fields(self):
if not hasattr(self, "_table_fields"):
if self.name!="DocType":
self._table_fields = self.get('fields', {"fieldtype":"Table"})
else:
self._table_fields = doctype_table_fields
return self._table_fields

def get_valid_columns(self):
@@ -74,12 +74,12 @@ class Meta(Document):
else:
self._valid_columns = self.default_fields + \
[df.fieldname for df in self.get("fields") if df.fieldtype in type_map]
return self._valid_columns
def get_table_field_doctype(self, fieldname):
return { "fields": "DocField", "permissions": "DocPerm"}.get(fieldname)
def get_field(self, fieldname):
if not fieldname in self._fields:
fields = self.get("fields", {"fieldname":fieldname})
@@ -88,31 +88,31 @@ class Meta(Document):

def get_label(self, fieldname):
return self.get_field(fieldname).label
def get_options(self, fieldname):
return self.get_field(fieldname).options
def process(self):
# don't process for special doctypes
# prevent's circular dependency
if self.name in self.special_doctypes:
return
self.add_custom_fields()
self.apply_property_setters()
self.sort_fields()
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
else:
raise
def apply_property_setters(self):
for ps in frappe.db.sql("""select * from `tabProperty Setter` where
doc_type=%s""", (self.name,), as_dict=1):
@@ -129,7 +129,7 @@ class Meta(Document):
ps.value = cint(ps.value)

docfield.set(ps.property, ps.value)
def sort_fields(self):
"""sort on basis of previous_field"""
newlist = []
@@ -157,7 +157,7 @@ class Meta(Document):
newlist.append(d)
pending.remove(d)

# recurring at end
# recurring at end
if pending:
newlist += pending

@@ -168,12 +168,12 @@ class Meta(Document):
idx += 1

self.set("fields", newlist)
def get_restricted_fields(self, restricted_types):
restricted_fields = self.get("fields", {
"fieldtype":"Link",
"parent": self.name,
"ignore_restrictions":("!=", 1),
"fieldtype":"Link",
"parent": self.name,
"ignore_restrictions":("!=", 1),
"options":("in", restricted_types)
})
if self.name in restricted_types:
@@ -184,7 +184,7 @@ class Meta(Document):


doctype_table_fields = [
frappe._dict({"fieldname": "fields", "options": "DocField"}),
frappe._dict({"fieldname": "fields", "options": "DocField"}),
frappe._dict({"fieldname": "permissions", "options": "DocPerm"})
]

@@ -197,8 +197,8 @@ def is_single(doctype):
raise Exception, 'Cannot determine whether %s is single' % doctype

def get_parent_dt(dt):
parent_dt = frappe.db.sql("""select parent from tabDocField
where fieldtype="Table" and options=%s and (parent not like "old_parent:%%")
parent_dt = frappe.db.sql("""select parent from tabDocField
where fieldtype="Table" and options=%s and (parent not like "old_parent:%%")
limit 1""", dt)
return parent_dt and parent_dt[0][0] or ''

@@ -208,37 +208,37 @@ def set_fieldname(field_id, fieldname):
def get_field_currency(df, doc):
"""get currency based on DocField options and fieldvalue in doc"""
currency = None
if ":" in cstr(df.options):
split_opts = df.options.split(":")
if len(split_opts)==3:
currency = frappe.db.get_value(split_opts[0], doc.get(split_opts[1]),
currency = frappe.db.get_value(split_opts[0], doc.get(split_opts[1]),
split_opts[2])
else:
currency = doc.get(df.options)

return currency
def get_field_precision(df, doc):
"""get precision based on DocField options and fieldvalue in doc"""
from frappe.utils import get_number_format_info
number_format = None
if df.fieldtype == "Currency":
currency = get_field_currency(df, doc)
if currency:
number_format = frappe.db.get_value("Currency", currency, "number_format")
if not number_format:
number_format = frappe.db.get_default("number_format") or "#,###.##"
decimal_str, comma_str, precision = get_number_format_info(number_format)

if df.fieldtype == "Float":
precision = cint(frappe.db.get_default("float_precision")) or 3

return precision
def clear_cache(doctype=None):
def clear_single(dt):
frappe.cache().delete_value("meta:" + dt)
@@ -248,7 +248,7 @@ def clear_cache(doctype=None):
clear_single(doctype)

# clear all parent doctypes
for dt in frappe.db.sql("""select parent from tabDocField
for dt in frappe.db.sql("""select parent from tabDocField
where fieldtype="Table" and options=%s""", (doctype,)):
clear_single(dt[0])

@@ -261,4 +261,4 @@ def clear_cache(doctype=None):
for dt in frappe.db.sql("""select name from tabDocType"""):
clear_single(dt[0])

frappe.cache().delete_value("is_table")
frappe.cache().delete_value("is_table")

+ 28
- 27
frappe/public/js/frappe/model/create_new.js 파일 보기

@@ -18,39 +18,40 @@ $.extend(frappe.model, {
owner: user
};
frappe.model.set_default_values(doc, parent_doc);
if(parent_doc) {
$.extend(doc, {
parent: parent_doc.name,
parentfield: parentfield,
parenttype: parent_doc.doctype,
});
if(!parent_doc[parentfield]) parent_doc[parentfield] = [];
parent_doc[parentfield].push(doc);
} else {
frappe.provide("frappe.model.docinfo." + doctype + "." + doc.name);
}

frappe.model.add_to_locals(doc);
frappe.model.add_to_locals(doc);
return doc;
},
make_new_doc_and_get_name: function(doctype) {
return frappe.model.get_new_doc(doctype).name;
},
get_new_name: function(doctype) {
var cnt = frappe.model.new_name_count
if(!cnt[doctype])
if(!cnt[doctype])
cnt[doctype] = 0;
cnt[doctype]++;
return frappe._('New') + ' '+ frappe._(doctype) + ' ' + cnt[doctype];
},
set_default_values: function(doc, parent_doc) {
var doctype = doc.doctype;
var docfields = frappe.meta.docfield_list[doctype] || [];
var updated = [];
for(var fid=0;fid<docfields.length;fid++) {
var f = docfields[fid];
if(!in_list(frappe.model.no_value_type, f.fieldtype) && doc[f.fieldname]==null) {
@@ -60,7 +61,7 @@ $.extend(frappe.model, {
v = cint(v);
else if(in_list(["Currency", "Float"], f.fieldtype))
v = flt(v);
doc[f.fieldname] = v;
updated.push(f.fieldname);
}
@@ -68,17 +69,17 @@ $.extend(frappe.model, {
}
return updated;
},
get_default_value: function(df, doc, parent_doc) {
var def_vals = {
"__user": user,
"Today": dateutil.get_today(),
}
var restrictions = frappe.defaults.get_restrictions();
if(df.fieldtype==="Link" && restrictions
&& df.ignore_restrictions != 1
&& restrictions[df.options]
&& restrictions[df.options]
&& (restrictions[df.options].length===1))
return restrictions[df.options][0];
else if(frappe.defaults.get_user_default(df.fieldname))
@@ -92,22 +93,22 @@ $.extend(frappe.model, {
else if(df["default"] && df["default"][0]!==":")
return df["default"];
},
get_default_from_boot_docs: function(df, doc, parent_doc) {
// set default from partial docs passed during boot like ":User"
if(frappe.get_list(df["default"]).length > 0) {
var ref_fieldname = df["default"].slice(1).toLowerCase().replace(" ", "_");
var ref_value = parent_doc ?
var ref_value = parent_doc ?
parent_doc[ref_fieldname] :
frappe.defaults.get_user_default(ref_fieldname);
var ref_doc = ref_value ? frappe.get_doc(df["default"], ref_value) : null;
if(ref_doc && ref_doc[df.fieldname]) {
return ref_doc[df.fieldname];
}
}
},
add_child: function(parent_doc, doctype, parentfield, idx) {
// create row doc
idx = idx ? idx - 0.1 : (parent_doc[parentfield] || []).length + 1;
@@ -124,10 +125,10 @@ $.extend(frappe.model, {
}

cur_frm && cur_frm.dirty();
return d;
},
copy_doc: function(doc, from_amend) {
var no_copy_list = ['name','amended_from','amendment_date','cancel_reason'];
var newdoc = frappe.model.get_new_doc(doc.doctype);
@@ -135,10 +136,10 @@ $.extend(frappe.model, {
for(var key in doc) {
// dont copy name and blank fields
var df = frappe.meta.get_docfield(doc.doctype, key);
if(key.substr(0,2)!='__'
&& !in_list(no_copy_list, key)
&& !(df && (!from_amend && cint(df.no_copy)==1))) {
if(key.substr(0,2)!='__'
&& !in_list(no_copy_list, key)
&& !(df && (!from_amend && cint(df.no_copy)==1))) {
value = doc[key];
if(df.fieldtype==="Table") {
newdoc[key] = [];
@@ -160,7 +161,7 @@ $.extend(frappe.model, {

return newdoc;
},
open_mapped_doc: function(opts) {
return frappe.call({
type: "GET",
@@ -204,10 +205,10 @@ $.extend(frappe.model, {
title: frappe._("Get From ") + frappe._(opts.source_doctype),
fields: [
{
"fieldtype": "Link",
"fieldtype": "Link",
"label": frappe._(opts.source_doctype),
"fieldname": opts.source_doctype,
"options": opts.source_doctype,
"fieldname": opts.source_doctype,
"options": opts.source_doctype,
"get_query": opts.get_query,
reqd:1},
{
@@ -215,7 +216,7 @@ $.extend(frappe.model, {
"label": frappe._("Get"),
click: function() {
var values = d.get_values();
if(!values)
if(!values)
return;
opts.source_name = values[opts.source_doctype];
d.hide();
@@ -229,4 +230,4 @@ $.extend(frappe.model, {
_map();
}
}
})
})

불러오는 중...
취소
저장