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)