fix: relink attachments before saving doc
Certain people add attachment, before filling mandatory fields which will raise Missing Fields error. Or any other kind of errors raised by different validators due to which file is uploaded but doc is not saved. This will lead to orphaned/mislinked files. ex. new-purchase-receipt-1 This fix changes name of new docs to new-<doctype>-<no>-<10digithash> after saving the document we can use this new name to find any mislinked files created in past hour and relink them to the new doc on save.
This commit is contained in:
parent
009d9e010b
commit
53cdd6d1bf
5 changed files with 60 additions and 2 deletions
|
|
@ -339,6 +339,7 @@ def attach_files_to_document(doc: "Document", event) -> None:
|
|||
"attached_to_name": doc.name,
|
||||
"attached_to_doctype": doc.doctype,
|
||||
"attached_to_field": df.fieldname,
|
||||
"is_private": value.startswith("/private"),
|
||||
},
|
||||
)
|
||||
continue
|
||||
|
|
@ -357,6 +358,49 @@ def attach_files_to_document(doc: "Document", event) -> None:
|
|||
doc.log_error("Error Attaching File")
|
||||
|
||||
|
||||
def relink_files(doc, fieldname, temp_doc_name):
|
||||
from frappe.utils.data import add_to_date, now_datetime
|
||||
|
||||
"""
|
||||
Relink files attached to incorrect document name to the new document name
|
||||
by check if file with temp name exists that was created in last 60 minutes
|
||||
"""
|
||||
mislinked_file = frappe.db.exists(
|
||||
"File",
|
||||
{
|
||||
"file_url": doc.get(fieldname),
|
||||
"attached_to_name": temp_doc_name,
|
||||
"attached_to_doctype": doc.doctype,
|
||||
"attached_to_field": fieldname,
|
||||
"creation": (
|
||||
"between",
|
||||
[now_datetime() - add_to_date(date=now_datetime(), minutes=-60), now_datetime()],
|
||||
),
|
||||
},
|
||||
)
|
||||
"""If file exists, attach it to the new docname"""
|
||||
if mislinked_file:
|
||||
frappe.db.set_value(
|
||||
"File",
|
||||
mislinked_file,
|
||||
field={
|
||||
"attached_to_name": doc.name,
|
||||
"attached_to_doctype": doc.doctype,
|
||||
"attached_to_field": fieldname,
|
||||
},
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
def relink_mismatched_files(doc: "Document") -> None:
|
||||
if not doc.get("file_relink_temp_docname", None):
|
||||
return
|
||||
attach_fields = doc.meta.get("fields", {"fieldtype": ["in", ["Attach", "Attach Image"]]})
|
||||
for df in attach_fields:
|
||||
if doc.get(df.fieldname):
|
||||
relink_files(doc, df.fieldname, doc.file_relink_temp_docname)
|
||||
|
||||
|
||||
def decode_file_content(content: bytes) -> bytes:
|
||||
if isinstance(content, str):
|
||||
content = content.encode("utf-8")
|
||||
|
|
|
|||
|
|
@ -17,6 +17,10 @@ def savedocs(doc, action):
|
|||
"""save / submit / update doclist"""
|
||||
doc = frappe.get_doc(json.loads(doc))
|
||||
capture_doc(doc, action)
|
||||
if doc.doctype not in ["DocType", "File"] and doc.name.startswith(
|
||||
"new-" + doc.doctype.lower().replace(" ", "-")
|
||||
):
|
||||
doc.file_relink_temp_docname = doc.name
|
||||
set_local_name(doc)
|
||||
|
||||
# action
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from werkzeug.exceptions import NotFound
|
|||
|
||||
import frappe
|
||||
from frappe import _, is_whitelisted, msgprint
|
||||
from frappe.core.doctype.file.utils import relink_mismatched_files
|
||||
from frappe.core.doctype.server_script.server_script_utils import run_server_script_for_doc_event
|
||||
from frappe.desk.form.document_follow import follow_document
|
||||
from frappe.integrations.doctype.webhook import run_webhooks
|
||||
|
|
@ -304,6 +305,7 @@ class Document(BaseDocument):
|
|||
if self.get("amended_from"):
|
||||
self.copy_attachments_from_amended_from()
|
||||
|
||||
relink_mismatched_files(self)
|
||||
self.run_post_save_methods()
|
||||
self.flags.in_insert = False
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,8 @@ $.extend(frappe.model, {
|
|||
var cnt = frappe.model.new_name_count;
|
||||
if (!cnt[doctype]) cnt[doctype] = 0;
|
||||
cnt[doctype]++;
|
||||
return frappe.router.slug(`new-${doctype}-${cnt[doctype]}`);
|
||||
// random hash is added to idenity mislinked files when doc is not saved and file is uploaded.
|
||||
return frappe.router.slug(`new-${doctype}-${cnt[doctype]}${frappe.utils.get_random(10)}`);
|
||||
},
|
||||
|
||||
set_default_values: function (doc, parent_doc) {
|
||||
|
|
|
|||
|
|
@ -186,7 +186,14 @@ frappe.breadcrumbs = {
|
|||
|
||||
set_form_breadcrumb(breadcrumbs, view) {
|
||||
const doctype = breadcrumbs.doctype;
|
||||
const docname = frappe.get_route().slice(2).join("/");
|
||||
let docname = frappe.get_route().slice(2).join("/");
|
||||
if (docname.startsWith("new-" + doctype.toLowerCase().replace(/ /g, "-"))) {
|
||||
// using docname instead of doctype to include No like Doctype Name + 1, 2, 3
|
||||
docname = docname
|
||||
.slice(0, -10)
|
||||
.replace(/-/g, " ")
|
||||
.replace(/\b\w/g, (l) => l.toUpperCase());
|
||||
}
|
||||
let form_route = `/app/${frappe.router.slug(doctype)}/${docname}`;
|
||||
this.append_breadcrumb_element(form_route, __(docname));
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue