diff --git a/erpnext/stock/deprecated_serial_batch.py b/erpnext/stock/deprecated_serial_batch.py index b3f4c2dead45..7611d751fdd3 100644 --- a/erpnext/stock/deprecated_serial_batch.py +++ b/erpnext/stock/deprecated_serial_batch.py @@ -181,6 +181,9 @@ def calculate_avg_rate_for_non_batchwise_valuation(self): stock_value_change = self.batch_avg_rate[batch_no] * ledger.qty self.stock_value_change += stock_value_change + self.non_batchwise_balance_value[batch_no] -= stock_value_change + self.non_batchwise_balance_qty[batch_no] -= ledger.qty + frappe.db.set_value( "Serial and Batch Entry", ledger.name, @@ -220,7 +223,6 @@ def set_balance_value_from_sl_entries(self) -> None: .select( sle.batch_no, Sum(sle.actual_qty).as_("batch_qty"), - Sum(sle.stock_value_difference).as_("batch_value"), ) .where( (sle.item_code == self.sle.item_code) @@ -237,11 +239,59 @@ def set_balance_value_from_sl_entries(self) -> None: if self.sle.name: query = query.where(sle.name != self.sle.name) - for d in query.run(as_dict=True): - self.non_batchwise_balance_value[d.batch_no] += flt(d.batch_value) - self.non_batchwise_balance_qty[d.batch_no] += flt(d.batch_qty) + batch_data = query.run(as_dict=True) + for d in batch_data: self.available_qty[d.batch_no] += flt(d.batch_qty) + last_sle = self.get_last_sle_for_non_batch() + for d in batch_data: + self.non_batchwise_balance_value[d.batch_no] += flt(last_sle.stock_value) + self.non_batchwise_balance_qty[d.batch_no] += flt(last_sle.qty_after_transaction) + + def get_last_sle_for_non_batch(self): + from erpnext.stock.utils import get_combine_datetime + + sle = frappe.qb.DocType("Stock Ledger Entry") + batch = frappe.qb.DocType("Batch") + + posting_datetime = get_combine_datetime(self.sle.posting_date, self.sle.posting_time) + if not self.sle.creation: + posting_datetime = posting_datetime + datetime.timedelta(milliseconds=1) + + timestamp_condition = sle.posting_datetime < posting_datetime + + if self.sle.creation: + timestamp_condition |= (sle.posting_datetime == posting_datetime) & ( + sle.creation < self.sle.creation + ) + + query = ( + frappe.qb.from_(sle) + .inner_join(batch) + .on(sle.batch_no == batch.name) + .select( + sle.stock_value, + sle.qty_after_transaction, + ) + .where( + (sle.item_code == self.sle.item_code) + & (sle.warehouse == self.sle.warehouse) + & (sle.batch_no.isnotnull()) + & (batch.use_batchwise_valuation == 0) + & (sle.is_cancelled == 0) + ) + .where(timestamp_condition) + .orderby(sle.posting_datetime, order=Order.desc) + .orderby(sle.creation, order=Order.desc) + .limit(1) + ) + + if self.sle.name: + query = query.where(sle.name != self.sle.name) + + data = query.run(as_dict=True) + return data[0] if data else {} + @deprecated def set_balance_value_from_bundle(self) -> None: bundle = frappe.qb.DocType("Serial and Batch Bundle") diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py index 647082baa687..45a474df2b70 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py @@ -166,7 +166,7 @@ def test_old_batch_valuation(self): for qty, valuation in {10: 100, 20: 200}.items(): stock_queue.append([qty, valuation]) qty_after_transaction += qty - balance_value += qty_after_transaction * valuation + balance_value += qty * valuation doc = frappe.get_doc( { @@ -177,6 +177,7 @@ def test_old_batch_valuation(self): "incoming_rate": valuation, "qty_after_transaction": qty_after_transaction, "stock_value_difference": valuation * qty, + "stock_value": balance_value, "balance_value": balance_value, "valuation_rate": balance_value / qty_after_transaction, "actual_qty": qty,