mirror of
https://github.com/frappe/erpnext.git
synced 2026-09-14 01:20:41 +00:00
fix: stop asking for a manufacturing entry when process loss explains the shortfall
When a previous operation manufactured less than the current job card is completing, the error always said 'Submit the manufacturing entry for the operation first' — even when the entry was already submitted and the missing quantity was booked as process loss, which made the advice a dead end. Sum the process loss of the previous operation's job cards alongside the manufactured quantity. When manufactured + process loss covers the requested quantity, say the shortfall is process loss so the user knows to reduce the completed quantity; keep the submit-first message for genuinely pending manufacturing entries.
This commit is contained in:
@@ -1464,12 +1464,12 @@ class JobCard(Document):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if self.track_semi_finished_goods and previous_operations:
|
if self.track_semi_finished_goods and previous_operations:
|
||||||
manufactured_qty = self.get_manufactured_qty_per_operation(
|
totals = self.get_manufactured_qty_per_operation([row.name for row in previous_operations])
|
||||||
[row.name for row in previous_operations]
|
|
||||||
)
|
|
||||||
|
|
||||||
for row in previous_operations:
|
for row in previous_operations:
|
||||||
row.manufactured_qty = flt(manufactured_qty.get(row.name))
|
operation_totals = totals.get(row.name)
|
||||||
|
row.manufactured_qty = flt(operation_totals and operation_totals.manufactured_qty)
|
||||||
|
row.process_loss_qty = flt(operation_totals and operation_totals.process_loss_qty)
|
||||||
|
|
||||||
return previous_operations
|
return previous_operations
|
||||||
|
|
||||||
@@ -1478,7 +1478,11 @@ class JobCard(Document):
|
|||||||
|
|
||||||
data = (
|
data = (
|
||||||
frappe.qb.from_(job_card)
|
frappe.qb.from_(job_card)
|
||||||
.select(job_card.operation_id, Sum(job_card.manufactured_qty))
|
.select(
|
||||||
|
job_card.operation_id,
|
||||||
|
Sum(job_card.manufactured_qty).as_("manufactured_qty"),
|
||||||
|
Sum(job_card.process_loss_qty).as_("process_loss_qty"),
|
||||||
|
)
|
||||||
.where(
|
.where(
|
||||||
(job_card.work_order == self.work_order)
|
(job_card.work_order == self.work_order)
|
||||||
& (job_card.docstatus == 1)
|
& (job_card.docstatus == 1)
|
||||||
@@ -1486,9 +1490,9 @@ class JobCard(Document):
|
|||||||
& (job_card.operation_id.isin(operation_ids))
|
& (job_card.operation_id.isin(operation_ids))
|
||||||
)
|
)
|
||||||
.groupby(job_card.operation_id)
|
.groupby(job_card.operation_id)
|
||||||
).run()
|
).run(as_dict=True)
|
||||||
|
|
||||||
return dict(data)
|
return {row.operation_id: row for row in data}
|
||||||
|
|
||||||
def get_current_operation_completed_qty(self):
|
def get_current_operation_completed_qty(self):
|
||||||
current_operation_qty = 0.0
|
current_operation_qty = 0.0
|
||||||
@@ -1540,19 +1544,35 @@ class JobCard(Document):
|
|||||||
OperationSequenceError,
|
OperationSequenceError,
|
||||||
)
|
)
|
||||||
|
|
||||||
if manufactured_qty < current_operation_qty:
|
if manufactured_qty >= current_operation_qty:
|
||||||
|
return
|
||||||
|
|
||||||
|
if manufactured_qty + flt(row.process_loss_qty) >= current_operation_qty:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_(
|
_(
|
||||||
"The completed quantity {0} of an operation {1} cannot be greater than the manufactured quantity {2} of a previous operation {3}. Submit the manufacturing entry for the operation {3} first."
|
"The completed quantity {0} of an operation {1} cannot be greater than the manufactured quantity {2} of a previous operation {3}, as {4} was booked as process loss there."
|
||||||
).format(
|
).format(
|
||||||
bold(self.get_qty_with_uom(current_operation_qty)),
|
bold(self.get_qty_with_uom(current_operation_qty)),
|
||||||
bold(self.operation),
|
bold(self.operation),
|
||||||
bold(self.get_qty_with_uom(manufactured_qty, row.finished_good)),
|
bold(self.get_qty_with_uom(manufactured_qty, row.finished_good)),
|
||||||
bold(row.operation),
|
bold(row.operation),
|
||||||
|
bold(self.get_qty_with_uom(flt(row.process_loss_qty), row.finished_good)),
|
||||||
),
|
),
|
||||||
OperationSequenceError,
|
OperationSequenceError,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"The completed quantity {0} of an operation {1} cannot be greater than the manufactured quantity {2} of a previous operation {3}. Submit the manufacturing entry for the operation {3} first."
|
||||||
|
).format(
|
||||||
|
bold(self.get_qty_with_uom(current_operation_qty)),
|
||||||
|
bold(self.operation),
|
||||||
|
bold(self.get_qty_with_uom(manufactured_qty, row.finished_good)),
|
||||||
|
bold(row.operation),
|
||||||
|
),
|
||||||
|
OperationSequenceError,
|
||||||
|
)
|
||||||
|
|
||||||
def validate_work_order(self):
|
def validate_work_order(self):
|
||||||
if self.is_work_order_closed():
|
if self.is_work_order_closed():
|
||||||
frappe.throw(_("You cannot make any changes to Job Card since Work Order is closed."))
|
frappe.throw(_("You cannot make any changes to Job Card since Work Order is closed."))
|
||||||
|
|||||||
Reference in New Issue
Block a user