mirror of
https://github.com/frappe/erpnext.git
synced 2026-03-05 11:33:56 +00:00
Merge pull request #46801 from rohitwaghchaure/fixed-ux-for-job-card
fix: UX for partial job card completion
This commit is contained in:
@@ -45,6 +45,7 @@ frappe.ui.form.on("Job Card", {
|
||||
|
||||
setup_stock_entry(frm) {
|
||||
if (
|
||||
frm.doc.manufactured_qty &&
|
||||
frm.doc.finished_good &&
|
||||
frm.doc.docstatus === 1 &&
|
||||
!frm.doc.is_subcontracted &&
|
||||
@@ -91,11 +92,11 @@ frappe.ui.form.on("Job Card", {
|
||||
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) {
|
||||
if (!frm.is_new() && !frm.doc.skip_material_transfer && 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;
|
||||
|
||||
if (to_request || excess_transfer_allowed) {
|
||||
if (has_items && (to_request || excess_transfer_allowed)) {
|
||||
frm.add_custom_button(__("Material Request"), () => {
|
||||
frm.trigger("make_material_request");
|
||||
});
|
||||
@@ -105,7 +106,7 @@ frappe.ui.form.on("Job Card", {
|
||||
// in case of multiple items in JC
|
||||
let to_transfer = frm.doc.items.some((row) => row.transferred_qty < row.required_qty);
|
||||
|
||||
if (to_transfer || excess_transfer_allowed) {
|
||||
if (has_items && (to_transfer || excess_transfer_allowed)) {
|
||||
frm.add_custom_button(__("Material Transfer"), () => {
|
||||
frm.trigger("make_stock_entry");
|
||||
});
|
||||
@@ -132,7 +133,8 @@ frappe.ui.form.on("Job Card", {
|
||||
frm.doc.for_quantity + frm.doc.process_loss_qty > frm.doc.total_completed_qty &&
|
||||
(frm.doc.skip_material_transfer ||
|
||||
frm.doc.transferred_qty >= frm.doc.for_quantity + frm.doc.process_loss_qty ||
|
||||
!frm.doc.finished_good)
|
||||
!frm.doc.finished_good ||
|
||||
!has_items?.length)
|
||||
) {
|
||||
if (!frm.doc.time_logs?.length) {
|
||||
frm.add_custom_button(__("Start Job"), () => {
|
||||
@@ -168,7 +170,8 @@ frappe.ui.form.on("Job Card", {
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (frm.doc.for_quantity - frm.doc.manufactured_qty > 0) {
|
||||
let manufactured_qty = frm.doc.manufactured_qty || frm.doc.total_completed_qty;
|
||||
if (frm.doc.for_quantity - (manufactured_qty + frm.doc.process_loss_qty) > 0) {
|
||||
if (!frm.doc.is_paused) {
|
||||
frm.add_custom_button(__("Pause Job"), () => {
|
||||
frm.call({
|
||||
@@ -217,12 +220,48 @@ frappe.ui.form.on("Job Card", {
|
||||
|
||||
complete_job_card(frm) {
|
||||
let fields = [
|
||||
{
|
||||
fieldtype: "Float",
|
||||
label: __("Qty to Manufacture"),
|
||||
fieldname: "for_quantity",
|
||||
reqd: 1,
|
||||
default: frm.doc.for_quantity,
|
||||
change() {
|
||||
let doc = frm.job_completion_dialog;
|
||||
|
||||
doc.set_value("completed_qty", doc.get_value("for_quantity"));
|
||||
doc.set_value("process_loss_qty", 0);
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldtype: "Float",
|
||||
label: __("Completed Quantity"),
|
||||
fieldname: "qty",
|
||||
fieldname: "completed_qty",
|
||||
reqd: 1,
|
||||
default: frm.doc.for_quantity - frm.doc.total_completed_qty,
|
||||
change() {
|
||||
let doc = frm.job_completion_dialog;
|
||||
|
||||
let process_loss_qty = doc.get_value("for_quantity") - doc.get_value("completed_qty");
|
||||
if (process_loss_qty > 0 && process_loss_qty != doc.get_value("process_loss_qty")) {
|
||||
doc.set_value("process_loss_qty", process_loss_qty);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldtype: "Float",
|
||||
label: __("Process Loss Quantity"),
|
||||
fieldname: "process_loss_qty",
|
||||
reqd: 1,
|
||||
onchange() {
|
||||
let doc = frm.job_completion_dialog;
|
||||
|
||||
let completed_qty = doc.get_value("for_quantity") - doc.get_value("process_loss_qty");
|
||||
doc.set_value("completed_qty", completed_qty);
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldtype: "Section Break",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -236,7 +275,7 @@ frappe.ui.form.on("Job Card", {
|
||||
});
|
||||
}
|
||||
|
||||
frappe.prompt(
|
||||
frm.job_completion_dialog = frappe.prompt(
|
||||
fields,
|
||||
(data) => {
|
||||
if (data.qty <= 0) {
|
||||
@@ -247,7 +286,8 @@ frappe.ui.form.on("Job Card", {
|
||||
method: "complete_job_card",
|
||||
doc: frm.doc,
|
||||
args: {
|
||||
qty: data.qty,
|
||||
qty: data.completed_qty,
|
||||
for_quantity: data.for_quantity,
|
||||
end_time: data.end_time,
|
||||
},
|
||||
callback: function (r) {
|
||||
@@ -628,7 +668,15 @@ frappe.ui.form.on("Job Card", {
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Job Card Time Log", {
|
||||
completed_qty: function (frm) {
|
||||
completed_qty: function (frm, cdt, cdn) {
|
||||
let row = locals[cdt][cdn];
|
||||
if (!row.completed_qty) {
|
||||
frappe.model.set_value(row.doctype, row.name, {
|
||||
time_in_mins: 0,
|
||||
to_time: "",
|
||||
});
|
||||
}
|
||||
|
||||
frm.events.set_total_completed_qty(frm);
|
||||
},
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"status",
|
||||
"operation_row_id",
|
||||
"is_paused",
|
||||
"track_semi_finished_goods",
|
||||
"column_break_20",
|
||||
"operation_row_number",
|
||||
"operation_id",
|
||||
@@ -530,10 +531,11 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.track_semi_finished_goods",
|
||||
"fieldname": "target_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"label": "Target Warehouse",
|
||||
"mandatory_depends_on": "eval:doc.finished_good",
|
||||
"mandatory_depends_on": "eval:doc.track_semi_finished_goods",
|
||||
"options": "Warehouse"
|
||||
},
|
||||
{
|
||||
@@ -610,12 +612,19 @@
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Paused",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fetch_from": "work_order.track_semi_finished_goods",
|
||||
"fieldname": "track_semi_finished_goods",
|
||||
"fieldtype": "Check",
|
||||
"label": "Track Semi Finished Goods"
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-03-25 17:50:18.608869",
|
||||
"modified": "2025-03-30 18:53:38.206399",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Job Card",
|
||||
|
||||
@@ -129,6 +129,7 @@ class JobCard(Document):
|
||||
time_required: DF.Float
|
||||
total_completed_qty: DF.Float
|
||||
total_time_in_mins: DF.Float
|
||||
track_semi_finished_goods: DF.Check
|
||||
transferred_qty: DF.Float
|
||||
wip_warehouse: DF.Link | None
|
||||
work_order: DF.Link
|
||||
@@ -723,7 +724,7 @@ class JobCard(Document):
|
||||
)
|
||||
|
||||
def validate_job_card(self):
|
||||
if self.finished_good:
|
||||
if self.track_semi_finished_goods:
|
||||
return
|
||||
|
||||
if self.work_order and frappe.get_cached_value("Work Order", self.work_order, "status") == "Stopped":
|
||||
@@ -794,7 +795,7 @@ class JobCard(Document):
|
||||
)
|
||||
|
||||
def update_work_order(self):
|
||||
if self.finished_good:
|
||||
if self.track_semi_finished_goods:
|
||||
return
|
||||
|
||||
if not self.work_order:
|
||||
@@ -1037,7 +1038,7 @@ class JobCard(Document):
|
||||
if self.docstatus == 0 and self.time_logs:
|
||||
self.status = "Work In Progress"
|
||||
|
||||
if not self.finished_good and self.docstatus < 2:
|
||||
if not self.track_semi_finished_goods and self.docstatus < 2:
|
||||
if flt(self.for_quantity) <= flt(self.transferred_qty):
|
||||
self.status = "Material Transferred"
|
||||
|
||||
@@ -1254,6 +1255,10 @@ class JobCard(Document):
|
||||
|
||||
if kwargs.end_time:
|
||||
self.add_time_logs(to_time=kwargs.end_time, completed_qty=kwargs.qty, employees=self.employee)
|
||||
|
||||
if kwargs.for_quantity:
|
||||
self.for_quantity = kwargs.for_quantity
|
||||
|
||||
self.save()
|
||||
else:
|
||||
self.add_time_logs(completed_qty=kwargs.qty, employees=self.employee)
|
||||
|
||||
Reference in New Issue
Block a user