From 7661e5ed96a49972363b41c4dedb9a8698b9f422 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 26 Jun 2026 10:25:18 +0530 Subject: [PATCH 1/2] test: add coverage for Serial No Ledger report Co-Authored-By: Claude Opus 4.8 (1M context) --- .../serial_no_ledger/test_serial_no_ledger.py | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 erpnext/stock/report/serial_no_ledger/test_serial_no_ledger.py diff --git a/erpnext/stock/report/serial_no_ledger/test_serial_no_ledger.py b/erpnext/stock/report/serial_no_ledger/test_serial_no_ledger.py new file mode 100644 index 00000000000..ca87efd7617 --- /dev/null +++ b/erpnext/stock/report/serial_no_ledger/test_serial_no_ledger.py @@ -0,0 +1,74 @@ +# Copyright (c) 2026, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +import frappe + +from erpnext.stock.doctype.item.test_item import make_item +from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry +from erpnext.stock.report.serial_no_ledger.serial_no_ledger import execute +from erpnext.tests.utils import ERPNextTestSuite + + +class TestSerialNoLedger(ERPNextTestSuite): + def run_report(self, **extra): + filters = { + "company": "_Test Company", + "warehouse": "_Test Warehouse - _TC", + "posting_date": "2026-06-30", + } + filters.update(extra) + return execute(frappe._dict(filters))[1] + + def make_serial_item(self) -> str: + return make_item( + properties={ + "is_stock_item": 1, + "has_serial_no": 1, + "serial_no_series": "SNL-.#####", + } + ).name + + def test_receipt_appears_in_serial_ledger(self): + item = self.make_serial_item() + stock_entry = make_stock_entry( + item_code=item, + to_warehouse="_Test Warehouse - _TC", + qty=2, + rate=100, + posting_date="2026-06-01", + ) + + serial_nos = frappe.get_all("Serial No", {"item_code": item}, pluck="name") + self.assertEqual(len(serial_nos), 2) + serial_no = serial_nos[0] + + data = self.run_report(item_code=item, serial_no=serial_no) + + self.assertEqual(len(data), 1) + row = data[0] + self.assertEqual(row["serial_no"], serial_no) + self.assertEqual(row["voucher_type"], "Stock Entry") + self.assertEqual(row["voucher_no"], stock_entry.name) + self.assertEqual(row["warehouse"], "_Test Warehouse - _TC") + self.assertEqual(row["qty"], 1) + self.assertEqual(row["valuation_rate"], 100) + + def test_filter_by_item_lists_all_received_serials(self): + item = self.make_serial_item() + make_stock_entry( + item_code=item, + to_warehouse="_Test Warehouse - _TC", + qty=2, + rate=150, + posting_date="2026-06-01", + ) + + serial_nos = frappe.get_all("Serial No", {"item_code": item}, pluck="name") + + data = self.run_report(item_code=item) + + ledger_serials = sorted(row["serial_no"] for row in data) + self.assertEqual(ledger_serials, sorted(serial_nos)) + for row in data: + self.assertEqual(row["qty"], 1) + self.assertEqual(row["valuation_rate"], 150) From dc4f5ce0abdf11296e106b27c0bd4d1f61a68f74 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 26 Jun 2026 13:27:56 +0530 Subject: [PATCH 2/2] test: reuse BootStrapTestData master data to reduce runtime Co-Authored-By: Claude Opus 4.8 (1M context) --- .../serial_no_ledger/test_serial_no_ledger.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/erpnext/stock/report/serial_no_ledger/test_serial_no_ledger.py b/erpnext/stock/report/serial_no_ledger/test_serial_no_ledger.py index ca87efd7617..444c2d95755 100644 --- a/erpnext/stock/report/serial_no_ledger/test_serial_no_ledger.py +++ b/erpnext/stock/report/serial_no_ledger/test_serial_no_ledger.py @@ -3,7 +3,6 @@ import frappe -from erpnext.stock.doctype.item.test_item import make_item from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry from erpnext.stock.report.serial_no_ledger.serial_no_ledger import execute from erpnext.tests.utils import ERPNextTestSuite @@ -13,26 +12,20 @@ class TestSerialNoLedger(ERPNextTestSuite): def run_report(self, **extra): filters = { "company": "_Test Company", - "warehouse": "_Test Warehouse - _TC", + "warehouse": "Stores - _TC", "posting_date": "2026-06-30", } filters.update(extra) return execute(frappe._dict(filters))[1] def make_serial_item(self) -> str: - return make_item( - properties={ - "is_stock_item": 1, - "has_serial_no": 1, - "serial_no_series": "SNL-.#####", - } - ).name + return "_Test Serialized Item With Series" def test_receipt_appears_in_serial_ledger(self): item = self.make_serial_item() stock_entry = make_stock_entry( item_code=item, - to_warehouse="_Test Warehouse - _TC", + to_warehouse="Stores - _TC", qty=2, rate=100, posting_date="2026-06-01", @@ -49,7 +42,7 @@ class TestSerialNoLedger(ERPNextTestSuite): self.assertEqual(row["serial_no"], serial_no) self.assertEqual(row["voucher_type"], "Stock Entry") self.assertEqual(row["voucher_no"], stock_entry.name) - self.assertEqual(row["warehouse"], "_Test Warehouse - _TC") + self.assertEqual(row["warehouse"], "Stores - _TC") self.assertEqual(row["qty"], 1) self.assertEqual(row["valuation_rate"], 100) @@ -57,7 +50,7 @@ class TestSerialNoLedger(ERPNextTestSuite): item = self.make_serial_item() make_stock_entry( item_code=item, - to_warehouse="_Test Warehouse - _TC", + to_warehouse="Stores - _TC", qty=2, rate=150, posting_date="2026-06-01",