From 2680459e2ffcbec9eee595055a14a9e29cdbe2ff Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 28 Mar 2014 15:23:25 +0530 Subject: [PATCH] frappe/frappe#478 --- .../doctype/customize_form/customize_form.py | 82 +++++++------ .../core/doctype/print_format/print_format.py | 3 - frappe/core/doctype/report/report.py | 3 - frappe/core/doctype/user/user.py | 2 +- frappe/database.py | 15 ++- frappe/model/base_document.py | 4 + frappe/model/controller.py | 4 +- frappe/model/create_new.py | 18 ++- frappe/model/document.py | 4 +- frappe/model/mapper.py | 112 +++++++----------- frappe/website/website_generator.py | 4 +- 11 files changed, 112 insertions(+), 139 deletions(-) diff --git a/frappe/core/doctype/customize_form/customize_form.py b/frappe/core/doctype/customize_form/customize_form.py index 684c7aeb8e..4c805157dc 100644 --- a/frappe/core/doctype/customize_form/customize_form.py +++ b/frappe/core/doctype/customize_form/customize_form.py @@ -12,45 +12,43 @@ from frappe.utils import cstr from frappe.model.document import Document class CustomizeForm(Document): - def __init__(self, doc, doclist=[]): - self.doc, self.doclist = doc, doclist - self.doctype_properties = [ - 'search_fields', - 'default_print_format', - 'read_only_onload', - 'allow_print', - 'allow_email', - 'allow_copy', - 'allow_attach', - 'max_attachments' - ] - self.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', - ] - - self.property_restrictions = { - 'fieldtype': [['Currency', 'Float'], ['Small Text', 'Data'], ['Text', 'Text Editor', 'Code']], - } - + doctype_properties = [ + 'search_fields', + 'default_print_format', + 'read_only_onload', + 'allow_print', + 'allow_email', + 'allow_copy', + 'allow_attach', + 'max_attachments' + ] + + 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', + ] + + property_restrictions = { + 'fieldtype': [['Currency', 'Float'], ['Small Text', 'Data'], ['Text', 'Text Editor', 'Code']], + } def get(self): """ @@ -105,12 +103,12 @@ class CustomizeForm(Document): args can contain: * list --> list of attributes to set - * doc_to_set --> defaults to self.doc + * doc_to_set --> defaults to self * value --> to set all attributes to one value eg. None * doc --> copy attributes from doc to doc_to_set """ if not 'doc_to_set' in args: - args['doc_to_set'] = self.doc + args['doc_to_set'] = self if 'list' in args: if 'value' in args: @@ -131,7 +129,7 @@ class CustomizeForm(Document): from frappe.model import doc from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype - this_doclist = frappe.doclist([self.doc] + self.doclist) + this_doclist = frappe.doclist([self] + self.doclist) ref_doclist = self.get_ref_doclist() dt_doclist = doc.get('DocType', self.doc_type) diff --git a/frappe/core/doctype/print_format/print_format.py b/frappe/core/doctype/print_format/print_format.py index 1932323339..4248a1b3ba 100644 --- a/frappe/core/doctype/print_format/print_format.py +++ b/frappe/core/doctype/print_format/print_format.py @@ -11,9 +11,6 @@ standard_format = "templates/print_formats/standard.html" from frappe.model.document import Document class PrintFormat(Document): - def __init__(self, d, dl): - self.doc, self.doclist = d,dl - def validate(self): if self.standard=="Yes" and frappe.session.user != "Administrator": frappe.msgprint("Standard Print Format cannot be updated.", raise_exception=1) diff --git a/frappe/core/doctype/report/report.py b/frappe/core/doctype/report/report.py index 0a1f9c4d67..26c646529c 100644 --- a/frappe/core/doctype/report/report.py +++ b/frappe/core/doctype/report/report.py @@ -8,9 +8,6 @@ from frappe import conf, _ from frappe.model.document import Document class Report(Document): - def __init__(self, doc, doclist): - self.doc, self.doclist = doc, doclist - def validate(self): """only administrator can save standard report""" if not self.module: diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index 3980bec9e2..d7fa879d84 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -68,7 +68,7 @@ class User(Document): def on_update(self): # owner is always name - frappe.db.set(self.doc, 'owner', self.name) + frappe.db.set(self, 'owner', self.name) # clear new password new_password = self.new_password diff --git a/frappe/database.py b/frappe/database.py index 749dfee446..da7ba924da 100644 --- a/frappe/database.py +++ b/frappe/database.py @@ -386,23 +386,30 @@ class Database: def set_value(self, dt, dn, field, val, modified=None, modified_by=None): from frappe.utils import now + if not modified: + modified = now() + if not modified_by: + modified_by = frappe.session.user + if dn and dt!=dn: self.sql("""update `tab%s` set `%s`=%s, modified=%s, modified_by=%s where name=%s""" % (dt, field, "%s", "%s", "%s", "%s"), - (val, modified or now(), modified_by or frappe.session["user"], dn)) + (val, modified, modified_by, dn)) else: if self.sql("select value from tabSingles where field=%s and doctype=%s", (field, dt)): self.sql("""update tabSingles set value=%s where field=%s and doctype=%s""", (val, field, dt)) else: self.sql("""insert into tabSingles(doctype, field, value) - values (%s, %s, %s)""", (dt, field, val, )) + values (%s, %s, %s)""", (dt, field, val)) - if field!="modified": - self.set_value(dt, dn, "modified", modified or now()) + if field not in ("modified", "modified_by"): + self.set_value(dt, dn, "modified", modified) + self.set_value(dt, dn, "modified_by", modified_by) def set(self, doc, field, val): doc.set(field, val) + frappe.db.set_value(doc.doctype, doc.name, field, val) def touch(self, doctype, docname): from frappe.utils import now diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index 1fdeb6ff87..be3a5116db 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -137,6 +137,10 @@ class BaseDocument(object): def get_table_field_doctype(self, fieldname): return self.meta.get("fields", {"fieldname":fieldname})[0].options + + def get_parentfield_of_doctype(self, doctype): + fieldname = [df.fieldname for df in self.get_table_fields() if df.options==doctype] + return fieldname[0] if fieldname else None def db_insert(self): set_new_name(self) diff --git a/frappe/model/controller.py b/frappe/model/controller.py index 55606caf4f..8cb6dde473 100644 --- a/frappe/model/controller.py +++ b/frappe/model/controller.py @@ -27,7 +27,7 @@ class DocListController(Document): } if not doc: - doc = self.doc + doc = self df = self.meta.get_field(fieldname, parent=doc.doctype) @@ -83,7 +83,7 @@ class DocListController(Document): df = self.meta.get_field(fieldname, parentfield=parentfield) if df.fieldtype == "Currency" and df.options and not self._precision.options.get(df.options): - self._precision.options[df.options] = get_field_precision(df, self.doc) + self._precision.options[df.options] = get_field_precision(df, self) if df.fieldtype == "Currency": self._precision[parentfield or "main"][fieldname] = cint(self._precision.options.get(df.options)) or \ diff --git a/frappe/model/create_new.py b/frappe/model/create_new.py index 020cb55727..ce6206323f 100644 --- a/frappe/model/create_new.py +++ b/frappe/model/create_new.py @@ -11,15 +11,13 @@ from frappe.utils import nowdate, nowtime, cint, flt import frappe.defaults def get_new_doc(doctype, parent_doc = None, parentfield = None): - doc = frappe.doc({ + doc = frappe.get_doc({ "doctype": doctype, "__islocal": 1, "owner": frappe.session.user, "docstatus": 0 }) - meta = frappe.get_meta(doctype) - restrictions = frappe.defaults.get_restrictions() if parent_doc: @@ -31,7 +29,7 @@ def get_new_doc(doctype, parent_doc = None, parentfield = None): defaults = frappe.defaults.get_defaults() - for d in meta.get({"doctype":"DocField", "parent": doctype}): + for d in doc.meta.get("fields"): default = defaults.get(d.fieldname) if (d.fieldtype=="Link") and d.ignore_restrictions != 1 and (d.options in restrictions)\ @@ -46,22 +44,22 @@ def get_new_doc(doctype, parent_doc = None, parentfield = None): doc.set(d.fieldname, nowdate()) elif d.default.startswith(":"): - ref_fieldname = d.default[1:].lower().replace(" ", "_") + ref_doctype = d.default[1:] + ref_fieldname = ref_doctype.lower().replace(" ", "_") if parent_doc: - ref_docname = parent_doc.fields[ref_fieldname] + ref_docname = parent_doc.get(ref_fieldname) else: ref_docname = frappe.db.get_default(ref_fieldname) - doc.set(d.fieldname, frappe.db.get_value(d.default[1:], ) - ref_docname, d.fieldname) + doc.set(d.fieldname, frappe.db.get_value(ref_doctype, ref_docname, d.fieldname)) else: doc.set(d.fieldname, d.default) # convert type of default if d.fieldtype in ("Int", "Check"): - doc.set(d.fieldname, cint(doc.fields[d.fieldname])) + doc.set(d.fieldname, cint(doc.get(d.fieldname))) elif d.fieldtype in ("Float", "Currency"): - doc.set(d.fieldname, flt(doc.fields[d.fieldname])) + doc.set(d.fieldname, flt(doc.get(d.fieldname))) elif d.fieldtype == "Time": doc.set(d.fieldname, nowtime()) diff --git a/frappe/model/document.py b/frappe/model/document.py index d859988672..2265be6c12 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -195,12 +195,12 @@ class Document(BaseDocument): if frappe.flags.in_import: return - new_doc = frappe.new_doc(self.doctype).fields + new_doc = frappe.new_doc(self.doctype) self.set_missing_values(new_doc) # children for df in self.meta.get("fields", {"fieldtype":"Table"}): - new_doc = frappe.new_doc(df.options).fields + new_doc = frappe.new_doc(df.options) value = self.get(df.fieldname) if isinstance(value, list): for d in value: diff --git a/frappe/model/mapper.py b/frappe/model/mapper.py index b9cbd473e3..6cb6c9bec7 100644 --- a/frappe/model/mapper.py +++ b/frappe/model/mapper.py @@ -7,84 +7,58 @@ from frappe import _ from frappe.utils import cstr from frappe.model import default_fields -def get_mapped_doclist(from_doctype, from_docname, table_maps, target_doclist=None, +def get_mapped_doc(from_doctype, from_docname, table_maps, target_doc=None, postprocess=None, ignore_permissions=False): - if target_doclist is None: - target_doclist = [] - - if isinstance(target_doclist, basestring): - target_doclist = json.loads(target_doclist) + if isinstance(target_doc, basestring): + target_doc = json.loads(target_doc) - source = frappe.bean(from_doctype, from_docname) + source_doc = frappe.get_doc(from_doctype, from_docname) - if not ignore_permissions and not frappe.has_permission(from_doctype, "read", source.doc): + if not ignore_permissions and not doc.has_permission("read"): frappe.msgprint("No Permission", raise_exception=frappe.PermissionError) - source_meta = frappe.get_meta(from_doctype) - target_meta = frappe.get_meta(table_maps[from_doctype]["doctype"]) - # main - if target_doclist: - if isinstance(target_doclist[0], dict): - target_doc = frappe.doc(fielddata=target_doclist[0]) - else: - target_doc = target_doclist[0] - else: + if not target_doc: target_doc = frappe.new_doc(table_maps[from_doctype]["doctype"]) - map_doc(source.doc, target_doc, table_maps[source.doctype], source_meta, target_meta) - if target_doclist: - target_doclist[0] = target_doc - else: - target_doclist = [target_doc] - - target_doclist = frappe.doclist(target_doclist) - + map_doc(source_doc, target_doc, table_maps[source_doc.doctype]) + row_exists_for_parentfield = {} # children - for source_d in source.doclist[1:]: - table_map = table_maps.get(source_d.doctype) + for df in source_doc.get_table_fields(): + source_child_doctype = df.options + table_map = table_maps.get(source_child_doctype) if table_map: - if "condition" in table_map: - if not table_map["condition"](source_d): - continue - target_doctype = table_map["doctype"] - parentfield = target_meta.get({ - "parent": target_doc.doctype, - "doctype": "DocField", - "fieldtype": "Table", - "options": target_doctype - })[0].fieldname - - # does row exist for a parentfield? - if parentfield not in row_exists_for_parentfield: - row_exists_for_parentfield[parentfield] = True if \ - frappe.doclist(target_doclist).get({"parentfield": parentfield}) else False - - if table_map.get("add_if_empty") and row_exists_for_parentfield.get(parentfield): - continue - - target_d = frappe.new_doc(target_doctype, target_doc, parentfield) - map_doc(source_d, target_d, table_map, source_meta, target_meta, source.doclist[0]) - target_d.idx = None - target_doclist.append(target_d) + for source_d in source_doc.get(df.fieldname): + if "condition" in table_map: + if not table_map["condition"](source_d): + continue + + target_child_doctype = table_map["doctype"] + target_parentfield = target_doc.get_parentfield_of_doctype(target_child_doctype) - target_doclist = frappe.doclist(target_doclist) + # does row exist for a parentfield? + if df.fieldname not in row_exists_for_parentfield: + row_exists_for_parentfield[target_parentfield] = (True + if target_doc.get(target_parentfield) else False) + + if table_map.get("add_if_empty") and row_exists_for_parentfield.get(target_parentfield): + continue + + target_d = frappe.new_doc(target_child_doctype, target_doc, target_parentfield) + map_doc(source_d, target_d, table_map, source_doc) + target_d.idx = None + target_doc.append(target_parentfield, target_d) if postprocess: - new_target_doclist = postprocess(source, target_doclist) - if new_target_doclist: - target_doclist = new_target_doclist + postprocess(source_doc, target_doc) - return target_doclist + return target_doc -def map_doc(source_doc, target_doc, table_map, source_meta, target_meta, source_parent=None): - no_copy_fields = set(\ - [d.fieldname for d in source_meta.get({"no_copy": 1, - "parent": source_doc.doctype})] \ - + [d.fieldname for d in target_meta.get({"no_copy": 1, - "parent": target_doc.doctype})] \ +def map_doc(source_doc, target_doc, table_map, source_parent=None): + no_copy_fields = set([d.fieldname for d in source_doc.meta.get("fields", {"no_copy": 1})] + + [d.fieldname for d in target_doc.meta.get("fields", {"no_copy": 1})] + default_fields + table_map.get("field_no_map", [])) @@ -92,18 +66,16 @@ def map_doc(source_doc, target_doc, table_map, source_meta, target_meta, source_ for key, condition in table_map["validation"].items(): if condition[0]=="=": if source_doc.get(key) != condition[1]: - frappe.msgprint(_("Cannot map because following condition fails: ") - + key + "=" + cstr(condition[1]), raise_exception=frappe.ValidationError) + frappe.throw(_("Cannot map because following condition fails: ") + + key + "=" + cstr(condition[1])) # map same fields - target_fields = target_meta.get({"doctype": "DocField", "parent": target_doc.doctype}) - for key in [d.fieldname for d in target_fields]: - if key not in no_copy_fields: - val = source_doc.get(key) + for df in target_doc.meta.get("fields"): + if df.fieldname not in no_copy_fields: + val = source_doc.get(df.fieldname) if val not in (None, ""): - target_doc.set(key, val) - - + target_doc.set(df.fieldname, val) + # map other fields field_map = table_map.get("field_map") diff --git a/frappe/website/website_generator.py b/frappe/website/website_generator.py index ae2c394da4..ef6a2cdae9 100644 --- a/frappe/website/website_generator.py +++ b/frappe/website/website_generator.py @@ -24,7 +24,7 @@ class WebsiteGenerator(DocListController): if self.is_new(): self.set(self.website_template.page_name_field, page_name) else: - frappe.db.set(self.doc, self.website_template.page_name_field, page_name) + frappe.db.set(self, self.website_template.page_name_field, page_name) return page_name @@ -96,7 +96,7 @@ class WebsiteGenerator(DocListController): idx = add_to_sitemap(opts) if idx!=None and self.idx != idx: - frappe.db.set(self.doc, "idx", idx) + frappe.db.set(self, "idx", idx) def update_permissions(self, opts): if self.meta.get_field("public_read"):