Skip to content

Commit

Permalink
fix: negative valuation rate in PR return (backport #37424) (backport #…
Browse files Browse the repository at this point in the history
…37462) (#37463)

fix: negative valuation rate in PR return (backport #37424) (#37462)

* fix: negative valuation rate in PR return (#37424)

* fix: negative valuation rate in PR return

* test: add test case for PR return

(cherry picked from commit 26ad688)

# Conflicts:
#	erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py

* chore: `conflicts`

---------

Co-authored-by: s-aga-r <[email protected]>
(cherry picked from commit 66ad823)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
mergify[bot] authored Oct 11, 2023
1 parent 0000c38 commit f6b3532
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 12 deletions.
20 changes: 16 additions & 4 deletions erpnext/controllers/buying_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
from erpnext.controllers.stock_controller import StockController
from erpnext.controllers.subcontracting import Subcontracting
from erpnext.stock.get_item_details import get_conversion_factor
from erpnext.stock.utils import get_incoming_rate
from erpnext.stock.stock_ledger import get_previous_sle
from erpnext.stock.utils import get_incoming_rate, get_valuation_method


class QtyMismatchError(ValidationError):
Expand Down Expand Up @@ -504,9 +505,20 @@ def update_stock_ledger(self, allow_negative_stock=False, via_landed_cost_vouche
)

if self.is_return:
outgoing_rate = get_rate_for_return(
self.doctype, self.name, d.item_code, self.return_against, item_row=d
)
if get_valuation_method(d.item_code) == "Moving Average":
previous_sle = get_previous_sle(
{
"item_code": d.item_code,
"warehouse": d.warehouse,
"posting_date": self.posting_date,
"posting_time": self.posting_time,
}
)
outgoing_rate = flt(previous_sle.get("valuation_rate"))
else:
outgoing_rate = get_rate_for_return(
self.doctype, self.name, d.item_code, self.return_against, item_row=d
)

sle.update({"outgoing_rate": outgoing_rate, "recalculate_rate": 1})
if d.from_warehouse:
Expand Down
54 changes: 54 additions & 0 deletions erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
Original file line number Diff line number Diff line change
Expand Up @@ -1996,6 +1996,60 @@ def test_purchase_receipt_with_backdated_landed_cost_voucher(self):
ste7.reload()
self.assertEqual(ste7.items[0].valuation_rate, valuation_rate)

def test_valuation_rate_in_return_purchase_receipt_for_moving_average(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
from erpnext.stock.stock_ledger import get_previous_sle

# Step - 1: Create an Item (Valuation Method = Moving Average)
item_code = make_item(properties={"is_stock_item": 1, "valuation_method": "Moving Average"}).name

# Step - 2: Create a Purchase Receipt (Qty = 10, Rate = 100)
pr = make_purchase_receipt(qty=10, rate=100, item_code=item_code)

# Step - 3: Create a Material Receipt Stock Entry (Qty = 100, Basic Rate = 10)
warehouse = "_Test Warehouse - _TC"
make_stock_entry(
purpose="Material Receipt",
item_code=item_code,
to_warehouse=warehouse,
qty=100,
rate=10,
)

# Step - 4: Create a Material Issue Stock Entry (Qty = 100, Basic Rate = 18.18 [Auto Fetched])
make_stock_entry(
purpose="Material Issue", item_code=item_code, from_warehouse=warehouse, qty=100
)

# Step - 5: Create a Return Purchase Return (Qty = -8, Rate = 100 [Auto fetched])
return_pr = make_purchase_receipt(
is_return=1,
return_against=pr.name,
item_code=item_code,
qty=-8,
)

sle = frappe.db.get_value(
"Stock Ledger Entry",
{"voucher_no": return_pr.name, "voucher_detail_no": return_pr.items[0].name},
["posting_date", "posting_time", "outgoing_rate", "valuation_rate"],
as_dict=1,
)
previous_sle_valuation_rate = get_previous_sle(
{
"item_code": item_code,
"warehouse": warehouse,
"posting_date": sle.posting_date,
"posting_time": sle.posting_time,
}
).get("valuation_rate")

# Test - 1: Valuation Rate should be equal to Outgoing Rate
self.assertEqual(flt(sle.outgoing_rate, 2), flt(sle.valuation_rate, 2))

# Test - 2: Valuation Rate should be equal to Previous SLE Valuation Rate
self.assertEqual(flt(sle.valuation_rate, 2), flt(previous_sle_valuation_rate, 2))


def prepare_data_for_internal_transfer():
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier
Expand Down
18 changes: 10 additions & 8 deletions erpnext/stock/stock_ledger.py
Original file line number Diff line number Diff line change
Expand Up @@ -658,14 +658,16 @@ def get_incoming_outgoing_rate_from_transaction(self, sle):
get_rate_for_return, # don't move this import to top
)

rate = get_rate_for_return(
sle.voucher_type,
sle.voucher_no,
sle.item_code,
voucher_detail_no=sle.voucher_detail_no,
sle=sle,
)

if self.valuation_method == "Moving Average":
rate = self.data[self.args.warehouse].previous_sle.valuation_rate
else:
rate = get_rate_for_return(
sle.voucher_type,
sle.voucher_no,
sle.item_code,
voucher_detail_no=sle.voucher_detail_no,
sle=sle,
)
elif (
sle.voucher_type in ["Purchase Receipt", "Purchase Invoice"]
and sle.voucher_detail_no
Expand Down

0 comments on commit f6b3532

Please sign in to comment.