From 10a5900ed3d792653623d97da4a3128737f03f63 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 27 Jul 2020 19:47:46 +0530 Subject: [PATCH 1/3] fix: Attach files to the document if they are set programmatically --- frappe/core/doctype/file/file.py | 37 ++++++++++++++++++++++++++++++++ frappe/hooks.py | 3 ++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/frappe/core/doctype/file/file.py b/frappe/core/doctype/file/file.py index 1748c60020..316915e43a 100755 --- a/frappe/core/doctype/file/file.py +++ b/frappe/core/doctype/file/file.py @@ -922,3 +922,40 @@ def update_existing_file_docs(doc): content_hash=doc.content_hash, file_name=doc.name )) + +def attach_files_to_document(doc, event): + """ Runs on on_update hook of all documents. + Goes through every Attach and Attach Image field and attaches + the file url to the document if it is not already attached. + """ + + attach_fields = doc.meta.get( + "fields", {"fieldtype": ["in", ["Attach", "Attach Image"]]} + ) + + for df in attach_fields: + # this method runs in on_update hook of all documents + # we dont want the update to fail if file cannot be attached for some reason + try: + value = doc.get(df.fieldname) + if not value.startswith(("/files", "/private/files")): + return + + if frappe.db.exists("File", { + "file_url": value, + "attached_to_name": doc.name, + "attached_to_doctype": doc.doctype, + "attached_to_field": df.fieldname, + }): + return + + frappe.get_doc( + doctype="File", + file_url=value, + attached_to_name=doc.name, + attached_to_doctype=doc.doctype, + attached_to_field=df.fieldname, + folder="Home/Attachments", + ).insert() + except Exception: + frappe.log_error(title=_("Error Attaching File")) diff --git a/frappe/hooks.py b/frappe/hooks.py index 1f209f00a2..0a3d5d011c 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -132,7 +132,8 @@ doc_events = { "frappe.core.doctype.activity_log.feed.update_feed", "frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions", "frappe.automation.doctype.assignment_rule.assignment_rule.apply", - "frappe.automation.doctype.milestone_tracker.milestone_tracker.evaluate_milestone" + "frappe.automation.doctype.milestone_tracker.milestone_tracker.evaluate_milestone", + "frappe.core.doctype.file.file.attach_files_to_document" ], "after_rename": "frappe.desk.notifications.clear_doctype_notifications", "on_cancel": [ From eb87e6b77358c8bddd860cea90592d08891871bb Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Fri, 21 Aug 2020 13:30:20 +0530 Subject: [PATCH 2/3] fix: Set fieldname when attaching to field --- frappe/public/js/frappe/file_uploader/FileUploader.vue | 7 +++++++ frappe/public/js/frappe/file_uploader/index.js | 2 ++ frappe/public/js/frappe/form/controls/attach.js | 1 + 3 files changed, 10 insertions(+) diff --git a/frappe/public/js/frappe/file_uploader/FileUploader.vue b/frappe/public/js/frappe/file_uploader/FileUploader.vue index 845fbf92b4..f8d9253931 100644 --- a/frappe/public/js/frappe/file_uploader/FileUploader.vue +++ b/frappe/public/js/frappe/file_uploader/FileUploader.vue @@ -144,6 +144,9 @@ export default { docname: { default: null }, + fieldname: { + default: null + }, folder: { default: 'Home' }, @@ -406,6 +409,10 @@ export default { form_data.append('docname', this.docname); } + if (this.fieldname) { + form_data.append('fieldname', this.fieldname); + } + if (this.method) { form_data.append('method', this.method); } diff --git a/frappe/public/js/frappe/file_uploader/index.js b/frappe/public/js/frappe/file_uploader/index.js index f81a1f1776..62a7bff822 100644 --- a/frappe/public/js/frappe/file_uploader/index.js +++ b/frappe/public/js/frappe/file_uploader/index.js @@ -7,6 +7,7 @@ export default class FileUploader { on_success, doctype, docname, + fieldname, files, folder, restrictions, @@ -28,6 +29,7 @@ export default class FileUploader { show_upload_button: !Boolean(this.dialog), doctype, docname, + fieldname, method, folder, on_success, diff --git a/frappe/public/js/frappe/form/controls/attach.js b/frappe/public/js/frappe/form/controls/attach.js index 15cbd3b043..fe662c1ada 100644 --- a/frappe/public/js/frappe/form/controls/attach.js +++ b/frappe/public/js/frappe/form/controls/attach.js @@ -66,6 +66,7 @@ frappe.ui.form.ControlAttach = frappe.ui.form.ControlData.extend({ if (this.frm) { options.doctype = this.frm.doctype; options.docname = this.frm.docname; + options.fieldname = this.df.fieldname; } if (this.df.options) { From 85cac9122e9e2d9a478d455e3049ef47f38d9a9e Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Fri, 21 Aug 2020 13:31:07 +0530 Subject: [PATCH 3/3] test: For file attachment on update --- frappe/core/doctype/file/test_file.py | 46 +++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/frappe/core/doctype/file/test_file.py b/frappe/core/doctype/file/test_file.py index ec4f97bf67..85397ea1ee 100644 --- a/frappe/core/doctype/file/test_file.py +++ b/frappe/core/doctype/file/test_file.py @@ -328,3 +328,49 @@ class TestFile(unittest.TestCase): self.assertTrue(os.path.exists(file2.get_full_path())) +class TestAttachment(unittest.TestCase): + test_doctype = 'Test For Attachment' + + def setUp(self): + if frappe.db.exists('DocType', self.test_doctype): + return + + frappe.get_doc( + doctype='DocType', + name=self.test_doctype, + module='Custom', + custom=1, + fields=[ + {'label': 'Title', 'fieldname': 'title', 'fieldtype': 'Data'}, + {'label': 'Attachment', 'fieldname': 'attachment', 'fieldtype': 'Attach'}, + ] + ).insert() + + def tearDown(self): + frappe.delete_doc('DocType', self.test_doctype) + + def test_file_attachment_on_update(self): + doc = frappe.get_doc( + doctype=self.test_doctype, + title='test for attachment on update' + ).insert() + + file = frappe.get_doc({ + 'doctype': 'File', + 'file_name': 'test_attach.txt', + 'content': 'Test Content' + }) + file.save() + + doc.attachment = file.file_url + doc.save() + + exists = frappe.db.exists('File', { + 'file_name': 'test_attach.txt', + 'file_url': file.file_url, + 'attached_to_doctype': self.test_doctype, + 'attached_to_name': doc.name, + 'attached_to_field': 'attachment' + }) + + self.assertTrue(exists)