-
Notifications
You must be signed in to change notification settings - Fork 7.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #34356 from frappe/mergify/bp/version-14-hotfix/pr…
…-34352 fix: `BOM Stock Report` (backport #34352)
- Loading branch information
Showing
2 changed files
with
151 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
erpnext/manufacturing/report/bom_stock_report/test_bom_stock_report.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors | ||
# For license information, please see license.txt | ||
|
||
|
||
import frappe | ||
from frappe.exceptions import ValidationError | ||
from frappe.tests.utils import FrappeTestCase | ||
from frappe.utils import floor | ||
|
||
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom | ||
from erpnext.manufacturing.report.bom_stock_report.bom_stock_report import ( | ||
get_bom_stock as bom_stock_report, | ||
) | ||
from erpnext.stock.doctype.item.test_item import make_item | ||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry | ||
|
||
|
||
class TestBomStockReport(FrappeTestCase): | ||
def setUp(self): | ||
self.warehouse = "_Test Warehouse - _TC" | ||
self.fg_item, self.rm_items = create_items() | ||
make_stock_entry(target=self.warehouse, item_code=self.rm_items[0], qty=20, basic_rate=100) | ||
make_stock_entry(target=self.warehouse, item_code=self.rm_items[1], qty=40, basic_rate=200) | ||
self.bom = make_bom(item=self.fg_item, quantity=1, raw_materials=self.rm_items, rm_qty=10) | ||
|
||
def test_bom_stock_report(self): | ||
# Test 1: When `qty_to_produce` is 0. | ||
filters = frappe._dict( | ||
{ | ||
"bom": self.bom.name, | ||
"warehouse": "Stores - _TC", | ||
"qty_to_produce": 0, | ||
} | ||
) | ||
self.assertRaises(ValidationError, bom_stock_report, filters) | ||
|
||
# Test 2: When stock is not available. | ||
data = bom_stock_report( | ||
frappe._dict( | ||
{ | ||
"bom": self.bom.name, | ||
"warehouse": "Stores - _TC", | ||
"qty_to_produce": 1, | ||
} | ||
) | ||
) | ||
expected_data = get_expected_data(self.bom, "Stores - _TC", 1) | ||
self.assertSetEqual(set(tuple(x) for x in data), set(tuple(x) for x in expected_data)) | ||
|
||
# Test 3: When stock is available. | ||
data = bom_stock_report( | ||
frappe._dict( | ||
{ | ||
"bom": self.bom.name, | ||
"warehouse": self.warehouse, | ||
"qty_to_produce": 1, | ||
} | ||
) | ||
) | ||
expected_data = get_expected_data(self.bom, self.warehouse, 1) | ||
self.assertSetEqual(set(tuple(x) for x in data), set(tuple(x) for x in expected_data)) | ||
|
||
|
||
def create_items(): | ||
fg_item = make_item(properties={"is_stock_item": 1}).name | ||
rm_item1 = make_item( | ||
properties={ | ||
"is_stock_item": 1, | ||
"standard_rate": 100, | ||
"opening_stock": 100, | ||
"last_purchase_rate": 100, | ||
} | ||
).name | ||
rm_item2 = make_item( | ||
properties={ | ||
"is_stock_item": 1, | ||
"standard_rate": 200, | ||
"opening_stock": 200, | ||
"last_purchase_rate": 200, | ||
} | ||
).name | ||
|
||
return fg_item, [rm_item1, rm_item2] | ||
|
||
|
||
def get_expected_data(bom, warehouse, qty_to_produce, show_exploded_view=False): | ||
expected_data = [] | ||
|
||
for item in bom.get("exploded_items") if show_exploded_view else bom.get("items"): | ||
in_stock_qty = frappe.get_cached_value( | ||
"Bin", {"item_code": item.item_code, "warehouse": warehouse}, "actual_qty" | ||
) | ||
|
||
expected_data.append( | ||
[ | ||
item.item_code, | ||
item.description, | ||
item.stock_qty, | ||
item.stock_uom, | ||
item.stock_qty * qty_to_produce / bom.quantity, | ||
in_stock_qty, | ||
floor(in_stock_qty / (item.stock_qty * qty_to_produce / bom.quantity)) | ||
if in_stock_qty | ||
else None, | ||
] | ||
) | ||
|
||
return expected_data |