@@ -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 | |||
@@ -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) |
@@ -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 | |||
@@ -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() | |||