From 876598f71474f33a29bbf3cb691acba40aec6715 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 20 Aug 2025 21:55:04 +0530 Subject: [PATCH] fix: sub-operation not working --- .../doctype/job_card/job_card.js | 28 +++++++++++++++++-- .../doctype/job_card/job_card.py | 12 ++++++-- .../job_card_operation.json | 10 ++++--- .../job_card_time_log/job_card_time_log.json | 9 +++--- 4 files changed, 47 insertions(+), 12 deletions(-) diff --git a/erpnext/manufacturing/doctype/job_card/job_card.js b/erpnext/manufacturing/doctype/job_card/job_card.js index 21fec7c8afb..6469fada2ba 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.js +++ b/erpnext/manufacturing/doctype/job_card/job_card.js @@ -31,6 +31,16 @@ frappe.ui.form.on("Job Card", { }; }); + frm.set_query("operation", "time_logs", () => { + let operations = (frm.doc.sub_operations || []).map((d) => d.sub_operation); + return { + filters: { + name: ["in", operations], + }, + }; + }); + + frm.events.set_company_filters(frm, "target_warehouse"); frm.events.set_company_filters(frm, "source_warehouse"); frm.events.set_company_filters(frm, "wip_warehouse"); frm.set_query("source_warehouse", "items", () => { @@ -184,7 +194,12 @@ frappe.ui.form.on("Job Card", { !frm.doc.finished_good || !has_items?.length) ) { - if (!frm.doc.time_logs?.length) { + let last_row = {}; + if (frm.doc.sub_operations?.length && frm.doc.time_logs?.length) { + last_row = get_last_row(frm.doc.time_logs); + } + + if (!frm.doc.time_logs?.length || (frm.doc.sub_operations?.length && last_row?.to_time)) { frm.add_custom_button(__("Start Job"), () => { let from_time = frappe.datetime.now_datetime(); if ((frm.doc.employee && !frm.doc.employee.length) || !frm.doc.employee) { @@ -313,7 +328,12 @@ frappe.ui.form.on("Job Card", { ]; let last_completed_row = get_last_completed_row(frm.doc.time_logs); - if (!last_completed_row || !last_completed_row.to_time) { + let last_row = {}; + if (frm.doc.sub_operations?.length && frm.doc.time_logs?.length) { + last_row = get_last_row(frm.doc.time_logs); + } + + if (!last_completed_row || !last_completed_row.to_time || !last_row.to_time) { fields.push({ fieldtype: "Datetime", label: __("End Time"), @@ -758,3 +778,7 @@ function get_last_completed_row(time_logs) { return last_completed_row; } } + +function get_last_row(time_logs) { + return time_logs[time_logs.length - 1] || {}; +} diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index 868e09f3a06..a20c2e12043 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -157,6 +157,9 @@ class JobCard(Document): self.validate_sequence_id() self.set_sub_operations() self.update_sub_operation_status() + if self.sub_operations: + self.set_total_completed_qty_from_sub_operations() + self.validate_work_order() def on_update(self): @@ -280,8 +283,13 @@ class JobCard(Document): } ) + def set_total_completed_qty_from_sub_operations(self): + sub_op_total_qty = [] for row in self.sub_operations: - self.total_completed_qty += row.completed_qty + sub_op_total_qty.append(flt(row.completed_qty)) + + if sub_op_total_qty: + self.total_completed_qty = min(sub_op_total_qty) def get_overlap_for(self, args, open_job_cards=None): time_logs = [] @@ -613,7 +621,7 @@ class JobCard(Document): self.save() def update_sub_operation_status(self): - if not (self.sub_operations and self.time_logs): + if not self.sub_operations: return operation_wise_completed_time = {} diff --git a/erpnext/manufacturing/doctype/job_card_operation/job_card_operation.json b/erpnext/manufacturing/doctype/job_card_operation/job_card_operation.json index 8b3e90872de..a2df1425989 100644 --- a/erpnext/manufacturing/doctype/job_card_operation/job_card_operation.json +++ b/erpnext/manufacturing/doctype/job_card_operation/job_card_operation.json @@ -6,9 +6,9 @@ "engine": "InnoDB", "field_order": [ "sub_operation", + "completed_qty", "completed_time", - "status", - "completed_qty" + "status" ], "fields": [ { @@ -39,6 +39,7 @@ { "fieldname": "completed_qty", "fieldtype": "Float", + "in_list_view": 1, "label": "Completed Qty", "read_only": 1 } @@ -46,15 +47,16 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2024-03-27 13:09:57.090298", + "modified": "2025-08-20 21:44:43.941434", "modified_by": "Administrator", "module": "Manufacturing", "name": "Job Card Operation", "owner": "Administrator", "permissions": [], "quick_entry": 1, + "row_format": "Dynamic", "sort_field": "creation", "sort_order": "DESC", "states": [], "track_changes": 1 -} \ No newline at end of file +} diff --git a/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.json b/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.json index d524b2996d2..32c544e037c 100644 --- a/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.json +++ b/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.json @@ -16,6 +16,7 @@ "fields": [ { "allow_on_submit": 1, + "columns": 3, "fieldname": "from_time", "fieldtype": "Datetime", "in_list_view": 1, @@ -58,17 +59,17 @@ { "fieldname": "operation", "fieldtype": "Link", - "label": "Operation", + "in_list_view": 1, + "label": "Sub Operation", "no_copy": 1, - "options": "Operation", - "read_only": 1 + "options": "Operation" } ], "grid_page_length": 50, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2025-08-04 15:47:11.748937", + "modified": "2025-08-20 21:49:59.084876", "modified_by": "Administrator", "module": "Manufacturing", "name": "Job Card Time Log",