mirror of
https://github.com/frappe/erpnext.git
synced 2026-03-10 22:06:52 +00:00
fix: stock ledger entries for stock reco
This commit is contained in:
@@ -191,7 +191,7 @@ class StockReconciliation(StockController):
|
||||
|
||||
sl_entries = []
|
||||
|
||||
serialized_items = False
|
||||
serialized_items = []
|
||||
for row in self.items:
|
||||
item = frappe.get_cached_doc("Item", row.item_code)
|
||||
if not (item.has_serial_no):
|
||||
@@ -229,27 +229,29 @@ class StockReconciliation(StockController):
|
||||
sl_entries.append(sle_data)
|
||||
|
||||
else:
|
||||
serialized_items = True
|
||||
serialized_items.append(row.item_code)
|
||||
|
||||
if serialized_items:
|
||||
self.get_sle_for_serialized_items(sl_entries)
|
||||
self.get_sle_for_serialized_items(sl_entries, serialized_items)
|
||||
|
||||
if sl_entries:
|
||||
allow_negative_stock = frappe.get_cached_value("Stock Settings", None, "allow_negative_stock")
|
||||
self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock)
|
||||
|
||||
def get_sle_for_serialized_items(self, sl_entries):
|
||||
self.issue_existing_serial_and_batch(sl_entries)
|
||||
self.add_new_serial_and_batch(sl_entries)
|
||||
self.update_valuation_rate_for_serial_no()
|
||||
def get_sle_for_serialized_items(self, sl_entries, serialized_items=[]):
|
||||
self.issue_existing_serial_and_batch(sl_entries, serialized_items)
|
||||
self.add_new_serial_and_batch(sl_entries, serialized_items)
|
||||
self.update_valuation_rate_for_serial_no(serialized_items)
|
||||
|
||||
if sl_entries:
|
||||
sl_entries = self.merge_similar_item_serial_nos(sl_entries)
|
||||
|
||||
def issue_existing_serial_and_batch(self, sl_entries):
|
||||
def issue_existing_serial_and_batch(self, sl_entries, serialized_items=[]):
|
||||
from erpnext.stock.stock_ledger import get_stock_ledger_entries
|
||||
|
||||
for row in self.items:
|
||||
if row.item_code not in serialized_items: continue
|
||||
|
||||
serial_nos = get_serial_nos(row.serial_no) or []
|
||||
|
||||
# To issue existing serial nos
|
||||
@@ -303,8 +305,10 @@ class StockReconciliation(StockController):
|
||||
|
||||
sl_entries.append(new_args)
|
||||
|
||||
def add_new_serial_and_batch(self, sl_entries):
|
||||
def add_new_serial_and_batch(self, sl_entries, serialized_items=[]):
|
||||
for row in self.items:
|
||||
if row.item_code not in serialized_items: continue
|
||||
|
||||
if row.qty:
|
||||
args = self.get_sle_for_items(row)
|
||||
|
||||
@@ -316,9 +320,9 @@ class StockReconciliation(StockController):
|
||||
|
||||
sl_entries.append(args)
|
||||
|
||||
def update_valuation_rate_for_serial_no(self):
|
||||
def update_valuation_rate_for_serial_no(self, serialized_items=[]):
|
||||
for d in self.items:
|
||||
if not d.serial_no: continue
|
||||
if d.item_code not in serialized_items: continue
|
||||
|
||||
serial_nos = get_serial_nos(d.serial_no)
|
||||
self.update_valuation_rate_for_serial_nos(d, serial_nos)
|
||||
@@ -372,7 +376,16 @@ class StockReconciliation(StockController):
|
||||
where voucher_type=%s and voucher_no=%s""", (self.doctype, self.name))
|
||||
|
||||
sl_entries = []
|
||||
self.get_sle_for_serialized_items(sl_entries)
|
||||
|
||||
serialized_items = []
|
||||
|
||||
for row in self.items:
|
||||
has_serial_no = frappe.get_cached_value("Item", row.item_code, "has_serial_no")
|
||||
if has_serial_no:
|
||||
serialized_items.append(row.item_code)
|
||||
|
||||
if serialized_items:
|
||||
self.get_sle_for_serialized_items(sl_entries, serialized_items)
|
||||
|
||||
if sl_entries:
|
||||
sl_entries.reverse()
|
||||
|
||||
@@ -207,9 +207,9 @@ class TestStockReconciliation(unittest.TestCase):
|
||||
def test_stock_reco_for_serial_and_batch_item(self):
|
||||
set_perpetual_inventory()
|
||||
|
||||
item = frappe.db.exists("Item", {'item_name': 'Batched and Serialised Item'})
|
||||
item = frappe.db.exists("Item", {'item_name': 'Batched and Serialised Item 1'})
|
||||
if not item:
|
||||
item = create_item("Batched and Serialised Item")
|
||||
item = create_item("Batched and Serialised Item 1")
|
||||
item.has_batch_no = 1
|
||||
item.create_new_batch = 1
|
||||
item.has_serial_no = 1
|
||||
@@ -217,7 +217,7 @@ class TestStockReconciliation(unittest.TestCase):
|
||||
item.serial_no_series = "S-.####"
|
||||
item.save()
|
||||
else:
|
||||
item = frappe.get_doc("Item", {'item_name': 'Batched and Serialised Item'})
|
||||
item = frappe.get_doc("Item", {'item_name': 'Batched and Serialised Item 1'})
|
||||
|
||||
warehouse = "_Test Warehouse for Stock Reco2 - _TC"
|
||||
|
||||
@@ -236,7 +236,7 @@ class TestStockReconciliation(unittest.TestCase):
|
||||
self.assertEqual(frappe.db.exists("Batch", batch_no), None)
|
||||
|
||||
if frappe.db.exists("Serial No", serial_nos[0]):
|
||||
frappe.delete_doc("Serial No", serial_nos[0])
|
||||
frappe.delete_doc("Serial No", serial_nos[0])
|
||||
|
||||
def test_stock_reco_for_serial_and_batch_item_with_future_dependent_entry(self):
|
||||
"""
|
||||
@@ -255,9 +255,9 @@ class TestStockReconciliation(unittest.TestCase):
|
||||
|
||||
set_perpetual_inventory()
|
||||
|
||||
item = frappe.db.exists("Item", {'item_name': 'Batched and Serialised Item'})
|
||||
item = frappe.db.exists("Item", {'item_name': 'Batched and Serialised Item 1'})
|
||||
if not item:
|
||||
item = create_item("Batched and Serialised Item")
|
||||
item = create_item("Batched and Serialised Item 1")
|
||||
item.has_batch_no = 1
|
||||
item.create_new_batch = 1
|
||||
item.has_serial_no = 1
|
||||
@@ -265,7 +265,7 @@ class TestStockReconciliation(unittest.TestCase):
|
||||
item.serial_no_series = "S-.####"
|
||||
item.save()
|
||||
else:
|
||||
item = frappe.get_doc("Item", {'item_name': 'Batched and Serialised Item'})
|
||||
item = frappe.get_doc("Item", {'item_name': 'Batched and Serialised Item 1'})
|
||||
|
||||
warehouse = "_Test Warehouse for Stock Reco2 - _TC"
|
||||
|
||||
@@ -392,6 +392,35 @@ class TestStockReconciliation(unittest.TestCase):
|
||||
doc.cancel()
|
||||
frappe.delete_doc(doc.doctype, doc.name)
|
||||
|
||||
def test_stock_reco_with_serial_and_batch(self):
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||
|
||||
warehouse = "_Test Warehouse for Stock Reco1 - _TC"
|
||||
ste1=make_stock_entry(item_code="Stock-Reco-Serial-Item-1",
|
||||
target=warehouse, qty=2, basic_rate=100)
|
||||
|
||||
ste2=make_stock_entry(item_code="Stock-Reco-batch-Item-1",
|
||||
target=warehouse, qty=2, basic_rate=100)
|
||||
|
||||
sr = create_stock_reconciliation(item_code="Stock-Reco-Serial-Item-1",
|
||||
warehouse = warehouse, rate=200, do_not_submit=True)
|
||||
|
||||
sr.append("items", {
|
||||
"item_code": "Stock-Reco-batch-Item-1",
|
||||
"warehouse": warehouse,
|
||||
"batch_no": ste2.items[0].batch_no,
|
||||
"valuation_rate": 200
|
||||
})
|
||||
|
||||
sr.submit()
|
||||
sle = frappe.get_all("Stock Ledger Entry", filters={"item_code": "Stock-Reco-batch-Item-1",
|
||||
"warehouse": warehouse, "voucher_no": sr.name, "voucher_type": sr.doctype})
|
||||
|
||||
self.assertEquals(len(sle), 1)
|
||||
|
||||
for doc in [sr, ste2, ste1]:
|
||||
doc.cancel()
|
||||
|
||||
def insert_existing_sle(warehouse):
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||
|
||||
|
||||
Reference in New Issue
Block a user