Merge pull request #57887 from mihir-kandoi/fix-repost-ma-return-sibling-rate

fix: repost read stale sibling SLE rate for moving average returns
This commit is contained in:
Mihir Kandoi
2026-08-08 12:02:24 +05:30
committed by GitHub
2 changed files with 82 additions and 18 deletions

View File

@@ -653,6 +653,55 @@ class TestRepostItemValuation(ERPNextTestSuite, StockTestMixin):
# incoming rate after reposting should be 150
self.assertSLEs(se, [{"incoming_rate": 150}])
def test_repost_multi_line_moving_average_return(self):
from erpnext.controllers.sales_and_purchase_return import make_return_doc
item = self.make_item(properties={"valuation_method": "Moving Average"}).name
warehouse = "_Test Warehouse - _TC"
make_purchase_receipt(item_code=item, qty=100, rate=100, warehouse=warehouse)
pr = make_purchase_receipt(item_code=item, qty=400, rate=200, warehouse=warehouse, do_not_submit=1)
for qty in (100, 300, 100):
pr.append(
"items",
{
"item_code": item,
"warehouse": warehouse,
"qty": qty,
"received_qty": qty,
"rate": 200,
"uom": pr.items[0].uom,
"conversion_factor": 1.0,
},
)
pr.save()
pr.submit()
return_pr = make_return_doc(pr.doctype, pr.name)
return_pr.save()
return_pr.submit()
expected_sles = [
{"outgoing_rate": 190.0, "valuation_rate": 190.0, "qty_after_transaction": 600.0},
{"outgoing_rate": 190.0, "valuation_rate": 190.0, "qty_after_transaction": 500.0},
{"outgoing_rate": 190.0, "valuation_rate": 190.0, "qty_after_transaction": 200.0},
{"outgoing_rate": 190.0, "valuation_rate": 190.0, "qty_after_transaction": 100.0},
]
for _ in range(2):
riv = frappe.get_doc(
doctype="Repost Item Valuation",
based_on="Transaction",
voucher_type=pr.doctype,
voucher_no=pr.name,
posting_date=pr.posting_date,
posting_time=pr.posting_time,
)
riv.submit()
self.assertSLEs(return_pr, expected_sles)
def test_remove_attached_file(self):
item_code = make_item("_Test Remove Attached File Item", properties={"is_stock_item": 1})

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,
@@ -1460,23 +1459,7 @@ class update_entries_after:
and not sle.get("batch_no")
and not sle.get("serial_and_batch_bundle")
):
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(
@@ -1544,6 +1527,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