diff --git a/audit_management/audit_management/doctype/audit_level/audit_level.py b/audit_management/audit_management/doctype/audit_level/audit_level.py
index 6d245ae..95f190f 100755
--- a/audit_management/audit_management/doctype/audit_level/audit_level.py
+++ b/audit_management/audit_management/doctype/audit_level/audit_level.py
@@ -12,12 +12,30 @@ def before_insert(self):
self.division = get_user_division()
def validate(self):
+ self.validate_duplicate()
if is_new_system_enabled():
self.remove_blank_rows()
self.update_employee_emails()
else:
self.sync_new_to_old_stages()
+ def validate_duplicate(self):
+ """Prevents duplicate record creation for same branch + division combo."""
+ duplicate = frappe.db.exists(
+ "Audit Level",
+ {
+ "sahayog_branch": self.sahayog_branch,
+ "division": self.division,
+ "name": ["!=", self.name]
+ }
+ )
+ if duplicate:
+ frappe.throw(
+ frappe._("An Audit Level configuration already exists for Branch: {0} and Division: {1}.").format(
+ self.sahayog_branch, self.division
+ )
+ )
+
def remove_blank_rows(self):
cleaned_rows = []
if hasattr(self, "audit_stages"):
diff --git a/audit_management/audit_management/doctype/my_audits/my_audits.js b/audit_management/audit_management/doctype/my_audits/my_audits.js
index 08d9e08..ed46037 100755
--- a/audit_management/audit_management/doctype/my_audits/my_audits.js
+++ b/audit_management/audit_management/doctype/my_audits/my_audits.js
@@ -1057,7 +1057,7 @@ frappe.ui.form.on("My Audits", {
if (frm.doc.status === "Close") return;
- // 1. DRAFT STATE: Only Audit Team can see "Raise Request" Action
+ // 1. DRAFT STATE: Only Audit Team can see "Raise Request" and "Send to All" Action
if (frm.doc.status === "Draft" && is_audit_team) {
frm
.add_custom_button(
@@ -1111,9 +1111,30 @@ frappe.ui.form.on("My Audits", {
__("Raise Request"),
);
},
- __("Actions"),
)
.css({ "background-color": "#007bff", color: "white" });
+
+ frm
+ .add_custom_button(
+ __("Send to All"),
+ function () {
+ frappe.confirm(__("Are you sure you want to send this query to all stages?"), () => {
+ frappe.call({
+ method: "audit_management.audit_management.doctype.my_audits.my_audits.send_to_all_stages",
+ args: { docname: frm.doc.name },
+ freeze: true,
+ freeze_message: "Sending to all stages...",
+ callback: function (r) {
+ if (r.message) {
+ frappe.show_alert({ message: r.message, indicator: "green" });
+ frm.reload_doc();
+ }
+ }
+ });
+ });
+ },
+ )
+ .css({ "background-color": "#6f42c1", color: "white" });
}
// 2. PENDING STATE: Find the exact row that is currently pending
@@ -1188,7 +1209,6 @@ frappe.ui.form.on("My Audits", {
function () {
frm.trigger("handle_close_query");
},
- __("Actions"),
)
.css({ "background-color": "#dc3545", color: "white" });
@@ -1213,7 +1233,6 @@ frappe.ui.form.on("My Audits", {
},
});
},
- __("Actions"),
)
.css({ "background-color": "#28a745", color: "white" });
}
@@ -2098,8 +2117,7 @@ frappe.ui.form.on("My Audits", {
// No Action
},
);
- },
- __("Actions"),
+ }
);
}
}
diff --git a/audit_management/audit_management/doctype/my_audits/my_audits.py b/audit_management/audit_management/doctype/my_audits/my_audits.py
index 2bf8a70..84e2a85 100755
--- a/audit_management/audit_management/doctype/my_audits/my_audits.py
+++ b/audit_management/audit_management/doctype/my_audits/my_audits.py
@@ -358,6 +358,33 @@ def create_status_box(text, color, title):
return html_output
+@frappe.whitelist()
+def send_to_all_stages(docname):
+ doc = frappe.get_doc("My Audits", docname)
+
+ if doc.status != "Draft":
+ frappe.throw("Only Draft requests can be sent to all stages.")
+
+ if not doc.get("audit_stages"):
+ frappe.throw("No stages found to assign.")
+
+ for row in doc.get("audit_stages"):
+ if row.user_id:
+ row.status = "Pending"
+ row.pending_time = frappe.utils.now()
+
+ # Share document
+ frappe.share.add(doc.doctype, doc.name, row.user_id, read=1, write=1, share=1, notify=0)
+
+ # Send Notification
+ send_stage_notification(doc, row, action="assign")
+
+ doc.status = "Pending"
+ doc.query_status = "Pending From All Stages"
+ doc.save(ignore_permissions=True)
+
+ return "Query sent to all stages successfully!"
+
@frappe.whitelist()
def send_to_next_stage(docname):
doc = frappe.get_doc("My Audits", docname)