fix: batch no not copied while making Material Consumption entry (#40290)
This commit is contained in:
@@ -1383,8 +1383,9 @@ class TestWorkOrder(FrappeTestCase):
|
||||
|
||||
# Inward raw materials in Stores warehouse
|
||||
ste_doc.submit()
|
||||
ste_doc.reload()
|
||||
|
||||
serial_nos_list = sorted(get_serial_nos(ste_doc.items[0].serial_no))
|
||||
serial_nos_list = sorted(get_serial_nos_from_bundle(ste_doc.items[0].serial_and_batch_bundle))
|
||||
|
||||
wo_doc = make_wo_order_test_record(production_item=fg_item, qty=4)
|
||||
transferred_ste_doc = frappe.get_doc(
|
||||
@@ -1396,19 +1397,22 @@ class TestWorkOrder(FrappeTestCase):
|
||||
|
||||
# First Manufacture stock entry
|
||||
manufacture_ste_doc1 = frappe.get_doc(make_stock_entry(wo_doc.name, "Manufacture", 1))
|
||||
manufacture_ste_doc1.submit()
|
||||
manufacture_ste_doc1.reload()
|
||||
|
||||
# Serial nos should be same as transferred Serial nos
|
||||
self.assertEqual(get_serial_nos(manufacture_ste_doc1.items[0].serial_no), serial_nos_list[0:1])
|
||||
self.assertEqual(
|
||||
sorted(get_serial_nos_from_bundle(manufacture_ste_doc1.items[0].serial_and_batch_bundle)),
|
||||
serial_nos_list[0:1],
|
||||
)
|
||||
self.assertEqual(manufacture_ste_doc1.items[0].qty, 1)
|
||||
|
||||
manufacture_ste_doc1.submit()
|
||||
|
||||
# Second Manufacture stock entry
|
||||
manufacture_ste_doc2 = frappe.get_doc(make_stock_entry(wo_doc.name, "Manufacture", 2))
|
||||
manufacture_ste_doc2 = frappe.get_doc(make_stock_entry(wo_doc.name, "Manufacture", 3))
|
||||
|
||||
# Serial nos should be same as transferred Serial nos
|
||||
self.assertEqual(get_serial_nos(manufacture_ste_doc2.items[0].serial_no), serial_nos_list[1:3])
|
||||
self.assertEqual(manufacture_ste_doc2.items[0].qty, 2)
|
||||
self.assertEqual(get_serial_nos(manufacture_ste_doc2.items[0].serial_no), serial_nos_list[1:4])
|
||||
self.assertEqual(manufacture_ste_doc2.items[0].qty, 3)
|
||||
|
||||
def test_backflushed_serial_no_batch_raw_materials_based_on_transferred(self):
|
||||
frappe.db.set_single_value(
|
||||
@@ -1542,19 +1546,9 @@ class TestWorkOrder(FrappeTestCase):
|
||||
row.qty -= 2
|
||||
row.transfer_qty -= 2
|
||||
|
||||
if not row.serial_and_batch_bundle:
|
||||
continue
|
||||
|
||||
bundle_id = row.serial_and_batch_bundle
|
||||
bundle_doc = frappe.get_doc("Serial and Batch Bundle", bundle_id)
|
||||
if bundle_doc.has_serial_no:
|
||||
bundle_doc.set("entries", bundle_doc.entries[0:5])
|
||||
else:
|
||||
for bundle_row in bundle_doc.entries:
|
||||
bundle_row.qty += 2
|
||||
|
||||
bundle_doc.save()
|
||||
bundle_doc.load_from_db()
|
||||
if row.serial_no:
|
||||
serial_nos = get_serial_nos(row.serial_no)
|
||||
row.serial_no = "\n".join(serial_nos[:5])
|
||||
|
||||
ste_doc.save()
|
||||
ste_doc.submit()
|
||||
@@ -1897,6 +1891,71 @@ class TestWorkOrder(FrappeTestCase):
|
||||
"Manufacturing Settings", {"disable_capacity_planning": 1, "mins_between_operations": 0}
|
||||
)
|
||||
|
||||
def test_partial_material_consumption_with_batch(self):
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import (
|
||||
make_stock_entry as make_stock_entry_test_record,
|
||||
)
|
||||
|
||||
frappe.db.set_single_value("Manufacturing Settings", "material_consumption", 1)
|
||||
frappe.db.set_single_value(
|
||||
"Manufacturing Settings",
|
||||
"backflush_raw_materials_based_on",
|
||||
"Material Transferred for Manufacture",
|
||||
)
|
||||
|
||||
fg_item = make_item(
|
||||
"Test FG Item For Partial Material Consumption",
|
||||
{"is_stock_item": 1},
|
||||
).name
|
||||
|
||||
rm_item = make_item(
|
||||
"Test RM Item For Partial Material Consumption",
|
||||
{
|
||||
"is_stock_item": 1,
|
||||
"has_batch_no": 1,
|
||||
"create_new_batch": 1,
|
||||
"batch_number_series": "TST-BATCH-PMCC-.####",
|
||||
},
|
||||
).name
|
||||
|
||||
make_bom(
|
||||
item=fg_item,
|
||||
source_warehouse="Stores - _TC",
|
||||
raw_materials=[rm_item],
|
||||
)
|
||||
|
||||
make_stock_entry_test_record(
|
||||
purpose="Material Receipt",
|
||||
item_code=rm_item,
|
||||
target="Stores - _TC",
|
||||
qty=10,
|
||||
basic_rate=100,
|
||||
)
|
||||
|
||||
wo_order = make_wo_order_test_record(item=fg_item, qty=10)
|
||||
|
||||
stock_entry = frappe.get_doc(
|
||||
make_stock_entry(wo_order.name, "Material Transfer for Manufacture", 10)
|
||||
)
|
||||
stock_entry.submit()
|
||||
stock_entry.reload()
|
||||
|
||||
batch_no = get_batch_from_bundle(stock_entry.items[0].serial_and_batch_bundle)
|
||||
|
||||
stock_entry = frappe.get_doc(
|
||||
make_stock_entry(wo_order.name, "Material Consumption for Manufacture", 10)
|
||||
)
|
||||
|
||||
self.assertEqual(stock_entry.items[0].batch_no, batch_no)
|
||||
self.assertEqual(stock_entry.items[0].use_serial_batch_fields, 1)
|
||||
|
||||
frappe.db.set_single_value("Manufacturing Settings", "material_consumption", 0)
|
||||
frappe.db.set_single_value(
|
||||
"Manufacturing Settings",
|
||||
"backflush_raw_materials_based_on",
|
||||
"BOM",
|
||||
)
|
||||
|
||||
|
||||
def make_operation(**kwargs):
|
||||
kwargs = frappe._dict(kwargs)
|
||||
|
||||
@@ -2168,23 +2168,42 @@ class StockEntry(StockController):
|
||||
if not qty:
|
||||
return
|
||||
|
||||
use_serial_batch_fields = frappe.db.get_single_value("Stock Settings", "use_serial_batch_fields")
|
||||
|
||||
ste_item_details = {
|
||||
"from_warehouse": item.warehouse,
|
||||
"to_warehouse": "",
|
||||
"qty": qty,
|
||||
"item_name": item.item_name,
|
||||
"serial_and_batch_bundle": create_serial_and_batch_bundle(self, row, item, "Outward"),
|
||||
"serial_and_batch_bundle": create_serial_and_batch_bundle(self, row, item, "Outward")
|
||||
if not use_serial_batch_fields
|
||||
else "",
|
||||
"description": item.description,
|
||||
"stock_uom": item.stock_uom,
|
||||
"expense_account": item.expense_account,
|
||||
"cost_center": item.buying_cost_center,
|
||||
"original_item": item.original_item,
|
||||
"serial_no": "\n".join(row.serial_nos)
|
||||
if row.serial_nos and not row.batches_to_be_consume
|
||||
else "",
|
||||
"use_serial_batch_fields": use_serial_batch_fields,
|
||||
}
|
||||
|
||||
if self.is_return:
|
||||
ste_item_details["to_warehouse"] = item.s_warehouse
|
||||
|
||||
self.add_to_stock_entry_detail({item.item_code: ste_item_details})
|
||||
if use_serial_batch_fields and not row.serial_no and row.batches_to_be_consume:
|
||||
for batch_no, batch_qty in row.batches_to_be_consume.items():
|
||||
ste_item_details.update(
|
||||
{
|
||||
"batch_no": batch_no,
|
||||
"qty": batch_qty,
|
||||
}
|
||||
)
|
||||
|
||||
self.add_to_stock_entry_detail({item.item_code: ste_item_details})
|
||||
else:
|
||||
self.add_to_stock_entry_detail({item.item_code: ste_item_details})
|
||||
|
||||
@staticmethod
|
||||
def get_serial_nos_based_on_transferred_batch(batch_no, serial_nos) -> list:
|
||||
@@ -2335,6 +2354,9 @@ class StockEntry(StockController):
|
||||
"item_name",
|
||||
"serial_and_batch_bundle",
|
||||
"allow_zero_valuation_rate",
|
||||
"use_serial_batch_fields",
|
||||
"batch_no",
|
||||
"serial_no",
|
||||
]:
|
||||
if item_row.get(field):
|
||||
se_child.set(field, item_row.get(field))
|
||||
@@ -2983,7 +3005,7 @@ def get_available_materials(work_order) -> dict:
|
||||
if row.batch_no:
|
||||
item_data.batch_details[row.batch_no] += row.qty
|
||||
|
||||
if row.batch_nos:
|
||||
elif row.batch_nos:
|
||||
for batch_no, qty in row.batch_nos.items():
|
||||
item_data.batch_details[batch_no] += qty
|
||||
|
||||
@@ -2991,7 +3013,7 @@ def get_available_materials(work_order) -> dict:
|
||||
item_data.serial_nos.extend(get_serial_nos(row.serial_no))
|
||||
item_data.serial_nos.sort()
|
||||
|
||||
if row.serial_nos:
|
||||
elif row.serial_nos:
|
||||
item_data.serial_nos.extend(get_serial_nos(row.serial_nos))
|
||||
item_data.serial_nos.sort()
|
||||
else:
|
||||
@@ -3001,7 +3023,7 @@ def get_available_materials(work_order) -> dict:
|
||||
if row.batch_no:
|
||||
item_data.batch_details[row.batch_no] -= row.qty
|
||||
|
||||
if row.batch_nos:
|
||||
elif row.batch_nos:
|
||||
for batch_no, qty in row.batch_nos.items():
|
||||
item_data.batch_details[batch_no] += qty
|
||||
|
||||
@@ -3009,7 +3031,7 @@ def get_available_materials(work_order) -> dict:
|
||||
for serial_no in get_serial_nos(row.serial_no):
|
||||
item_data.serial_nos.remove(serial_no)
|
||||
|
||||
if row.serial_nos:
|
||||
elif row.serial_nos:
|
||||
for serial_no in get_serial_nos(row.serial_nos):
|
||||
item_data.serial_nos.remove(serial_no)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user