Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions audit_management/audit_management/doctype/my_audits/my_audits.js
Original file line number Diff line number Diff line change
Expand Up @@ -2554,6 +2554,12 @@ function open_stages_modal(frm) {
label: "Employee Name",
read_only: 1,
},
{
fieldtype: "Data",
fieldname: "email",
in_list_view: 1,
label: "Email",
},
],
},
],
Expand Down Expand Up @@ -2593,6 +2599,7 @@ function open_stages_modal(frm) {
target_row.stage_name = row.stage_name;
target_row.employee = row.employee;
target_row.employee_name = row.employee_name;
target_row.email = row.email;
target_row.stage = idx + 1;
target_row.idx = idx + 1; // Required by Frappe for sequence tracking

Expand All @@ -2617,13 +2624,57 @@ function open_stages_modal(frm) {
},
});

// Fetch logic for employee field in the modal
d.fields_dict.temp_stages.grid.get_field("employee").get_query = function () {
return {
filters: {
status: "Active",
},
};
};

// 🌟 FIX: Fetch Email and Employee Name when Employee is selected in the modal
d.fields_dict.temp_stages.grid.on_row_add = function (doc, cdt, cdn) {
let row = locals[cdt][cdn];
};

// We use the grid's change trigger
d.fields_dict.temp_stages.grid.on_row_add = function (doc, cdt, cdn) {
// Optional: logic on row add
};

// Use model events if doctype is set, or grid events
// Since temp_stages doesn't have a doctype, we use the grid's control events
let grid = d.fields_dict.temp_stages.grid;
grid.wrapper.on("change", 'input[data-fieldname="employee"]', function (e) {
let $input = $(e.currentTarget);
let name = $input.closest(".grid-row").attr("data-name");
let row = grid.get_row(name).doc;

if (row.employee) {
frappe.call({
method:
"audit_management.audit_management.doctype.my_audits.my_audits.fetch_employee_data",
args: { employee_id: row.employee },
callback: function (r) {
if (r.message) {
row.employee_name = r.message.employee_name;
row.email = r.message.company_email;
grid.refresh();
}
},
});
}
});

// Populate the modal with data, binding the exact Database ID to 'stage_id'
let existing_data = (frm.doc.audit_stages || []).map((row) => {
return {
stage_id: row.name, // Link to the original memory row
stage_name: row.stage_name,
employee: row.employee,
employee_name: row.employee_name,
email: row.email,
};
});

Expand Down
69 changes: 53 additions & 16 deletions audit_management/audit_management/doctype/my_audits/my_audits.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ def sync_new_to_old(self):
self.set(f"{prefix}_user_status", row.status)
self.set(f"{prefix}_response_box", row.response)
self.set(f"{prefix}_attach_box", row.attachment)
self.set(f"{prefix}_mail", row.email)
if row.pending_time:
self.set(f"{prefix}_pending_time", row.pending_time)

Expand Down Expand Up @@ -829,6 +830,9 @@ def get_permission_query_conditions(user=None):

from frappe.utils import now, time_diff_in_seconds, time_diff_in_hours, getdate, nowdate, format_datetime

from frappe.utils import now, time_diff_in_seconds, time_diff_in_hours, getdate, nowdate, format_datetime
import json

@frappe.whitelist()
def get_audit_history_summary(docname):
doc = frappe.get_doc("My Audits", docname)
Expand All @@ -838,45 +842,78 @@ def get_full_name(user_id):
if user_id == "System/Audit Team": return "System/Audit Team"
return frappe.db.get_value("User", user_id, "full_name") or user_id

# Formatted History List
history = []

# Creator Info
# 1. Capture Creation
history.append({
"event": "Query Created",
"user": doc.query_generated_by_name or get_full_name(doc.owner),
"date": format_datetime(doc.creation, "dd-MM-yyyy hh:mm a"),
"status": "Created"
"status": "Created",
"timestamp": doc.creation
})

# Stages Info
# 2. Capture Stage Assignments and Responses from child table
creator_name = doc.query_generated_by_name or get_full_name(doc.owner)
for row in doc.audit_stages:
if row.status or row.pending_time:
history.append({
"event": f"Assigned to {row.stage_name} ({row.employee_name})",
"user": creator_name,
"date": format_datetime(row.pending_time, "dd-MM-yyyy hh:mm a") if row.pending_time else "",
"status": "Pending"
"status": "Pending",
"timestamp": row.pending_time if row.pending_time else doc.creation
})
if row.status == "Responded":
history.append({
"event": f"Response from {row.stage_name}",
"user": row.employee_name,
"date": format_datetime(row.response_time, "dd-MM-yyyy hh:mm a") if row.response_time else "",
"status": "Responded"
"status": "Responded",
"timestamp": row.response_time if row.response_time else doc.creation
})

# Closure Info
if doc.status == "Closed":
# Attempt to find who closed it
closed_by_id = frappe.db.get_value("Version", {"ref_doctype": "My Audits", "docname": doc.name, "data": ["like", "%status%Closed%"]}, "owner")
history.append({
"event": "Query Closed",
"user": get_full_name(closed_by_id) or "System/Audit Team",
"date": format_datetime(str(doc.closing_date) + " 00:00:00", "dd-MM-yyyy hh:mm a") if doc.closing_date else "",
"status": "Closed"
})
# 3. Capture status transitions (Closed/Reopened) from Version history
versions = frappe.get_all(
"Version",
filters={"ref_doctype": "My Audits", "docname": docname},
fields=["data", "owner", "creation"],
order_by="creation asc"
)

for version in versions:
try:
version_data = json.loads(version.data)
# Some versions contain a list of changed fields in 'changed' key
changed_fields = version_data.get("changed", [])

for field in changed_fields:
# field is usually a list: [fieldname, old_value, new_value]
if len(field) == 3 and field[0] == "status":
old_val = field[1]
new_val = field[2]

if new_val == "Closed":
history.append({
"event": "Query Closed",
"user": get_full_name(version.owner),
"date": format_datetime(version.creation, "dd-MM-yyyy hh:mm a"),
"status": "Closed",
"timestamp": version.creation
})
elif old_val == "Closed" and new_val != "Closed":
history.append({
"event": "Query Reopened",
"user": get_full_name(version.owner),
"date": format_datetime(version.creation, "dd-MM-yyyy hh:mm a"),
"status": "Reopened",
"timestamp": version.creation
})
except Exception:
pass

# Sort history by timestamp
history.sort(key=lambda x: x["timestamp"])

return history

Expand Down
Loading