From dddaa80f9963e4964cb49eabc08bf992a6d22e77 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 26 Jun 2026 10:25:11 +0530 Subject: [PATCH] test: add coverage for Serial and Batch Summary report Co-Authored-By: Claude Opus 4.8 (1M context) --- .../test_serial_and_batch_summary.py | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 erpnext/stock/report/serial_and_batch_summary/test_serial_and_batch_summary.py diff --git a/erpnext/stock/report/serial_and_batch_summary/test_serial_and_batch_summary.py b/erpnext/stock/report/serial_and_batch_summary/test_serial_and_batch_summary.py new file mode 100644 index 00000000000..38fb65dec7d --- /dev/null +++ b/erpnext/stock/report/serial_and_batch_summary/test_serial_and_batch_summary.py @@ -0,0 +1,75 @@ +# Copyright (c) 2026, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +import frappe + +from erpnext.tests.utils import ERPNextTestSuite + + +class TestSerialAndBatchSummary(ERPNextTestSuite): + def run_report(self, **extra): + from erpnext.stock.report.serial_and_batch_summary.serial_and_batch_summary import execute + + return execute(frappe._dict(extra))[1] + + @staticmethod + def _cancel_and_delete_stock_entry(name): + if not frappe.db.exists("Stock Entry", name): + return + doc = frappe.get_doc("Stock Entry", name) + if doc.docstatus == 1: + doc.cancel() + frappe.delete_doc("Stock Entry", name, force=1) + + def test_serial_receipt_listed(self): + from erpnext.stock.doctype.item.test_item import make_item + from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry + + item = make_item( + properties={ + "is_stock_item": 1, + "has_serial_no": 1, + "serial_no_series": "SBS-.#####", + } + ).name + se = make_stock_entry(item_code=item, to_warehouse="_Test Warehouse - _TC", qty=3, basic_rate=100) + self.addCleanup(self._cancel_and_delete_stock_entry, se.name) + + data = self.run_report(voucher_no=[se.name], voucher_type="Stock Entry") + + self.assertEqual(len(data), 3) + self.assertEqual(len({row.serial_no for row in data}), 3) + for row in data: + self.assertTrue(row.serial_no) + self.assertEqual(row.qty, 1) + self.assertEqual(row.incoming_rate, 100) + self.assertEqual(row.warehouse, "_Test Warehouse - _TC") + self.assertEqual(row.voucher_no, se.name) + + def test_batch_receipt_listed(self): + from erpnext.stock.doctype.item.test_item import make_item + from erpnext.stock.doctype.serial_and_batch_bundle.test_serial_and_batch_bundle import ( + get_batch_from_bundle, + ) + from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry + + item = make_item( + properties={ + "is_stock_item": 1, + "has_batch_no": 1, + "create_new_batch": 1, + "batch_number_series": "SBB-.#####", + } + ).name + se = make_stock_entry(item_code=item, to_warehouse="_Test Warehouse - _TC", qty=10, basic_rate=50) + self.addCleanup(self._cancel_and_delete_stock_entry, se.name) + batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle) + + data = self.run_report(voucher_no=[se.name], voucher_type="Stock Entry") + + row = next((d for d in data if d.batch_no == batch_no), None) + self.assertIsNotNone(row) + self.assertEqual(row.qty, 10) + self.assertEqual(row.incoming_rate, 50) + self.assertEqual(row.warehouse, "_Test Warehouse - _TC") + self.assertEqual(row.voucher_no, se.name)