diff --git a/one_compliance/one_compliance/doctype/task_assigning_tool/task_assigning_tool.js b/one_compliance/one_compliance/doctype/task_assigning_tool/task_assigning_tool.js index adbf4ca1..c32330a6 100644 --- a/one_compliance/one_compliance/doctype/task_assigning_tool/task_assigning_tool.js +++ b/one_compliance/one_compliance/doctype/task_assigning_tool/task_assigning_tool.js @@ -2,6 +2,81 @@ // For license information, please see license.txt frappe.ui.form.on('Task Assigning Tool', { + + assignment_type: function(frm) { + if (frm.doc.assignment_type === "Remove") { + frm.toggle_display('employee', true); + frm.toggle_display('assign_from', false); + frm.toggle_display('assign_to', false); + frm.toggle_display('assign', false); + } else if (frm.doc.assignment_type === "Transfer") { + frm.toggle_display('employee', false); + frm.toggle_display('assign_from', true); + frm.toggle_display('assign_to', true); + frm.toggle_display('assign', true); + } + clear_values(frm); + }, + + employee: function(frm) { + if (frm.doc.assignment_type === "Remove" && frm.doc.employee) { + frappe.call({ + method: 'one_compliance.one_compliance.doctype.task_assigning_tool.task_assigning_tool.get_tasks_for_employee', + args: { + assign_from: frm.doc.employee, + assignment_type: frm.doc.assignment_type + }, + callback: function(r) { + if (r.message) { + frm.clear_table('task_removal'); + r.message.forEach(task => { + let assigned_task = frm.add_child('task_removal'); + assigned_task.task_id = task.task_id; + assigned_task.subject = task.subject; + assigned_task.project = task.project; + }); + frm.refresh_field('task_removal'); + } + } + }); + } + }, + + remove_assignments: function(frm) { + if (!frm.doc.employee) { + frappe.msgprint("Please select an employee."); + return; + } + + // Get only checked rows + const selectedTaskIds = (frm.doc.task_removal || []) + .filter(row => row.__checked === 1) // Make sure only selected checkboxes are used + .map(row => row.task_id); + + if (selectedTaskIds.length === 0) { + frappe.msgprint("Please select at least one task to remove."); + return; + } + + frappe.call({ + method: "one_compliance.one_compliance.doctype.task_assigning_tool.task_assigning_tool.remove_task_assignments", + args: { + employee: frm.doc.employee, + selected_tasks_json: JSON.stringify(selectedTaskIds) + }, + freeze: true, + freeze_message: "Removing selected task assignments...", + callback: function(r) { + if (r.message === "Assignments removed successfully") { + frappe.msgprint("Selected assignments removed successfully."); + frm.trigger("employee"); // Re-fetch tasks + } else { + frappe.msgprint("Error: " + r.message); + } + } + }); + }, + refresh: function(frm) { frm.disable_save(); frm.toggle_display('add_to_subcategories', false); @@ -38,7 +113,7 @@ frappe.ui.form.on('Task Assigning Tool', { var selectedTaskIds = selectedRows.map(function(rowName) { var row = frm.doc.task_reassigns.find(r => r.name === rowName); return row && row.task_id; - }).filter(Boolean); + }).filter(Boolean); frappe.call({ method: 'one_compliance.one_compliance.doctype.task_assigning_tool.task_assigning_tool.reassign_tasks', @@ -60,7 +135,7 @@ frappe.ui.form.on('Task Assigning Tool', { } }); }, - + compliance_categories: function(frm) { // Get the selected Compliance Category var selectedCategory = frm.doc.compliance_categories; @@ -283,4 +358,4 @@ function fetchEmployeeName(user_id, callback) { } } }); -} \ No newline at end of file +} diff --git a/one_compliance/one_compliance/doctype/task_assigning_tool/task_assigning_tool.json b/one_compliance/one_compliance/doctype/task_assigning_tool/task_assigning_tool.json index 73481fa0..4e9eef03 100644 --- a/one_compliance/one_compliance/doctype/task_assigning_tool/task_assigning_tool.json +++ b/one_compliance/one_compliance/doctype/task_assigning_tool/task_assigning_tool.json @@ -19,6 +19,9 @@ "assign", "task_reassigns_section", "task_reassigns", + "task_removal_section", + "task_removal", + "remove_assignments", "section_break_fyzdz", "compliance_categories", "compliance_executives" @@ -33,7 +36,7 @@ "options": "Department" }, { - "depends_on": "eval: doc.assignment_type == 'Assign'", + "depends_on": "eval: doc.assignment_type == 'Assign' || doc.assignment_type == 'Remove'", "fieldname": "employee", "fieldtype": "Link", "label": "Employee", @@ -43,7 +46,7 @@ "fieldname": "assignment_type", "fieldtype": "Select", "label": "Assignment Type", - "options": "\nTransfer\nAssign", + "options": "\nTransfer\nAssign\nRemove", "reqd": 1 }, { @@ -91,7 +94,7 @@ "label": "Assign" }, { - "depends_on": "eval: doc.employee", + "depends_on": "eval: doc.employee && doc.assignment_type == 'Assign'", "fieldname": "compliance_categories", "fieldtype": "Link", "label": "Compliance Categories", @@ -119,13 +122,31 @@ "fieldname": "add_to_subcategories", "fieldtype": "Button", "label": "Add To Subcategories" + }, + { + "fieldname": "task_removal_section", + "fieldtype": "Section Break", + "label": "Task Removal" + }, + { + "depends_on": "eval:doc.assignment_type == 'Remove' && doc.employee", + "fieldname": "task_removal", + "fieldtype": "Table", + "label": "Task Removal", + "options": "Task Reassign" + }, + { + "depends_on": "eval:doc.assignment_type == 'Remove' && doc.employee", + "fieldname": "remove_assignments", + "fieldtype": "Button", + "label": "Remove Assignments" } ], "hide_toolbar": 1, "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-11-01 12:05:00.127334", + "modified": "2025-08-05 19:39:38.456051", "modified_by": "Administrator", "module": "One Compliance", "name": "Task Assigning Tool", @@ -162,6 +183,7 @@ "write": 1 } ], + "row_format": "Dynamic", "sort_field": "modified", "sort_order": "DESC", "states": [] diff --git a/one_compliance/one_compliance/doctype/task_assigning_tool/task_assigning_tool.py b/one_compliance/one_compliance/doctype/task_assigning_tool/task_assigning_tool.py index 1de4061a..4ead19e0 100644 --- a/one_compliance/one_compliance/doctype/task_assigning_tool/task_assigning_tool.py +++ b/one_compliance/one_compliance/doctype/task_assigning_tool/task_assigning_tool.py @@ -18,23 +18,34 @@ def get_users_by_department(doctype, txt, searchfield, start, page_len, filters) exclude_email = filters.get("exclude_email") department = filters.get("department") + # Step 1: Get employees in the department, excluding those with status "Left" employees = frappe.get_all( "Employee", - filters={"department": department}, - fields=["user_id"], + filters={ + "department": department, + "status": ["!=", "Left"] + }, + fields=["user_id"] ) - user_ids = [emp.user_id for emp in employees if emp.user_id] - if not user_ids: - return [] + # Step 2: Build list of user_ids from valid employees + user_ids = [emp.user_id for emp in employees if emp.user_id] + # Step 3: Remove the excluded user if present if exclude_email in user_ids: user_ids.remove(exclude_email) + if not user_ids: + return [] + + # Step 4: Fetch users by user_ids without checking if enabled users = frappe.get_all( "User", - filters={"name": ["in", user_ids], "enabled": 1}, - or_filters=[["name", "like", f"%{txt}%"], ["full_name", "like", f"%{txt}%"]], + filters={"name": ["in", user_ids]}, + or_filters=[ + ["name", "like", f"%{txt}%"], + ["full_name", "like", f"%{txt}%"] + ], fields=["name", "full_name"], start=start, page_length=page_len, @@ -42,7 +53,6 @@ def get_users_by_department(doctype, txt, searchfield, start, page_len, filters) return [(user["name"], user["full_name"]) for user in users] - @frappe.whitelist() def reassign_tasks(assign_from, assign_to, selected_tasks_json): selected_tasks = frappe.parse_json(selected_tasks_json) @@ -87,7 +97,7 @@ def reassign_tasks(assign_from, assign_to, selected_tasks_json): "doctype": "ToDo", "owner": assign_to, "allocated_to": assign_to, - "assigned_by": assign_from, + "assigned_by": frappe.session.user, "reference_type": "Task", "reference_name": task_id, "description": f"Task reassigned from {assign_from}", @@ -240,3 +250,67 @@ def get_tasks_for_user(assign_from): {"task_id": task.name, "subject": task.subject, "project": task.project} for task in tasks ] +@frappe.whitelist() +def get_tasks_for_employee(assign_from, assignment_type=None): + # Query tasks from the ToDo doctype + tasks = frappe.get_all('ToDo', filters={'allocated_to': assign_from, 'status': 'Open'}, fields=['reference_type', 'reference_name', 'description']) + + task_details = [] + for task in tasks: + reference_type = task.reference_type + reference_id = task.reference_name + task_description = task.description + if reference_type == 'Task': + # Fetch details from the Task doctype based on the task_id + task_details_query = frappe.get_all('Task', filters={'name': reference_id}, fields=['subject', 'project']) + if task_details_query: + task_details.append({ + 'task_id': reference_id, + 'subject': task_details_query[0]['subject'], + 'project': task_details_query[0]['project'] + }) + elif reference_type == 'Project' and assignment_type != 'Remove': + + # Fetch task details from the Task doctype based on the project_name + tasks_for_project = frappe.get_all('Task', filters={'project': reference_id}, fields=['name', 'project', 'subject']) + project_task_details = [] + for task in tasks_for_project: + project_task_details.append({ + 'task_id': task.name, + 'subject': task.subject, + 'project': task.project + }) + task_details.extend(project_task_details) + return task_details + +@frappe.whitelist() +def remove_task_assignments(employee, selected_tasks_json): + import json + + try: + selected_tasks = json.loads(selected_tasks_json) + + if not selected_tasks: + return "No tasks selected." + + for task_id in selected_tasks: + # Get ToDos for the given employee and task + todos = frappe.get_all("ToDo", filters={ + "reference_type": "Task", + "reference_name": task_id, + "allocated_to": employee, + "status": "Open" + }, fields=["name"]) + + # Cancel each ToDo (no need to touch Task.assigned_to) + for todo in todos: + todo_doc = frappe.get_doc("ToDo", todo.name) + todo_doc.status = "Cancelled" + todo_doc.save(ignore_permissions=True) + + frappe.db.commit() + return "Assignments removed successfully" + + except Exception as e: + frappe.log_error(frappe.get_traceback(), "Task Assignment Removal Error") + return f"Error occurred: {str(e)}"