mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-25 16:04:46 +00:00
Merge pull request #29274 from frappe/mergify/bp/version-13-hotfix/pr-29271
fix: Don't validate FG in repack entry (backport #29271)
This commit is contained in:
@@ -87,8 +87,11 @@ class StockEntry(StockController):
|
|||||||
self.validate_warehouse()
|
self.validate_warehouse()
|
||||||
self.validate_work_order()
|
self.validate_work_order()
|
||||||
self.validate_bom()
|
self.validate_bom()
|
||||||
self.mark_finished_and_scrap_items()
|
|
||||||
self.validate_finished_goods()
|
if self.purpose in ("Manufacture", "Repack"):
|
||||||
|
self.mark_finished_and_scrap_items()
|
||||||
|
self.validate_finished_goods()
|
||||||
|
|
||||||
self.validate_with_material_request()
|
self.validate_with_material_request()
|
||||||
self.validate_batch()
|
self.validate_batch()
|
||||||
self.validate_inspection()
|
self.validate_inspection()
|
||||||
@@ -707,26 +710,25 @@ class StockEntry(StockController):
|
|||||||
validate_bom_no(item_code, d.bom_no)
|
validate_bom_no(item_code, d.bom_no)
|
||||||
|
|
||||||
def mark_finished_and_scrap_items(self):
|
def mark_finished_and_scrap_items(self):
|
||||||
if self.purpose in ("Repack", "Manufacture"):
|
if any([d.item_code for d in self.items if (d.is_finished_item and d.t_warehouse)]):
|
||||||
if any([d.item_code for d in self.items if (d.is_finished_item and d.t_warehouse)]):
|
return
|
||||||
return
|
|
||||||
|
|
||||||
finished_item = self.get_finished_item()
|
finished_item = self.get_finished_item()
|
||||||
|
|
||||||
if not finished_item and self.purpose == "Manufacture":
|
if not finished_item and self.purpose == "Manufacture":
|
||||||
# In case of independent Manufacture entry, don't auto set
|
# In case of independent Manufacture entry, don't auto set
|
||||||
# user must decide and set
|
# user must decide and set
|
||||||
return
|
return
|
||||||
|
|
||||||
for d in self.items:
|
for d in self.items:
|
||||||
if d.t_warehouse and not d.s_warehouse:
|
if d.t_warehouse and not d.s_warehouse:
|
||||||
if self.purpose=="Repack" or d.item_code == finished_item:
|
if self.purpose=="Repack" or d.item_code == finished_item:
|
||||||
d.is_finished_item = 1
|
d.is_finished_item = 1
|
||||||
else:
|
|
||||||
d.is_scrap_item = 1
|
|
||||||
else:
|
else:
|
||||||
d.is_finished_item = 0
|
d.is_scrap_item = 1
|
||||||
d.is_scrap_item = 0
|
else:
|
||||||
|
d.is_finished_item = 0
|
||||||
|
d.is_scrap_item = 0
|
||||||
|
|
||||||
def get_finished_item(self):
|
def get_finished_item(self):
|
||||||
finished_item = None
|
finished_item = None
|
||||||
@@ -739,9 +741,9 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
def validate_finished_goods(self):
|
def validate_finished_goods(self):
|
||||||
"""
|
"""
|
||||||
1. Check if FG exists
|
1. Check if FG exists (mfg, repack)
|
||||||
2. Check if Multiple FG Items are present
|
2. Check if Multiple FG Items are present (mfg)
|
||||||
3. Check FG Item and Qty against WO if present
|
3. Check FG Item and Qty against WO if present (mfg)
|
||||||
"""
|
"""
|
||||||
production_item, wo_qty, finished_items = None, 0, []
|
production_item, wo_qty, finished_items = None, 0, []
|
||||||
|
|
||||||
@@ -754,8 +756,9 @@ class StockEntry(StockController):
|
|||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
if d.is_finished_item:
|
if d.is_finished_item:
|
||||||
if not self.work_order:
|
if not self.work_order:
|
||||||
|
# Independent MFG Entry/ Repack Entry, no WO to match against
|
||||||
finished_items.append(d.item_code)
|
finished_items.append(d.item_code)
|
||||||
continue # Independent Manufacture Entry, no WO to match against
|
continue
|
||||||
|
|
||||||
if d.item_code != production_item:
|
if d.item_code != production_item:
|
||||||
frappe.throw(_("Finished Item {0} does not match with Work Order {1}")
|
frappe.throw(_("Finished Item {0} does not match with Work Order {1}")
|
||||||
@@ -768,19 +771,17 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
finished_items.append(d.item_code)
|
finished_items.append(d.item_code)
|
||||||
|
|
||||||
if len(set(finished_items)) > 1:
|
if not finished_items:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
msg=_("Multiple items cannot be marked as finished item"),
|
msg=_("There must be atleast 1 Finished Good in this Stock Entry").format(self.name),
|
||||||
title=_("Note"),
|
title=_("Missing Finished Good"), exc=FinishedGoodError
|
||||||
exc=FinishedGoodError
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.purpose == "Manufacture":
|
if self.purpose == "Manufacture":
|
||||||
if not finished_items:
|
if len(set(finished_items)) > 1:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
msg=_("There must be atleast 1 Finished Good in this Stock Entry").format(self.name),
|
msg=_("Multiple items cannot be marked as finished item"),
|
||||||
title=_("Missing Finished Good"),
|
title=_("Note"), exc=FinishedGoodError
|
||||||
exc=FinishedGoodError
|
|
||||||
)
|
)
|
||||||
|
|
||||||
allowance_percentage = flt(
|
allowance_percentage = flt(
|
||||||
|
|||||||
@@ -227,9 +227,47 @@ class TestStockEntry(ERPNextTestCase):
|
|||||||
|
|
||||||
mtn.cancel()
|
mtn.cancel()
|
||||||
|
|
||||||
def test_repack_no_change_in_valuation(self):
|
def test_repack_multiple_fg(self):
|
||||||
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
|
"Test `is_finished_item` for one item repacked into two items."
|
||||||
|
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=100, basic_rate=100)
|
||||||
|
|
||||||
|
repack = frappe.copy_doc(test_records[3])
|
||||||
|
repack.posting_date = nowdate()
|
||||||
|
repack.posting_time = nowtime()
|
||||||
|
|
||||||
|
repack.items[0].qty = 100.0
|
||||||
|
repack.items[0].transfer_qty = 100.0
|
||||||
|
repack.items[1].qty = 50.0
|
||||||
|
|
||||||
|
repack.append("items", {
|
||||||
|
"conversion_factor": 1.0,
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"doctype": "Stock Entry Detail",
|
||||||
|
"expense_account": "Stock Adjustment - _TC",
|
||||||
|
"basic_rate": 150,
|
||||||
|
"item_code": "_Test Item 2",
|
||||||
|
"parentfield": "items",
|
||||||
|
"qty": 50.0,
|
||||||
|
"stock_uom": "_Test UOM",
|
||||||
|
"t_warehouse": "_Test Warehouse - _TC",
|
||||||
|
"transfer_qty": 50.0,
|
||||||
|
"uom": "_Test UOM"
|
||||||
|
})
|
||||||
|
repack.set_stock_entry_type()
|
||||||
|
repack.insert()
|
||||||
|
|
||||||
|
self.assertEqual(repack.items[1].is_finished_item, 1)
|
||||||
|
self.assertEqual(repack.items[2].is_finished_item, 1)
|
||||||
|
|
||||||
|
repack.items[1].is_finished_item = 0
|
||||||
|
repack.items[2].is_finished_item = 0
|
||||||
|
|
||||||
|
# must raise error if 0 fg in repack entry
|
||||||
|
self.assertRaises(FinishedGoodError, repack.validate_finished_goods)
|
||||||
|
|
||||||
|
repack.delete() # teardown
|
||||||
|
|
||||||
|
def test_repack_no_change_in_valuation(self):
|
||||||
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100)
|
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100)
|
||||||
make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC",
|
make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC",
|
||||||
qty=50, basic_rate=100)
|
qty=50, basic_rate=100)
|
||||||
|
|||||||
Reference in New Issue
Block a user