diff --git a/frappe/core/doctype/submission_queue/submission_queue.py b/frappe/core/doctype/submission_queue/submission_queue.py
index dc0cbba962..0c53fe3ddf 100644
--- a/frappe/core/doctype/submission_queue/submission_queue.py
+++ b/frappe/core/doctype/submission_queue/submission_queue.py
@@ -168,9 +168,9 @@ def queue_submission(doc: Document, action: str, alert: bool = True):
"Submission Queue", {"ref_doctype": doc.doctype, "ref_docname": doc.name, "status": "Queued"}
):
frappe.msgprint(
- _(
- "This document has already been queued for submission. You can track the progress over {0}."
- ).format(f"here"),
+ _("This document has already been queued for {0}. You can track the progress over {1}.").format(
+ action, f"here"
+ ),
indicator="orange",
alert=True,
)
@@ -183,8 +183,8 @@ def queue_submission(doc: Document, action: str, alert: bool = True):
if alert:
frappe.msgprint(
- _("Queued for Submission. You can track the progress over {0}.").format(
- f"here"
+ _("Queued for {0}. You can track the progress over {1}.").format(
+ action, f"here"
),
indicator="green",
alert=True,
diff --git a/frappe/core/doctype/submission_queue/test_submission_queue.py b/frappe/core/doctype/submission_queue/test_submission_queue.py
index afecd49709..b88b3a37b5 100644
--- a/frappe/core/doctype/submission_queue/test_submission_queue.py
+++ b/frappe/core/doctype/submission_queue/test_submission_queue.py
@@ -51,3 +51,71 @@ class TestSubmissionQueue(IntegrationTestCase):
job = self.queue.fetch_job(submission_queue.job_id)
# Test completion
self.check_status(job, status="finished")
+
+ def test_cancel_operation(self):
+ from frappe.core.doctype.doctype.test_doctype import new_doctype
+ from frappe.core.doctype.submission_queue.submission_queue import queue_submission
+
+ if not frappe.db.table_exists("Test Submission Queue", cached=False):
+ doc = new_doctype("Test Submission Queue", is_submittable=True, queue_in_background=True)
+ doc.insert()
+
+ d = frappe.new_doc("Test Submission Queue")
+ d.update({"some_fieldname": "Random"})
+ d.insert()
+ d.submit()
+ frappe.db.commit()
+
+ self.assertEqual(d.docstatus, 1)
+
+ queue_submission(d, "Cancel")
+ frappe.db.commit()
+
+ time.sleep(4)
+ submission_queue = frappe.get_last_doc("Submission Queue")
+
+ job = self.queue.fetch_job(submission_queue.job_id)
+ self.check_status(job, status="finished")
+
+ d.reload()
+ self.assertEqual(d.docstatus, 2)
+
+ def test_cancel_on_cancelled_doc(self):
+ from frappe.core.doctype.doctype.test_doctype import new_doctype
+ from frappe.core.doctype.submission_queue.submission_queue import queue_submission
+
+ if not frappe.db.table_exists("Test Submission Queue", cached=False):
+ doc = new_doctype("Test Submission Queue", is_submittable=True, queue_in_background=True)
+ doc.insert()
+
+ d = frappe.new_doc("Test Submission Queue")
+ d.update({"some_fieldname": "Random"})
+ d.insert()
+ d.submit()
+ frappe.db.commit()
+
+ existing = frappe.get_doc(
+ {
+ "doctype": "Submission Queue",
+ "ref_doctype": d.doctype,
+ "ref_docname": d.name,
+ "status": "Queued",
+ }
+ )
+ existing.insert(d, "Cancel")
+ frappe.db.commit()
+
+ initial_count = frappe.db.count(
+ "Submission Queue", {"ref_doctype": d.doctype, "ref_docname": d.name, "status": "Queued"}
+ )
+
+ queue_submission(d, "Cancel")
+
+ final_count = frappe.db.count(
+ "Submission Queue", {"ref_doctype": d.doctype, "ref_docname": d.name, "status": "Queued"}
+ )
+
+ self.assertEqual(initial_count, final_count)
+
+ existing.delete(ignore_permissions=True)
+ frappe.db.commit()
diff --git a/frappe/desk/form/save.py b/frappe/desk/form/save.py
index c37d7452eb..4b15caaabd 100644
--- a/frappe/desk/form/save.py
+++ b/frappe/desk/form/save.py
@@ -64,6 +64,11 @@ def cancel(
if workflow_state_fieldname and workflow_state:
doc.set(workflow_state_fieldname, workflow_state)
+
+ if doc.meta.queue_in_background and not is_scheduler_inactive():
+ queue_submission(doc, "Cancel")
+ return
+
doc.cancel()
send_updated_docs(doc)
frappe.msgprint(frappe._("Cancelled"), indicator="red", alert=True)
diff --git a/frappe/model/workflow.py b/frappe/model/workflow.py
index b0f58da46e..d3e0d1cf4d 100644
--- a/frappe/model/workflow.py
+++ b/frappe/model/workflow.py
@@ -218,6 +218,10 @@ def apply_workflow(doc: Document | str | dict, action: str):
elif doc.docstatus.is_submitted() and new_docstatus.is_submitted():
doc.save()
elif doc.docstatus.is_submitted() and new_docstatus.is_cancelled():
+ if doc.meta.queue_in_background and not is_scheduler_inactive():
+ queue_submission(doc, "Cancel")
+ return
+
doc.cancel()
else:
frappe.throw(_("Illegal Document Status for {0}").format(next_state.state))
diff --git a/frappe/public/js/frappe/form/form.js b/frappe/public/js/frappe/form/form.js
index cdbeca6dd0..381f5daa34 100644
--- a/frappe/public/js/frappe/form/form.js
+++ b/frappe/public/js/frappe/form/form.js
@@ -2270,7 +2270,7 @@ frappe.ui.form.Form = class FrappeForm {
this.meta.is_submittable &&
this.meta.queue_in_background &&
!this.doc.__islocal &&
- this.doc.docstatus === 0
+ this.doc.docstatus <= 1
)
) {
wrapper.length && wrapper.remove();
@@ -2288,7 +2288,7 @@ frappe.ui.form.Form = class FrappeForm {
args: { doctype: this.doctype, docname: this.docname },
})
.then((r) => {
- if (r.message?.latest_submission) {
+ if (r.message?.latest_submission && r.message.status !== "Finished") {
// if we are here that means some submission(s) were queued and are in queued/failed state
let submission_label = __("Previous Submission");
let secondary = "";