diff --git a/erpnext/stock/doctype/bin/bin.js b/erpnext/stock/doctype/bin/bin.js index c725b691db4..5817d318965 100644 --- a/erpnext/stock/doctype/bin/bin.js +++ b/erpnext/stock/doctype/bin/bin.js @@ -3,17 +3,17 @@ frappe.ui.form.on("Bin", { refresh(frm) { - frm.trigger("recalculate_bin_quantity"); + frm.trigger("recalculate_values"); }, - recalculate_bin_quantity(frm) { - frm.add_custom_button(__("Recalculate Bin Qty"), () => { + recalculate_values(frm) { + frm.add_custom_button(__("Recalculate Values"), () => { frappe.call({ - method: "recalculate_qty", + method: "recalculate_values", freeze: true, doc: frm.doc, callback: function (r) { - frappe.show_alert(__("Bin Qty Recalculated"), 2); + frappe.show_alert(__("Bin Values Recalculated"), 2); }, }); }); diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py index 346de69532d..ae3b06d22ea 100644 --- a/erpnext/stock/doctype/bin/bin.py +++ b/erpnext/stock/doctype/bin/bin.py @@ -37,7 +37,7 @@ class Bin(Document): # end: auto-generated types @frappe.whitelist() - def recalculate_qty(self): + def recalculate_values(self): from erpnext.manufacturing.doctype.work_order.work_order import get_reserved_qty_for_production from erpnext.stock.stock_balance import ( get_indented_qty, @@ -46,7 +46,10 @@ class Bin(Document): get_reserved_qty, ) - self.actual_qty = get_actual_qty(self.item_code, self.warehouse) + last_sle = get_last_sle_values(self.item_code, self.warehouse) + self.actual_qty = last_sle.qty_after_transaction + self.valuation_rate = last_sle.valuation_rate + self.stock_value = last_sle.stock_value self.planned_qty = get_planned_qty(self.item_code, self.warehouse) self.indented_qty = get_indented_qty(self.item_code, self.warehouse) self.ordered_qty = get_ordered_qty(self.item_code, self.warehouse) @@ -302,20 +305,23 @@ def update_qty(bin_name, args): def get_actual_qty(item_code, warehouse): + return get_last_sle_values(item_code, warehouse).qty_after_transaction + + +def get_last_sle_values(item_code, warehouse): sle = frappe.qb.DocType("Stock Ledger Entry") - last_sle_qty = ( + last_sle = ( frappe.qb.from_(sle) - .select(sle.qty_after_transaction) + .select(sle.qty_after_transaction, sle.valuation_rate, sle.stock_value) .where((sle.item_code == item_code) & (sle.warehouse == warehouse) & (sle.is_cancelled == 0)) .orderby(sle.posting_datetime, order=Order.desc) .orderby(sle.creation, order=Order.desc) .limit(1) - .run() + .run(as_dict=True) ) - actual_qty = 0.0 - if last_sle_qty: - actual_qty = last_sle_qty[0][0] + if last_sle: + return last_sle[0] - return actual_qty + return frappe._dict(qty_after_transaction=0.0, valuation_rate=0.0, stock_value=0.0) diff --git a/erpnext/stock/doctype/bin/test_bin.py b/erpnext/stock/doctype/bin/test_bin.py index ef21bcf7833..92f8c6bbaaa 100644 --- a/erpnext/stock/doctype/bin/test_bin.py +++ b/erpnext/stock/doctype/bin/test_bin.py @@ -26,6 +26,35 @@ class TestBin(ERPNextTestSuite): bin = _create_bin(item_code, warehouse) self.assertEqual(bin.item_code, item_code) + def test_recalculate_values(self): + from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry + + item_code = make_item("_TestBinRecalculateValues").name + warehouse = "_Test Warehouse - _TC" + make_stock_entry(item_code=item_code, target=warehouse, qty=10, rate=100) + + bin = frappe.get_doc("Bin", {"item_code": item_code, "warehouse": warehouse}) + bin.db_set({"actual_qty": 0, "valuation_rate": 0, "stock_value": 0}) + bin.reload() + bin.recalculate_values() + + self.assertEqual(bin.actual_qty, 10) + self.assertEqual(bin.valuation_rate, 100) + self.assertEqual(bin.stock_value, 1000) + + def test_recalculate_values_without_sle(self): + item_code = make_item("_TestBinRecalculateValuesNoSLE").name + warehouse = "_Test Warehouse - _TC" + + bin = _create_bin(item_code, warehouse) + bin.db_set({"actual_qty": 5, "valuation_rate": 50, "stock_value": 250}) + bin.reload() + bin.recalculate_values() + + self.assertEqual(bin.actual_qty, 0) + self.assertEqual(bin.valuation_rate, 0) + self.assertEqual(bin.stock_value, 0) + def test_index_exists(self): indexes = frappe.db.sql("show index from tabBin where Non_unique = 0", as_dict=1) if not any(index.get("Key_name") == "unique_item_warehouse" for index in indexes):