fix: incorrect stock levels in the Batch
diff --git a/erpnext/stock/doctype/batch/batch.js b/erpnext/stock/doctype/batch/batch.js
index fa8b2be..3b07e4e 100644
--- a/erpnext/stock/doctype/batch/batch.js
+++ b/erpnext/stock/doctype/batch/batch.js
@@ -47,8 +47,6 @@
return;
}
- debugger
-
const section = frm.dashboard.add_section('', __("Stock Levels"));
// sort by qty
diff --git a/erpnext/stock/doctype/batch/test_batch.py b/erpnext/stock/doctype/batch/test_batch.py
index 0e4132d..7fb672c 100644
--- a/erpnext/stock/doctype/batch/test_batch.py
+++ b/erpnext/stock/doctype/batch/test_batch.py
@@ -59,6 +59,73 @@
return receipt
+ def test_batch_stock_levels(self, batch_qty=100):
+ """Test automated batch creation from Purchase Receipt"""
+ self.make_batch_item("ITEM-BATCH-1")
+
+ receipt = frappe.get_doc(
+ dict(
+ doctype="Purchase Receipt",
+ supplier="_Test Supplier",
+ company="_Test Company",
+ items=[dict(item_code="ITEM-BATCH-1", qty=10, rate=10, warehouse="Stores - _TC")],
+ )
+ ).insert()
+ receipt.submit()
+
+ receipt.load_from_db()
+ batch_no = get_batch_from_bundle(receipt.items[0].serial_and_batch_bundle)
+
+ bundle_id = (
+ SerialBatchCreation(
+ {
+ "item_code": "ITEM-BATCH-1",
+ "warehouse": "_Test Warehouse - _TC",
+ "actual_qty": 20,
+ "voucher_type": "Purchase Receipt",
+ "batches": frappe._dict({batch_no: 20}),
+ "type_of_transaction": "Inward",
+ "company": receipt.company,
+ }
+ )
+ .make_serial_and_batch_bundle()
+ .name
+ )
+
+ receipt2 = frappe.get_doc(
+ dict(
+ doctype="Purchase Receipt",
+ supplier="_Test Supplier",
+ company="_Test Company",
+ items=[
+ dict(
+ item_code="ITEM-BATCH-1",
+ qty=20,
+ rate=10,
+ warehouse="_Test Warehouse - _TC",
+ serial_and_batch_bundle=bundle_id,
+ )
+ ],
+ )
+ ).insert()
+ receipt2.submit()
+
+ receipt.load_from_db()
+ receipt2.load_from_db()
+
+ self.assertTrue(receipt.items[0].serial_and_batch_bundle)
+ self.assertTrue(receipt2.items[0].serial_and_batch_bundle)
+
+ batchwise_qty = frappe._dict({})
+ for receipt in [receipt, receipt2]:
+ batch_no = get_batch_from_bundle(receipt.items[0].serial_and_batch_bundle)
+ key = (batch_no, receipt.items[0].warehouse)
+ batchwise_qty[key] = receipt.items[0].qty
+
+ batches = get_batch_qty(batch_no)
+ for d in batches:
+ self.assertEqual(d.qty, batchwise_qty[(d.batch_no, d.warehouse)])
+
def test_stock_entry_incoming(self):
"""Test batch creation via Stock Entry (Work Order)"""
diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py
index 75b6ec7..0c6d33b 100644
--- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py
+++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py
@@ -1272,24 +1272,29 @@
if ids:
for d in get_serial_batch_ledgers(kwargs.item_code, docstatus=1, name=ids):
- if d.batch_no not in pos_batches:
- pos_batches[d.batch_no] = frappe._dict(
+ key = (d.batch_no, d.warehouse)
+ if key not in pos_batches:
+ pos_batches[key] = frappe._dict(
{
"qty": d.qty,
"warehouse": d.warehouse,
}
)
else:
- pos_batches[d.batch_no].qty += d.qty
+ pos_batches[key].qty += d.qty
for row in pos_invoices:
if not row.batch_no:
continue
- if row.batch_no in pos_batches:
- pos_batches[row.batch_no] -= row.qty * -1 if row.is_return else row.qty
+ if kwargs.get("batch_no") and row.batch_no != kwargs.get("batch_no"):
+ continue
+
+ key = (row.batch_no, row.warehouse)
+ if key in pos_batches:
+ pos_batches[key] -= row.qty * -1 if row.is_return else row.qty
else:
- pos_batches[row.batch_no] = frappe._dict(
+ pos_batches[key] = frappe._dict(
{
"qty": (row.qty * -1 if row.is_return else row.qty),
"warehouse": row.warehouse,
@@ -1309,6 +1314,7 @@
update_available_batches(available_batches, stock_ledgers_batches, pos_invoice_batches)
available_batches = list(filter(lambda x: x.qty > 0, available_batches))
+
if not qty:
return available_batches
@@ -1351,10 +1357,11 @@
def update_available_batches(available_batches, reserved_batches=None, pos_invoice_batches=None):
for batches in [reserved_batches, pos_invoice_batches]:
if batches:
- for batch_no, data in batches.items():
+ for key, data in batches.items():
+ batch_no, warehouse = key
batch_not_exists = True
for batch in available_batches:
- if batch.batch_no == batch_no and batch.warehouse == data.warehouse:
+ if batch.batch_no == batch_no and batch.warehouse == warehouse:
batch.qty += data.qty
batch_not_exists = False
@@ -1563,7 +1570,7 @@
.groupby(stock_ledger_entry.batch_no, stock_ledger_entry.warehouse)
)
- for field in ["warehouse", "item_code"]:
+ for field in ["warehouse", "item_code", "batch_no"]:
if not kwargs.get(field):
continue
@@ -1582,6 +1589,10 @@
data = query.run(as_dict=True)
batches = {}
for d in data:
- batches[d.batch_no] = d
+ key = (d.batch_no, d.warehouse)
+ if key not in batches:
+ batches[key] = d
+ else:
+ batches[key].qty += d.qty
return batches