Parcourir la source

Fixed import, export, delete doc #478

version-14
Anand Doshi il y a 11 ans
Parent
révision
ddff84d216
4 fichiers modifiés avec 76 ajouts et 132 suppressions
  1. +3
    -6
      frappe/__init__.py
  2. +18
    -26
      frappe/model/delete_doc.py
  3. +24
    -41
      frappe/modules/export_file.py
  4. +31
    -59
      frappe/modules/import_file.py

+ 3
- 6
frappe/__init__.py Voir le fichier

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


+ 18
- 26
frappe/model/delete_doc.py Voir le fichier

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

+ 24
- 41
frappe/modules/export_file.py Voir le fichier

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


+ 31
- 59
frappe/modules/import_file.py Voir le fichier

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

Chargement…
Annuler
Enregistrer