Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Job Card excess transfer behaviour #31054

Merged
merged 3 commits into from
May 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 41 additions & 10 deletions erpnext/manufacturing/doctype/job_card/job_card.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ class JobCardCancelError(frappe.ValidationError):
pass


class JobCardOverTransferError(frappe.ValidationError):
pass


class JobCard(Document):
def onload(self):
excess_transfer = frappe.db.get_single_value(
Expand Down Expand Up @@ -522,23 +526,50 @@ def get_current_operation_data(self):
},
)

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:
if not row.job_card_item:
continue

qty = frappe.db.sql(
""" SELECT SUM(qty) from `tabStock Entry Detail` sed, `tabStock Entry` se
WHERE sed.job_card_item = %s and se.docstatus = 1 and sed.parent = se.name and
se.purpose = 'Material Transfer for Manufacture'
""",
(row.job_card_item),
)[0][0]
sed = frappe.qb.DocType("Stock Entry Detail")
se = frappe.qb.DocType("Stock Entry")
transferred_qty = (
frappe.qb.from_(sed)
.join(se)
.on(sed.parent == se.name)
.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]

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(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):
"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:
self.transferred_qty = self.for_quantity if self.docstatus == 1 else 0

Expand Down
26 changes: 26 additions & 0 deletions erpnext/manufacturing/doctype/job_card/test_job_card.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from frappe.utils.data import add_to_date, now

from erpnext.manufacturing.doctype.job_card.job_card import (
JobCardOverTransferError,
OperationMismatchError,
OverlapError,
make_corrective_job_card,
Expand Down Expand Up @@ -165,6 +166,7 @@ def test_job_card_multiple_materials_transfer(self):
# transfer was made for 2 fg qty in first transfer Stock Entry
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):
"Test transferring more than required RM against Job Card."
self.transfer_material_against = "Job Card"
Expand Down Expand Up @@ -207,6 +209,30 @@ def test_job_card_excess_material_transfer(self):
# JC is Completed with excess transfer
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):
"Test partial material transfer against Job Card"
self.transfer_material_against = "Job Card"
Expand Down
2 changes: 1 addition & 1 deletion erpnext/stock/doctype/stock_entry/stock_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -1139,7 +1139,7 @@ def _validate_work_order(pro_doc):
if 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_in_job_card(self)
job_doc.set_transferred_qty_in_job_card_item(self)

if self.work_order:
pro_doc = frappe.get_doc("Work Order", self.work_order)
Expand Down