From dec0caeac56453a63fbc8e24f76e33e1fec56eb6 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 13:13:57 +0530 Subject: [PATCH] fix: valuation for batch (backport #45335) (#45420) * fix: valuation for batch (cherry picked from commit 5088d8576ff0edabaa04bfd1e3b7339666ef5154) # Conflicts: # erpnext/stock/deprecated_serial_batch.py * fix: version (cherry picked from commit 8028dd2683282e60bfa74dbd445db32d748a8d24) # Conflicts: # .github/workflows/server-tests-mariadb.yml * chore: fix conflicts * chore: fix conflicts * chore: fix conflicts --------- Co-authored-by: Rohit Waghchaure --- erpnext/stock/deprecated_serial_batch.py | 70 ++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/erpnext/stock/deprecated_serial_batch.py b/erpnext/stock/deprecated_serial_batch.py index 7611d751fdd..38e820c4c4f 100644 --- a/erpnext/stock/deprecated_serial_batch.py +++ b/erpnext/stock/deprecated_serial_batch.py @@ -245,8 +245,9 @@ class DeprecatedBatchNoValuation: 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) + if self.available_qty.get(d.batch_no): + 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 @@ -292,6 +293,58 @@ class DeprecatedBatchNoValuation: data = query.run(as_dict=True) return data[0] if data else {} + @deprecated + def get_last_sle_for_sabb_no_batchwise_valuation(self): + sabb = frappe.qb.DocType("Serial and Batch Bundle") + sabb_entry = frappe.qb.DocType("Serial and Batch Entry") + batch = frappe.qb.DocType("Batch") + + posting_datetime = CombineDatetime(self.sle.posting_date, self.sle.posting_time) + timestamp_condition = CombineDatetime(sabb.posting_date, sabb.posting_time) < posting_datetime + + if self.sle.creation: + timestamp_condition |= ( + CombineDatetime(sabb.posting_date, sabb.posting_time) == posting_datetime + ) & (sabb.creation < self.sle.creation) + + query = ( + frappe.qb.from_(sabb) + .inner_join(sabb_entry) + .on(sabb.name == sabb_entry.parent) + .inner_join(batch) + .on(sabb_entry.batch_no == batch.name) + .select(sabb.name) + .where( + (sabb.item_code == self.sle.item_code) + & (sabb.warehouse == self.sle.warehouse) + & (sabb_entry.batch_no.isnotnull()) + & (batch.use_batchwise_valuation == 0) + & (sabb.is_cancelled == 0) + & (sabb.docstatus == 1) + ) + .where(timestamp_condition) + .orderby(sabb.posting_date, order=Order.desc) + .orderby(sabb.posting_time, order=Order.desc) + .orderby(sabb.creation, order=Order.desc) + .limit(1) + ) + + if self.sle.voucher_detail_no: + query = query.where(sabb.voucher_detail_no != self.sle.voucher_detail_no) + + data = query.run(as_dict=True) + if not data: + return {} + + sle = frappe.db.get_value( + "Stock Ledger Entry", + {"serial_and_batch_bundle": data[0].name}, + ["stock_value", "qty_after_transaction"], + as_dict=1, + ) + + return sle if sle else {} + @deprecated def set_balance_value_from_bundle(self) -> None: bundle = frappe.qb.DocType("Serial and Batch Bundle") @@ -338,7 +391,14 @@ class DeprecatedBatchNoValuation: query = query.where(bundle.voucher_type != "Pick List") - 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_sabb_no_batchwise_valuation() + if not last_sle: + return + + for batch_no in self.available_qty: + self.non_batchwise_balance_value[batch_no] = flt(last_sle.stock_value) + self.non_batchwise_balance_qty[batch_no] = flt(last_sle.qty_after_transaction)