From 6595a32d909bc7a9d976223bec051664739b17e5 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 26 Jun 2026 10:40:07 +0530 Subject: [PATCH 1/2] test: add coverage for COGS By Item Group report Co-Authored-By: Claude Opus 4.8 (1M context) --- .../test_cogs_by_item_group.py | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 erpnext/stock/report/cogs_by_item_group/test_cogs_by_item_group.py diff --git a/erpnext/stock/report/cogs_by_item_group/test_cogs_by_item_group.py b/erpnext/stock/report/cogs_by_item_group/test_cogs_by_item_group.py new file mode 100644 index 00000000000..eb5dc7a434d --- /dev/null +++ b/erpnext/stock/report/cogs_by_item_group/test_cogs_by_item_group.py @@ -0,0 +1,67 @@ +# Copyright (c) 2026, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +import frappe + +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +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.cogs_by_item_group.cogs_by_item_group import execute +from erpnext.tests.utils import ERPNextTestSuite + + +class TestCogsByItemGroup(ERPNextTestSuite): + def run_report(self, **extra) -> list: + filters = frappe._dict( + company="_Test Company with perpetual inventory", + from_date="2026-01-01", + to_date="2026-12-31", + ) + filters.update(extra) + return execute(filters)[1] + + def test_cogs_for_item_group(self): + frappe.get_doc( + { + "doctype": "Item Group", + "item_group_name": "_Test COGS Group", + "parent_item_group": "All Item Groups", + "is_group": 0, + } + ).insert(ignore_if_duplicate=True) + + item = make_item( + properties={"is_stock_item": 1, "is_sales_item": 1, "item_group": "_Test COGS Group"} + ).name + + make_stock_entry( + item_code=item, + to_warehouse="Stores - TCP1", + qty=10, + rate=100, + company="_Test Company with perpetual inventory", + posting_date="2026-06-01", + ) + + # A Sales Invoice with update_stock delivers the goods and books the COGS + # against the company's default expense account, which the report keys on. + create_sales_invoice( + item_code=item, + qty=4, + rate=150, + warehouse="Stores - TCP1", + company="_Test Company with perpetual inventory", + update_stock=1, + cost_center="Main - TCP1", + parent_cost_center="Main - TCP1", + debit_to="Debtors - TCP1", + income_account="Sales - TCP1", + expense_account="Cost of Goods Sold - TCP1", + posting_date="2026-06-02", + ) + + data = self.run_report() + rows = [row for row in data if "_Test COGS Group" in row.get("item_group")] + self.assertTrue(rows, "No row found for _Test COGS Group") + # 4 units delivered at 100 valuation rate -> 400 COGS. + self.assertEqual(rows[0].get("cogs_debit"), 400) From 364250467f11172af3a33180b70e9e76d1a49ef4 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 26 Jun 2026 13:26:19 +0530 Subject: [PATCH 2/2] test: reuse BootStrapTestData master data to reduce runtime Co-Authored-By: Claude Opus 4.8 (1M context) --- .../test_cogs_by_item_group.py | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/erpnext/stock/report/cogs_by_item_group/test_cogs_by_item_group.py b/erpnext/stock/report/cogs_by_item_group/test_cogs_by_item_group.py index eb5dc7a434d..36b9d4ad1da 100644 --- a/erpnext/stock/report/cogs_by_item_group/test_cogs_by_item_group.py +++ b/erpnext/stock/report/cogs_by_item_group/test_cogs_by_item_group.py @@ -4,7 +4,6 @@ import frappe from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice -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.cogs_by_item_group.cogs_by_item_group import execute from erpnext.tests.utils import ERPNextTestSuite @@ -21,18 +20,9 @@ class TestCogsByItemGroup(ERPNextTestSuite): return execute(filters)[1] def test_cogs_for_item_group(self): - frappe.get_doc( - { - "doctype": "Item Group", - "item_group_name": "_Test COGS Group", - "parent_item_group": "All Item Groups", - "is_group": 0, - } - ).insert(ignore_if_duplicate=True) - - item = make_item( - properties={"is_stock_item": 1, "is_sales_item": 1, "item_group": "_Test COGS Group"} - ).name + # Reuse the bootstrap item `_Test Item` (item group `_Test Item Group`). + # It has zero stock in `Stores - TCP1`, so this receipt starts from a clean balance. + item = "_Test Item" make_stock_entry( item_code=item, @@ -61,7 +51,7 @@ class TestCogsByItemGroup(ERPNextTestSuite): ) data = self.run_report() - rows = [row for row in data if "_Test COGS Group" in row.get("item_group")] - self.assertTrue(rows, "No row found for _Test COGS Group") + rows = [row for row in data if "_Test Item Group" in row.get("item_group")] + self.assertTrue(rows, "No row found for _Test Item Group") # 4 units delivered at 100 valuation rate -> 400 COGS. self.assertEqual(rows[0].get("cogs_debit"), 400)