diff --git a/erpnext/manufacturing/doctype/job_card/job_card.js b/erpnext/manufacturing/doctype/job_card/job_card.js index 366c2f1d33ed3d853c416af064795df2ead35a52..8dee4ffb5d6648759090c031a23b1283a89b5dd4 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.js +++ b/erpnext/manufacturing/doctype/job_card/job_card.js @@ -88,6 +88,11 @@ frappe.ui.form.on('Job Card', { frm.toggle_enable("for_quantity", !has_stock_entry); + if (frm.doc.docstatus != 0) { + frm.fields_dict["time_logs"].grid.update_docfield_property("completed_qty", "read_only", 1); + frm.fields_dict["time_logs"].grid.update_docfield_property("time_in_mins", "read_only", 1); + } + if (!frm.is_new() && !frm.doc.skip_material_transfer && has_items && frm.doc.docstatus < 2) { let to_request = frm.doc.for_quantity > frm.doc.transferred_qty; let excess_transfer_allowed = frm.doc.__onload.job_card_excess_transfer; @@ -221,13 +226,17 @@ frappe.ui.form.on('Job Card', { reqd: 1, default: frm.doc.for_quantity - frm.doc.total_completed_qty, }, - { + ]; + + let last_completed_row = get_last_completed_row(frm.doc.time_logs); + if (!last_completed_row || !last_completed_row.to_time) { + fields.push({ fieldtype: "Datetime", label: __("End Time"), fieldname: "end_time", default: frappe.datetime.now_datetime(), - }, - ]; + }); + } frappe.prompt( fields, @@ -614,8 +623,31 @@ frappe.ui.form.on('Job Card Time Log', { to_time: function (frm) { frm.set_value("started_time", ""); }, + + time_in_mins(frm, cdt, cdn) { + let d = locals[cdt][cdn]; + if (d.time_in_mins) { + d.to_time = add_mins_to_time(d.from_time, d.time_in_mins); + frappe.model.set_value(cdt, cdn, "to_time", d.to_time); + } + }, }); function get_seconds_diff(d1, d2) { return moment(d1).diff(d2, "seconds"); } + +function add_mins_to_time(datetime, mins) { + let new_date = moment(datetime).add(mins, "minutes"); + + return new_date.format("YYYY-MM-DD HH:mm:ss"); +} + +function get_last_completed_row(time_logs) { + let completed_rows = time_logs.filter((d) => d.to_time); + + if (completed_rows?.length) { + let last_completed_row = completed_rows[completed_rows.length - 1]; + return last_completed_row; + } +} diff --git a/erpnext/manufacturing/doctype/job_card/job_card.json b/erpnext/manufacturing/doctype/job_card/job_card.json index 95fb7a4c08c645372bfc57b66c7cdd8ba03c73e6..1f9ebbccff8dd638a8f0e1d339e82c10de774dd4 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.json +++ b/erpnext/manufacturing/doctype/job_card/job_card.json @@ -525,7 +525,7 @@ "fieldname": "finished_good", "fieldtype": "Link", "in_preview": 1, - "label": "Finished Good", + "label": "Item to Manufacture", "options": "Item", "read_only": 1 }, @@ -555,7 +555,7 @@ { "fieldname": "semi_fg_bom", "fieldtype": "Link", - "label": "Semi Finished Goods BOM", + "label": "Manufacturing BOM", "options": "BOM", "read_only": 1 }, @@ -612,9 +612,10 @@ "read_only": 1 } ], + "grid_page_length": 50, "is_submittable": 1, "links": [], - "modified": "2024-06-03 17:44:18.324743", + "modified": "2025-03-25 17:50:18.608869", "modified_by": "Administrator", "module": "Manufacturing", "name": "Job Card", @@ -667,6 +668,7 @@ "write": 1 } ], + "row_format": "Dynamic", "show_preview_popup": 1, "sort_field": "creation", "sort_order": "DESC", diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index 726b19c6e11ff71230ca53a65dc8ee6a73c35e75..89715f6b780cabf3fa6d482ed8499cad8dd38b5b 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -1188,6 +1188,14 @@ class JobCard(Document): row = self.append("time_logs", kwargs) row.db_update() self.db_set("status", "Work In Progress") + elif not kwargs.from_time and not kwargs.to_time and kwargs.completed_qty: + update_status = True + for row in self.time_logs: + if row.employee != kwargs.employee: + continue + + row.completed_qty = kwargs.completed_qty + row.db_update() else: update_status = True for row in self.time_logs: @@ -1248,6 +1256,9 @@ class JobCard(Document): if kwargs.end_time: self.add_time_logs(to_time=kwargs.end_time, completed_qty=kwargs.qty, employees=self.employee) self.save() + else: + self.add_time_logs(completed_qty=kwargs.qty, employees=self.employee) + self.save() if kwargs.auto_submit: self.submit() @@ -1420,9 +1431,19 @@ def make_stock_entry(source_name, target_doc=None): target.qty = pending_rm_qty def set_missing_values(source, target): + if source.finished_good and not source.target_warehouse: + frappe.throw(_("Please set the Target Warehouse in the Job Card")) + + if not source.skip_material_transfer or source.backflush_from_wip_warehouse: + if not source.wip_warehouse: + frappe.throw(_("Please set the WIP Warehouse in the Job Card")) + target.purpose = "Material Transfer for Manufacture" target.from_bom = 1 + if source.semi_fg_bom: + target.bom_no = source.semi_fg_bom + # avoid negative 'For Quantity' pending_fg_qty = flt(source.get("for_quantity", 0)) - flt(source.get("transferred_qty", 0)) target.fg_completed_qty = pending_fg_qty if pending_fg_qty > 0 else 0 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 d6c3ec397bb22a95350cba7446b4fc77b8910cda..a7b69966e4e0fea197da653809a34b7c6e94437c 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 @@ -37,8 +37,7 @@ "fieldname": "time_in_mins", "fieldtype": "Float", "in_list_view": 1, - "label": "Time In Mins", - "read_only": 1 + "label": "Time In Mins" }, { "allow_on_submit": 1, @@ -64,17 +63,20 @@ "read_only": 1 } ], + "grid_page_length": 50, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2024-05-21 12:41:55.765860", + "modified": "2025-03-25 20:05:13.807905", "modified_by": "Administrator", "module": "Manufacturing", "name": "Job Card Time Log", "owner": "Administrator", "permissions": [], "quick_entry": 1, - "sort_field": "modified", - "sort_order": "DESC", + "row_format": "Dynamic", + "sort_field": "creation", + "sort_order": "ASC", + "states": [], "track_changes": 1 }