diff --git a/frappe/__init__.py b/frappe/__init__.py index cdfa378b1c..0b93244f0c 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -351,8 +351,7 @@ def get_meta(doctype, cached=True): import frappe.model.meta return frappe.model.meta.get_meta(doctype, cached=cached) -def delete_doc(doctype=None, name=None, doclist = None, force=0, ignore_doctypes=None, - for_reload=False, ignore_permissions=False): +def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reload=False, ignore_permissions=False): import frappe.model.delete_doc if not ignore_doctypes: @@ -360,11 +359,9 @@ def delete_doc(doctype=None, name=None, doclist = None, force=0, ignore_doctypes if isinstance(name, list): for n in name: - frappe.model.delete_doc.delete_doc(doctype, n, doclist, force, ignore_doctypes, - for_reload, ignore_permissions) + frappe.model.delete_doc.delete_doc(doctype, n, force, ignore_doctypes, for_reload, ignore_permissions) else: - frappe.model.delete_doc.delete_doc(doctype, name, doclist, force, ignore_doctypes, - for_reload, ignore_permissions) + frappe.model.delete_doc.delete_doc(doctype, name, force, ignore_doctypes, for_reload, ignore_permissions) def reload_doc(module, dt=None, dn=None, force=False): import frappe.modules diff --git a/frappe/model/delete_doc.py b/frappe/model/delete_doc.py index 902837b33b..02638497f8 100644 --- a/frappe/model/delete_doc.py +++ b/frappe/model/delete_doc.py @@ -9,7 +9,7 @@ import frappe.defaults from frappe.utils.file_manager import remove_all from frappe import _ -def delete_doc(doctype=None, name=None, doclist = None, force=0, ignore_doctypes=None, for_reload=False, ignore_permissions=False): +def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reload=False, ignore_permissions=False): """ Deletes a doc(dt, dn) and validates if it is not submitted and not linked in a live record """ @@ -27,20 +27,21 @@ def delete_doc(doctype=None, name=None, doclist = None, force=0, ignore_doctypes if not frappe.db.exists(doctype, name): return + doc = frappe.get_doc(doctype, name) + if not for_reload: - check_permission_and_not_submitted(doctype, name, ignore_permissions) - - run_on_trash(doctype, name, doclist) + check_permission_and_not_submitted(doc, ignore_permissions) + doc.run_method("on_trash") # check if links exist if not force: - check_if_doc_is_linked(doctype, name) + check_if_doc_is_linked(doc) try: - tablefields = frappe.model.meta.get_table_fields(doctype) frappe.db.sql("delete from `tab%s` where name=%s" % (doctype, "%s"), (name,)) - for t in tablefields: - if t[0] not in ignore_doctypes: - frappe.db.sql("delete from `tab%s` where parent = %s" % (t[0], '%s'), (name,)) + for t in doc.meta.get_table_fields(): + if t.options not in ignore_doctypes: + frappe.db.sql("delete from `tab%s` where parent = %s" % (t.options, '%s'), (name,)) + except Exception, e: if e.args[0]==1451: frappe.msgprint("Cannot delete %s '%s' as it is referenced in another record. You must delete the referred record first" % (doctype, name)) @@ -57,41 +58,32 @@ def delete_doc(doctype=None, name=None, doclist = None, force=0, ignore_doctypes def check_permission_and_not_submitted(doctype, name, ignore_permissions=False): # permission - if not ignore_permissions and frappe.session.user!="Administrator" and not frappe.has_permission(doctype, "cancel"): + if not ignore_permissions and frappe.session.user!="Administrator" and not doc.has_permission("cancel"): frappe.msgprint(_("User not allowed to delete."), raise_exception=True) # check if submitted - if frappe.db.get_value(doctype, name, "docstatus") == 1: - frappe.msgprint(_("Submitted Record cannot be deleted")+": "+name+"("+doctype+")", + if doc.docstatus == 1: + frappe.msgprint(_("Submitted Record cannot be deleted")+": "+doc.name+"("+doc.doctype+")", raise_exception=True) -def run_on_trash(doctype, name, doclist): - # call on_trash if required - if doclist: - bean = frappe.bean(doclist) - else: - bean = frappe.bean(doctype, name) - - bean.run_method("on_trash") - class LinkExistsError(frappe.ValidationError): pass -def check_if_doc_is_linked(dt, dn, method="Delete"): +def check_if_doc_is_linked(doc, method="Delete"): """ Raises excption if the given doc(dt, dn) is linked in another record. """ from frappe.model.rename_doc import get_link_fields - link_fields = get_link_fields(dt) + link_fields = get_link_fields(doc.doctype) link_fields = [[lf['parent'], lf['fieldname'], lf['issingle']] for lf in link_fields] for link_dt, link_field, issingle in link_fields: if not issingle: - item = frappe.db.get_value(link_dt, {link_field:dn}, + item = frappe.db.get_value(link_dt, {link_field:doc.name}, ["name", "parent", "parenttype", "docstatus"], as_dict=True) - if item and item.parent != dn and ((method=="Delete" and item.docstatus<2) or + if item and item.parent != doc.name and ((method=="Delete" and item.docstatus<2) or (method=="Cancel" and item.docstatus==1)): frappe.msgprint(method + " " + _("Error") + ":"+\ - ("%s (%s) " % (dn, dt)) + _("is linked in") + (" %s (%s)") % + ("%s (%s) " % (doc.name, doc.doctype)) + _("is linked in") + (" %s (%s)") % (item.parent or item.name, item.parent and item.parenttype or link_dt), raise_exception=LinkExistsError) diff --git a/frappe/modules/export_file.py b/frappe/modules/export_file.py index 2044988d94..db01558b14 100644 --- a/frappe/modules/export_file.py +++ b/frappe/modules/export_file.py @@ -3,8 +3,8 @@ from __future__ import unicode_literals -import frappe, os -import frappe.model.doc +import frappe, os, json +import frappe.model from frappe.modules import scrub, get_module_path, lower_case_files_for, scrub_dt_dn def export_doc(doc): @@ -17,58 +17,41 @@ def export_to_files(record_list=None, record_module=None, verbose=0, create_init if frappe.flags.in_import: return - module_doclist =[] if record_list: for record in record_list: - write_document_file(frappe.model.doc.get(record[0], record[1]), - record_module, create_init=create_init) + write_document_file(frappe.get_doc(record[0], record[1]), record_module, create_init=create_init) -def write_document_file(doclist, record_module=None, create_init=None): - from frappe.modules.utils import pprint_doclist +def write_document_file(doc, record_module=None, create_init=None): + newdoc = doc.as_dict() - doclist = [filter_fields(d.fields) for d in doclist] - - module = record_module or get_module_name(doclist) + # strip out default fields from children + for df in doc.get_table_fields(): + for d in newdoc.get(df.fieldname): + for fieldname in frappe.model.default_fields: + if fieldname in d: + del d[fieldname] + + module = record_module or get_module_name(doc) if create_init is None: - create_init = doclist[0]['doctype'] in lower_case_files_for + create_init = doc.doctype in lower_case_files_for # create folder - folder = create_folder(module, doclist[0]['doctype'], doclist[0]['name'], create_init) + folder = create_folder(module, doc.doctype, doc.name, create_init) # write the data file - fname = (doclist[0]['doctype'] in lower_case_files_for and scrub(doclist[0]['name'])) or doclist[0]['name'] + fname = (doc.doctype in lower_case_files_for and scrub(doc.name)) or doc.name with open(os.path.join(folder, fname +'.txt'),'w+') as txtfile: - txtfile.write(pprint_doclist(doclist)) - -def filter_fields(doc): - from frappe.model.doctype import get - from frappe.model import default_fields - - doctypelist = get(doc.get("doctype"), False) - valid_fields = [d.fieldname for d in doctypelist.get({"parent":doc.get("doctype"), - "doctype":"DocField"})] - to_remove = [] - - for key in doc: - if (not key in default_fields) and (not key in valid_fields): - to_remove.append(key) - elif doc[key]==None: - to_remove.append(key) - - for key in to_remove: - del doc[key] - - return doc + txtfile.write(json.dumps(newdoc, indent=1, sort_keys=True)) -def get_module_name(doclist): - if doclist[0]['doctype'] == 'Module Def': - module = doclist[0]['name'] - elif doclist[0]['doctype']=='Control Panel': +def get_module_name(doc): + if doc.doctype == 'Module Def': + module = doc.name + elif doc.doctype=='Control Panel': module = 'Core' - elif doclist[0]['doctype']=="Workflow": - module = frappe.db.get_value("DocType", doclist[0]["document_type"], "module") + elif doc.doctype=="Workflow": + module = frappe.db.get_value("DocType", doc.document_type, "module") else: - module = doclist[0]['module'] + module = doc.module return module diff --git a/frappe/modules/import_file.py b/frappe/modules/import_file.py index 05c02ada0a..42ef2cceae 100644 --- a/frappe/modules/import_file.py +++ b/frappe/modules/import_file.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals -import frappe, os +import frappe, os, json from frappe.modules import scrub, get_module_path, scrub_dt_dn def import_files(module, dt=None, dn=None, force=False): @@ -31,11 +31,9 @@ def get_file_path(module, dt, dn): def import_file_by_path(path, force=False): frappe.flags.in_import = True - doclist = read_doclist_from_file(path) + doc = read_doc_from_file(path) - if doclist: - doc = doclist[0] - + if doc: if not force: # check if timestamps match if doc['modified']==str(frappe.db.get_value(doc['doctype'], doc['name'], 'modified')): @@ -43,7 +41,7 @@ def import_file_by_path(path, force=False): original_modified = doc["modified"] - import_doclist(doclist) + import_doc(doc) # since there is a new timestamp on the file, update timestamp in frappe.db.sql("update `tab%s` set modified=%s where name=%s" % \ @@ -53,17 +51,15 @@ def import_file_by_path(path, force=False): frappe.flags.in_import = False return True -def read_doclist_from_file(path): - doclist = None +def read_doc_from_file(path): + doc = None if os.path.exists(path): - from frappe.modules.utils import peval_doclist - with open(path, 'r') as f: - doclist = peval_doclist(f.read()) + doc = json.loads(f.read()) else: raise Exception, '%s missing' % path - return doclist + return doc ignore_values = { "Report": ["disabled"], @@ -71,56 +67,32 @@ ignore_values = { ignore_doctypes = ["Page Role", "DocPerm"] -def import_doclist(doclist): - doctype = doclist[0]["doctype"] - name = doclist[0]["name"] +def import_doc(docdict): + docdict["__islocal"] = 1 + doc = frappe.get_doc(docdict) + old_doc = None - - doctypes = set([d["doctype"] for d in doclist]) - ignore = list(doctypes.intersection(set(ignore_doctypes))) - if doctype in ignore_values: - if frappe.db.exists(doctype, name): - old_doc = frappe.doc(doctype, name) - + if frappe.db.exists(doc.doctype, doc.name): + old_doc = frappe.get_doc(doc.doctype, doc.name) + + # update ignore values + for key in ignore_values.get(doctype) or []: + doc.set(key, old_doc.get(key)) + + # update ignored docs into new doc + for df in doc.get_table_fields(): + if df.options in ignore_doctypes: + doc.set(df.fieldname, []) + # delete old frappe.delete_doc(doctype, name, force=1, ignore_doctypes=ignore, for_reload=True) - # don't overwrite ignored docs - doclist1 = remove_ignored_docs_if_they_already_exist(doclist, ignore, name) - - # update old values (if not to be overwritten) - if doctype in ignore_values and old_doc: - update_original_values(doclist1, doctype, old_doc) - - # reload_new - new_bean = frappe.bean(doclist1) - new_bean.ignore_children_type = ignore - new_bean.ignore_links = True - new_bean.ignore_validate = True - new_bean.ignore_permissions = True - new_bean.ignore_mandatory = True - new_bean.ignore_restrictions = True - - if doctype=="DocType" and name in ["DocField", "DocType"]: - new_bean.ignore_fields = True - - new_bean.insert() - -def remove_ignored_docs_if_they_already_exist(doclist, ignore, name): - doclist1 = doclist - if ignore: - has_records = [] - for d in ignore: - if frappe.db.get_value(d, {"parent":name}): - has_records.append(d) - - if has_records: - doclist1 = filter(lambda d: d["doctype"] not in has_records, doclist) - - return doclist1 - -def update_original_values(doclist, doctype, old_doc): - for key in ignore_values[doctype]: - doclist[0][key] = old_doc.fields[key] + doc.ignore_children_type = ignore + doc.ignore_links = True + doc.ignore_validate = True + doc.ignore_permissions = True + doc.ignore_mandatory = True + doc.ignore_restrictions = True + doc.insert() \ No newline at end of file