Merge pull request #31054 from marination/jc-excess-transfer-config
fix: Job Card excess transfer behaviour
This commit is contained in:
commit
fa039b223e
@ -42,6 +42,10 @@ class JobCardCancelError(frappe.ValidationError):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class JobCardOverTransferError(frappe.ValidationError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class JobCard(Document):
|
class JobCard(Document):
|
||||||
def onload(self):
|
def onload(self):
|
||||||
excess_transfer = frappe.db.get_single_value(
|
excess_transfer = frappe.db.get_single_value(
|
||||||
@ -522,23 +526,50 @@ class JobCard(Document):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
def set_transferred_qty_in_job_card(self, ste_doc):
|
def set_transferred_qty_in_job_card_item(self, ste_doc):
|
||||||
|
from frappe.query_builder.functions import Sum
|
||||||
|
|
||||||
|
def _validate_over_transfer(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")
|
||||||
|
is_excess = flt(transferred_qty) > flt(required_qty)
|
||||||
|
if is_excess:
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
|
||||||
for row in ste_doc.items:
|
for row in ste_doc.items:
|
||||||
if not row.job_card_item:
|
if not row.job_card_item:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
qty = frappe.db.sql(
|
sed = frappe.qb.DocType("Stock Entry Detail")
|
||||||
""" SELECT SUM(qty) from `tabStock Entry Detail` sed, `tabStock Entry` se
|
se = frappe.qb.DocType("Stock Entry")
|
||||||
WHERE sed.job_card_item = %s and se.docstatus = 1 and sed.parent = se.name and
|
transferred_qty = (
|
||||||
se.purpose = 'Material Transfer for Manufacture'
|
frappe.qb.from_(sed)
|
||||||
""",
|
.join(se)
|
||||||
(row.job_card_item),
|
.on(sed.parent == se.name)
|
||||||
)[0][0]
|
.select(Sum(sed.qty))
|
||||||
|
.where(
|
||||||
|
(sed.job_card_item == row.job_card_item)
|
||||||
|
& (se.docstatus == 1)
|
||||||
|
& (se.purpose == "Material Transfer for Manufacture")
|
||||||
|
)
|
||||||
|
).run()[0][0]
|
||||||
|
|
||||||
frappe.db.set_value("Job Card Item", row.job_card_item, "transferred_qty", flt(qty))
|
allow_excess = frappe.db.get_single_value("Manufacturing Settings", "job_card_excess_transfer")
|
||||||
|
if not allow_excess:
|
||||||
|
_validate_over_transfer(row, transferred_qty)
|
||||||
|
|
||||||
|
frappe.db.set_value("Job Card Item", row.job_card_item, "transferred_qty", flt(transferred_qty))
|
||||||
|
|
||||||
def set_transferred_qty(self, update_status=False):
|
def set_transferred_qty(self, update_status=False):
|
||||||
"Set total FG Qty for which RM was transferred."
|
"Set total FG Qty in Job Card for which RM was transferred."
|
||||||
if not self.items:
|
if not self.items:
|
||||||
self.transferred_qty = self.for_quantity if self.docstatus == 1 else 0
|
self.transferred_qty = self.for_quantity if self.docstatus == 1 else 0
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ from frappe.utils import random_string
|
|||||||
from frappe.utils.data import add_to_date, now
|
from frappe.utils.data import add_to_date, now
|
||||||
|
|
||||||
from erpnext.manufacturing.doctype.job_card.job_card import (
|
from erpnext.manufacturing.doctype.job_card.job_card import (
|
||||||
|
JobCardOverTransferError,
|
||||||
OperationMismatchError,
|
OperationMismatchError,
|
||||||
OverlapError,
|
OverlapError,
|
||||||
make_corrective_job_card,
|
make_corrective_job_card,
|
||||||
@ -165,6 +166,7 @@ class TestJobCard(FrappeTestCase):
|
|||||||
# transfer was made for 2 fg qty in first transfer Stock Entry
|
# transfer was made for 2 fg qty in first transfer Stock Entry
|
||||||
self.assertEqual(transfer_entry_2.fg_completed_qty, 0)
|
self.assertEqual(transfer_entry_2.fg_completed_qty, 0)
|
||||||
|
|
||||||
|
@change_settings("Manufacturing Settings", {"job_card_excess_transfer": 1})
|
||||||
def test_job_card_excess_material_transfer(self):
|
def test_job_card_excess_material_transfer(self):
|
||||||
"Test transferring more than required RM against Job Card."
|
"Test transferring more than required RM against Job Card."
|
||||||
self.transfer_material_against = "Job Card"
|
self.transfer_material_against = "Job Card"
|
||||||
@ -207,6 +209,30 @@ class TestJobCard(FrappeTestCase):
|
|||||||
# JC is Completed with excess transfer
|
# JC is Completed with excess transfer
|
||||||
self.assertEqual(job_card.status, "Completed")
|
self.assertEqual(job_card.status, "Completed")
|
||||||
|
|
||||||
|
@change_settings("Manufacturing Settings", {"job_card_excess_transfer": 0})
|
||||||
|
def test_job_card_excess_material_transfer_block(self):
|
||||||
|
|
||||||
|
self.transfer_material_against = "Job Card"
|
||||||
|
self.source_warehouse = "Stores - _TC"
|
||||||
|
|
||||||
|
self.generate_required_stock(self.work_order)
|
||||||
|
|
||||||
|
job_card_name = frappe.db.get_value("Job Card", {"work_order": self.work_order.name})
|
||||||
|
|
||||||
|
# fully transfer both RMs
|
||||||
|
transfer_entry_1 = make_stock_entry_from_jc(job_card_name)
|
||||||
|
transfer_entry_1.insert()
|
||||||
|
transfer_entry_1.submit()
|
||||||
|
|
||||||
|
# transfer extra qty of both RM due to previously damaged RM
|
||||||
|
transfer_entry_2 = make_stock_entry_from_jc(job_card_name)
|
||||||
|
# deliberately change 'For Quantity'
|
||||||
|
transfer_entry_2.fg_completed_qty = 1
|
||||||
|
transfer_entry_2.items[0].qty = 5
|
||||||
|
transfer_entry_2.items[1].qty = 3
|
||||||
|
transfer_entry_2.insert()
|
||||||
|
self.assertRaises(JobCardOverTransferError, transfer_entry_2.submit)
|
||||||
|
|
||||||
def test_job_card_partial_material_transfer(self):
|
def test_job_card_partial_material_transfer(self):
|
||||||
"Test partial material transfer against Job Card"
|
"Test partial material transfer against Job Card"
|
||||||
self.transfer_material_against = "Job Card"
|
self.transfer_material_against = "Job Card"
|
||||||
|
@ -1139,7 +1139,7 @@ class StockEntry(StockController):
|
|||||||
if self.job_card:
|
if self.job_card:
|
||||||
job_doc = frappe.get_doc("Job Card", self.job_card)
|
job_doc = frappe.get_doc("Job Card", self.job_card)
|
||||||
job_doc.set_transferred_qty(update_status=True)
|
job_doc.set_transferred_qty(update_status=True)
|
||||||
job_doc.set_transferred_qty_in_job_card(self)
|
job_doc.set_transferred_qty_in_job_card_item(self)
|
||||||
|
|
||||||
if self.work_order:
|
if self.work_order:
|
||||||
pro_doc = frappe.get_doc("Work Order", self.work_order)
|
pro_doc = frappe.get_doc("Work Order", self.work_order)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user