mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-15 07:28:39 +00:00
fix: add partially transferred status and fix button visibility for partial material transfer on job card
(cherry picked from commit a22b83a97f)
# Conflicts:
# erpnext/manufacturing/doctype/job_card/job_card.py
This commit is contained in:
@@ -207,7 +207,9 @@ frappe.ui.form.on("Job Card", {
|
||||
if (frm.is_new() || doc.skip_material_transfer || doc.docstatus >= 2) return;
|
||||
|
||||
const excess_transfer_allowed = doc.__onload.job_card_excess_transfer;
|
||||
const to_request = doc.for_quantity > doc.transferred_qty;
|
||||
const to_transfer =
|
||||
has_items && doc.items.some((row) => flt(row.transferred_qty) < flt(row.required_qty));
|
||||
const to_request = to_transfer;
|
||||
|
||||
if (has_items && (to_request || excess_transfer_allowed)) {
|
||||
frm.add_custom_button(
|
||||
@@ -217,9 +219,6 @@ frappe.ui.form.on("Job Card", {
|
||||
);
|
||||
}
|
||||
|
||||
// check if any row has untransferred materials in case of multiple items in JC
|
||||
const to_transfer = doc.items.some((row) => row.transferred_qty < row.required_qty);
|
||||
|
||||
if (has_items && (to_transfer || excess_transfer_allowed)) {
|
||||
frm.add_custom_button(
|
||||
__("Material Transfer"),
|
||||
@@ -586,11 +585,10 @@ frappe.ui.form.on("Job Card", {
|
||||
|
||||
// ── Determine which action buttons to show ────────────────────────
|
||||
const has_remaining_qty = doc.for_quantity + doc.process_loss_qty > doc.total_completed_qty;
|
||||
const pending_transfer =
|
||||
has_items && doc.items.some((row) => flt(row.transferred_qty) < flt(row.required_qty));
|
||||
const materials_ready =
|
||||
doc.skip_material_transfer ||
|
||||
doc.transferred_qty >= doc.for_quantity + doc.process_loss_qty ||
|
||||
!doc.finished_good ||
|
||||
!has_items?.length;
|
||||
doc.skip_material_transfer || !pending_transfer || !doc.finished_good || !has_items;
|
||||
|
||||
let last_row = {};
|
||||
const has_sub_ops_or_pending_qty = doc.sub_operations?.length || doc.pending_qty > 0;
|
||||
|
||||
@@ -272,7 +272,7 @@
|
||||
"fieldtype": "Select",
|
||||
"label": "Status",
|
||||
"no_copy": 1,
|
||||
"options": "Open\nWork In Progress\nMaterial Transferred\nOn Hold\nSubmitted\nCancelled\nCompleted",
|
||||
"options": "Open\nWork In Progress\nPartially Transferred\nMaterial Transferred\nOn Hold\nSubmitted\nCancelled\nCompleted",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
@@ -695,7 +695,7 @@
|
||||
"grid_page_length": 50,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2026-05-21 18:37:05.688342",
|
||||
"modified": "2026-06-19 17:39:42.293242",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Job Card",
|
||||
|
||||
@@ -123,6 +123,7 @@ class JobCard(Document):
|
||||
status: DF.Literal[
|
||||
"Open",
|
||||
"Work In Progress",
|
||||
"Partially Transferred",
|
||||
"Material Transferred",
|
||||
"On Hold",
|
||||
"Submitted",
|
||||
@@ -1168,6 +1169,48 @@ class JobCard(Document):
|
||||
|
||||
frappe.db.set_value("Job Card Item", row.job_card_item, "transferred_qty", flt(transferred_qty))
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
self.set_status(update_status=True)
|
||||
|
||||
def get_job_card_items_transferred_qty(self, ste_doc):
|
||||
from frappe.query_builder.functions import Sum
|
||||
|
||||
job_card_items = [x.get("job_card_item") for x in ste_doc.get("items") if x.get("job_card_item")]
|
||||
if not job_card_items:
|
||||
return {}
|
||||
|
||||
se = frappe.qb.DocType("Stock Entry")
|
||||
sed = frappe.qb.DocType("Stock Entry Detail")
|
||||
|
||||
query = (
|
||||
frappe.qb.from_(sed)
|
||||
.join(se)
|
||||
.on(sed.parent == se.name)
|
||||
.select(sed.job_card_item, Sum(sed.qty))
|
||||
.where(
|
||||
(sed.job_card_item.isin(job_card_items))
|
||||
& (se.docstatus == 1)
|
||||
& (se.purpose == "Material Transfer for Manufacture")
|
||||
)
|
||||
.groupby(sed.job_card_item)
|
||||
)
|
||||
|
||||
return frappe._dict(query.run(as_list=True))
|
||||
|
||||
def validate_over_transfer(self, ste_doc, row, transferred_qty):
|
||||
"Block over transfer of items if not allowed in settings."
|
||||
required_qty = frappe.db.get_value("Job Card Item", row.job_card_item, "required_qty")
|
||||
if flt(transferred_qty) > flt(required_qty):
|
||||
frappe.throw(
|
||||
_(
|
||||
"Row #{0}: Cannot transfer more than Required Qty {1} for Item {2} against Job Card {3}"
|
||||
).format(row.idx, frappe.bold(required_qty), frappe.bold(row.item_code), ste_doc.job_card),
|
||||
title=_("Excess Transfer"),
|
||||
exc=JobCardOverTransferError,
|
||||
)
|
||||
|
||||
>>>>>>> a22b83a97f (fix: add partially transferred status and fix button visibility for partial material transfer on job card)
|
||||
def set_transferred_qty(self, update_status=False):
|
||||
from frappe.query_builder.functions import Sum
|
||||
|
||||
@@ -1249,6 +1292,42 @@ class JobCard(Document):
|
||||
if self.workstation:
|
||||
self.update_workstation_status()
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
def set_finished_good_status(self):
|
||||
if (self.manufactured_qty + self.process_loss_qty) >= self.for_quantity:
|
||||
self.status = "Completed"
|
||||
elif self.transferred_qty > 0 or self.skip_material_transfer:
|
||||
self.status = "Work In Progress"
|
||||
|
||||
def set_non_semi_fg_status(self):
|
||||
if self.items:
|
||||
item_data = frappe.get_all(
|
||||
"Job Card Item",
|
||||
filters={"parent": self.name},
|
||||
fields=["transferred_qty", "required_qty"],
|
||||
)
|
||||
all_transferred = item_data and all(
|
||||
flt(d.transferred_qty) >= flt(d.required_qty) for d in item_data
|
||||
)
|
||||
any_transferred = any(flt(d.transferred_qty) > 0 for d in item_data)
|
||||
|
||||
if all_transferred:
|
||||
self.status = "Material Transferred"
|
||||
elif any_transferred:
|
||||
self.status = "Partially Transferred"
|
||||
elif flt(self.for_quantity) <= flt(self.transferred_qty):
|
||||
self.status = "Material Transferred"
|
||||
|
||||
if self.time_logs:
|
||||
self.status = "Work In Progress"
|
||||
|
||||
if self.docstatus == 1 and (
|
||||
self.for_quantity <= (self.total_completed_qty + self.process_loss_qty) or not self.items
|
||||
):
|
||||
self.status = "Completed"
|
||||
|
||||
>>>>>>> a22b83a97f (fix: add partially transferred status and fix button visibility for partial material transfer on job card)
|
||||
def set_wip_warehouse(self):
|
||||
if not self.wip_warehouse:
|
||||
self.wip_warehouse = frappe.get_cached_value("Company", self.company, "default_wip_warehouse")
|
||||
@@ -1780,6 +1859,7 @@ def get_job_details(start, end, filters=None):
|
||||
event_color = {
|
||||
"Completed": "#cdf5a6",
|
||||
"Material Transferred": "#ffdd9e",
|
||||
"Partially Transferred": "#ffe5b4",
|
||||
"Work In Progress": "#D3D3D3",
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ frappe.listview_settings["Job Card"] = {
|
||||
Completed: "green",
|
||||
Cancelled: "red",
|
||||
"Material Transferred": "blue",
|
||||
"Partially Transferred": "yellow",
|
||||
Open: "red",
|
||||
};
|
||||
const status = doc.status || "Open";
|
||||
|
||||
Reference in New Issue
Block a user