@@ -351,8 +351,7 @@ def get_meta(doctype, cached=True): | |||||
import frappe.model.meta | import frappe.model.meta | ||||
return frappe.model.meta.get_meta(doctype, cached=cached) | 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 | import frappe.model.delete_doc | ||||
if not ignore_doctypes: | 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): | if isinstance(name, list): | ||||
for n in name: | 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: | 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): | def reload_doc(module, dt=None, dn=None, force=False): | ||||
import frappe.modules | import frappe.modules | ||||
@@ -9,7 +9,7 @@ import frappe.defaults | |||||
from frappe.utils.file_manager import remove_all | from frappe.utils.file_manager import remove_all | ||||
from frappe import _ | 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 | 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): | if not frappe.db.exists(doctype, name): | ||||
return | return | ||||
doc = frappe.get_doc(doctype, name) | |||||
if not for_reload: | 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 | # check if links exist | ||||
if not force: | if not force: | ||||
check_if_doc_is_linked(doctype, name) | |||||
check_if_doc_is_linked(doc) | |||||
try: | try: | ||||
tablefields = frappe.model.meta.get_table_fields(doctype) | |||||
frappe.db.sql("delete from `tab%s` where name=%s" % (doctype, "%s"), (name,)) | 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: | except Exception, e: | ||||
if e.args[0]==1451: | 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)) | 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): | def check_permission_and_not_submitted(doctype, name, ignore_permissions=False): | ||||
# permission | # 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) | frappe.msgprint(_("User not allowed to delete."), raise_exception=True) | ||||
# check if submitted | # 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) | 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 | 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. | Raises excption if the given doc(dt, dn) is linked in another record. | ||||
""" | """ | ||||
from frappe.model.rename_doc import get_link_fields | 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] | link_fields = [[lf['parent'], lf['fieldname'], lf['issingle']] for lf in link_fields] | ||||
for link_dt, link_field, issingle in link_fields: | for link_dt, link_field, issingle in link_fields: | ||||
if not issingle: | 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) | ["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)): | (method=="Cancel" and item.docstatus==1)): | ||||
frappe.msgprint(method + " " + _("Error") + ":"+\ | 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), | (item.parent or item.name, item.parent and item.parenttype or link_dt), | ||||
raise_exception=LinkExistsError) | raise_exception=LinkExistsError) |
@@ -3,8 +3,8 @@ | |||||
from __future__ import unicode_literals | 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 | from frappe.modules import scrub, get_module_path, lower_case_files_for, scrub_dt_dn | ||||
def export_doc(doc): | 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: | if frappe.flags.in_import: | ||||
return | return | ||||
module_doclist =[] | |||||
if record_list: | if record_list: | ||||
for record in 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: | 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 | # 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 | # 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: | 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' | 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: | else: | ||||
module = doclist[0]['module'] | |||||
module = doc.module | |||||
return module | return module | ||||
@@ -3,7 +3,7 @@ | |||||
from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
import frappe, os | |||||
import frappe, os, json | |||||
from frappe.modules import scrub, get_module_path, scrub_dt_dn | from frappe.modules import scrub, get_module_path, scrub_dt_dn | ||||
def import_files(module, dt=None, dn=None, force=False): | 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): | def import_file_by_path(path, force=False): | ||||
frappe.flags.in_import = True | 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: | if not force: | ||||
# check if timestamps match | # check if timestamps match | ||||
if doc['modified']==str(frappe.db.get_value(doc['doctype'], doc['name'], 'modified')): | 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"] | original_modified = doc["modified"] | ||||
import_doclist(doclist) | |||||
import_doc(doc) | |||||
# since there is a new timestamp on the file, update timestamp in | # since there is a new timestamp on the file, update timestamp in | ||||
frappe.db.sql("update `tab%s` set modified=%s where name=%s" % \ | 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 | frappe.flags.in_import = False | ||||
return True | return True | ||||
def read_doclist_from_file(path): | |||||
doclist = None | |||||
def read_doc_from_file(path): | |||||
doc = None | |||||
if os.path.exists(path): | if os.path.exists(path): | ||||
from frappe.modules.utils import peval_doclist | |||||
with open(path, 'r') as f: | with open(path, 'r') as f: | ||||
doclist = peval_doclist(f.read()) | |||||
doc = json.loads(f.read()) | |||||
else: | else: | ||||
raise Exception, '%s missing' % path | raise Exception, '%s missing' % path | ||||
return doclist | |||||
return doc | |||||
ignore_values = { | ignore_values = { | ||||
"Report": ["disabled"], | "Report": ["disabled"], | ||||
@@ -71,56 +67,32 @@ ignore_values = { | |||||
ignore_doctypes = ["Page Role", "DocPerm"] | 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 | old_doc = None | ||||
doctypes = set([d["doctype"] for d in doclist]) | |||||
ignore = list(doctypes.intersection(set(ignore_doctypes))) | |||||
if doctype in ignore_values: | 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 | # delete old | ||||
frappe.delete_doc(doctype, name, force=1, ignore_doctypes=ignore, for_reload=True) | 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() | |||||