Skip to content

Commit

Permalink
fix: batch no not copied while making Material Consumption entry (bac…
Browse files Browse the repository at this point in the history
…kport #40290) (#40300)

fix: batch no not copied while making Material Consumption entry (#40290)

(cherry picked from commit 1eaa386)

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
  • Loading branch information
mergify[bot] and rohitwaghchaure authored Mar 6, 2024
1 parent 50e49be commit 6d1c144
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 26 deletions.
99 changes: 79 additions & 20 deletions erpnext/manufacturing/doctype/work_order/test_work_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -1382,8 +1382,9 @@ def test_backflushed_serial_no_raw_materials_based_on_transferred(self):

# 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(
Expand All @@ -1395,19 +1396,22 @@ def test_backflushed_serial_no_raw_materials_based_on_transferred(self):

# 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(
Expand Down Expand Up @@ -1541,19 +1545,9 @@ def test_non_consumed_material_return_against_work_order(self):
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()
Expand Down Expand Up @@ -1896,6 +1890,71 @@ def test_capcity_planning_for_workstation(self):
"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)
Expand Down
34 changes: 28 additions & 6 deletions erpnext/stock/doctype/stock_entry/stock_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -2163,23 +2163,42 @@ def update_item_in_stock_entry_detail(self, row, item, qty) -> None:
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:
Expand Down Expand Up @@ -2330,6 +2349,9 @@ def add_to_stock_entry_detail(self, item_dict, bom_no=None):
"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))
Expand Down Expand Up @@ -2978,15 +3000,15 @@ 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

if row.serial_no:
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:
Expand All @@ -2996,15 +3018,15 @@ 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

if row.serial_no:
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)

Expand Down

0 comments on commit 6d1c144

Please sign in to comment.