fix: zero-rate repost fallback could still read sibling SLE

When the in-memory running rate is zero, the fallback went through
get_incoming_rate, whose previous-SLE lookup matches the same
posting_datetime and can land on a sibling line of the voucher being
replayed. Replace it with get_previous_sle_of_current_voucher excluding
the current voucher, keeping the get_valuation_rate chain when no
previous entry exists. get_incoming_rate is no longer used in this
module.
This commit is contained in:
Mihir Kandoi
2026-08-08 11:00:47 +05:30
parent 9c8d5ac8a5
commit 8131af9405

View File

@@ -38,7 +38,6 @@ from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry impor
from erpnext.stock.utils import (
get_combine_datetime,
get_incoming_outgoing_rate_for_cancel,
get_incoming_rate,
get_or_make_bin,
get_serial_nos_data,
get_stock_balance,
@@ -1260,25 +1259,7 @@ class update_entries_after:
and not sle.get("batch_no")
and not sle.get("serial_and_batch_bundle")
):
rate = flt(self.wh_data.valuation_rate)
if not rate:
rate = get_incoming_rate(
{
"item_code": sle.item_code,
"warehouse": sle.warehouse,
"posting_date": sle.posting_date,
"posting_time": sle.posting_time,
"qty": sle.actual_qty,
"serial_no": sle.get("serial_no"),
"batch_no": sle.get("batch_no"),
"serial_and_batch_bundle": sle.get("serial_and_batch_bundle"),
"company": sle.company,
"voucher_type": sle.voucher_type,
"voucher_no": sle.voucher_no,
"allow_zero_valuation": self.allow_zero_rate,
"sle": sle.name,
}
)
rate = self.get_moving_average_rate_for_return(sle)
if not rate and sle.voucher_type in ["Delivery Note", "Sales Invoice"]:
rate = get_rate_for_return(
@@ -1346,6 +1327,38 @@ class update_entries_after:
return rate
def get_moving_average_rate_for_return(self, sle):
"""Rate just before this entry, taken from the in-memory running state so a
multi-line return never reads a sibling row of its own voucher."""
rate = flt(self.wh_data.valuation_rate)
if rate:
return rate
previous_sle = get_previous_sle_of_current_voucher(
frappe._dict(
item_code=sle.item_code,
warehouse=sle.warehouse,
posting_date=sle.posting_date,
posting_time=sle.posting_time,
voucher_no=sle.voucher_no,
),
exclude_current_voucher=True,
)
rate = previous_sle.get("valuation_rate")
if rate is None:
rate = get_valuation_rate(
sle.item_code,
sle.warehouse,
sle.voucher_type,
sle.voucher_no,
self.allow_zero_rate,
currency=erpnext.get_company_currency(sle.company),
company=sle.company,
)
return flt(rate)
def update_outgoing_rate_on_transaction(self, sle):
"""
Update outgoing rate in Stock Entry, Delivery Note, Sales Invoice and Sales Return