mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-23 12:06:43 +00:00
test: make Item Prices tests deterministic (fresh items, label-based columns)
This commit is contained in:
@@ -3,33 +3,36 @@
|
||||
|
||||
import frappe
|
||||
|
||||
from erpnext.stock.doctype.item.test_item import make_item
|
||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||
from erpnext.stock.report.item_prices.item_prices import execute
|
||||
from erpnext.tests.utils import ERPNextTestSuite
|
||||
|
||||
# Positional columns returned by the report (it returns string-format columns,
|
||||
# not dicts, so rows are plain lists indexed by position).
|
||||
ITEM_CODE = 0
|
||||
LAST_PURCHASE_RATE = 6
|
||||
VALUATION_RATE = 7
|
||||
SALES_PRICE_LIST = 8
|
||||
PURCHASE_PRICE_LIST = 9
|
||||
|
||||
|
||||
class TestItemPrices(ERPNextTestSuite):
|
||||
"""Correctness tests for the Item Prices report."""
|
||||
|
||||
def run_report(self, **extra):
|
||||
filters = frappe._dict({"items": "Enabled Items only", **extra})
|
||||
return execute(filters)[1]
|
||||
return execute(filters)[:2]
|
||||
|
||||
def row_for(self, data, item_code):
|
||||
# The report returns string-format columns ("Label:fieldtype:width"); resolve positions
|
||||
# by label so the tests self-correct if the column order changes.
|
||||
@staticmethod
|
||||
def labels(columns):
|
||||
return [c.split(":")[0] if isinstance(c, str) else c.get("label") for c in columns]
|
||||
|
||||
def row_for(self, columns, data, item_code):
|
||||
item_idx = self.labels(columns).index("Item")
|
||||
for row in data:
|
||||
if row[ITEM_CODE] == item_code:
|
||||
if row[item_idx] == item_code:
|
||||
return row
|
||||
self.fail(f"No report row found for item {item_code}")
|
||||
|
||||
def cell(self, columns, row, label):
|
||||
return row[self.labels(columns).index(label)]
|
||||
|
||||
def test_item_selling_price_listed(self):
|
||||
"""A Standard Selling Item Price shows up in the Sales Price List column."""
|
||||
item = "_Test Item"
|
||||
@@ -42,12 +45,13 @@ class TestItemPrices(ERPNextTestSuite):
|
||||
}
|
||||
).insert()
|
||||
|
||||
row = self.row_for(self.run_report(), item)
|
||||
self.assertIn("250.0", row[SALES_PRICE_LIST])
|
||||
self.assertIn("Standard Selling", row[SALES_PRICE_LIST])
|
||||
columns, data = self.run_report()
|
||||
row = self.row_for(columns, data, item)
|
||||
self.assertIn("250.0", self.cell(columns, row, "Sales Price List"))
|
||||
self.assertIn("Standard Selling", self.cell(columns, row, "Sales Price List"))
|
||||
# A selling price must not leak into the buying column.
|
||||
self.assertNotIn("250.0", row[PURCHASE_PRICE_LIST] or "")
|
||||
self.assertNotIn("Standard Selling", row[PURCHASE_PRICE_LIST] or "")
|
||||
self.assertNotIn("250.0", self.cell(columns, row, "Purchase Price List") or "")
|
||||
self.assertNotIn("Standard Selling", self.cell(columns, row, "Purchase Price List") or "")
|
||||
|
||||
def test_item_buying_price_listed(self):
|
||||
"""A Standard Buying Item Price shows up in the Purchase Price List column."""
|
||||
@@ -61,30 +65,34 @@ class TestItemPrices(ERPNextTestSuite):
|
||||
}
|
||||
).insert()
|
||||
|
||||
row = self.row_for(self.run_report(), item)
|
||||
self.assertIn("175.0", row[PURCHASE_PRICE_LIST])
|
||||
self.assertIn("Standard Buying", row[PURCHASE_PRICE_LIST])
|
||||
columns, data = self.run_report()
|
||||
row = self.row_for(columns, data, item)
|
||||
self.assertIn("175.0", self.cell(columns, row, "Purchase Price List"))
|
||||
self.assertIn("Standard Buying", self.cell(columns, row, "Purchase Price List"))
|
||||
# A buying price must not leak into the selling column.
|
||||
self.assertNotIn("175.0", row[SALES_PRICE_LIST] or "")
|
||||
self.assertNotIn("Standard Buying", row[SALES_PRICE_LIST] or "")
|
||||
self.assertNotIn("175.0", self.cell(columns, row, "Sales Price List") or "")
|
||||
self.assertNotIn("Standard Buying", self.cell(columns, row, "Sales Price List") or "")
|
||||
|
||||
def test_last_purchase_rate_from_receipt(self):
|
||||
"""The latest purchase rate (from a Purchase Receipt) shows in the Last Purchase Rate column."""
|
||||
item = "_Test Item"
|
||||
# a fresh item has no other committed purchase records, so it is the only (and latest) row
|
||||
item = make_item(properties={"is_stock_item": 1, "is_purchase_item": 1}).name
|
||||
make_purchase_receipt(
|
||||
item_code=item, qty=5, rate=500, company="_Test Company", posting_date="2026-06-01"
|
||||
)
|
||||
|
||||
row = self.row_for(self.run_report(), item)
|
||||
self.assertEqual(row[LAST_PURCHASE_RATE], 500)
|
||||
columns, data = self.run_report()
|
||||
row = self.row_for(columns, data, item)
|
||||
self.assertEqual(self.cell(columns, row, "Last Purchase Rate"), 500)
|
||||
|
||||
def test_valuation_rate_from_stock(self):
|
||||
"""The Bin valuation rate shows in the Valuation Rate column."""
|
||||
# _Test FG Item has no opening-stock baseline, so its valuation reflects only this receipt
|
||||
item = "_Test FG Item"
|
||||
# a fresh item has no other committed bins, so its average valuation is exactly this receipt's rate
|
||||
item = make_item(properties={"is_stock_item": 1}).name
|
||||
make_stock_entry(
|
||||
item_code=item, to_warehouse="Stores - _TC", qty=10, rate=250, posting_date="2026-06-01"
|
||||
)
|
||||
|
||||
row = self.row_for(self.run_report(), item)
|
||||
self.assertEqual(row[VALUATION_RATE], 250)
|
||||
columns, data = self.run_report()
|
||||
row = self.row_for(columns, data, item)
|
||||
self.assertEqual(self.cell(columns, row, "Valuation Rate"), 250)
|
||||
|
||||
Reference in New Issue
Block a user