fix: incorrect valuation for sales return with different warhouse

(cherry picked from commit 3a2e816759)

# Conflicts:
#	erpnext/stock/doctype/delivery_note/test_delivery_note.py
This commit is contained in:
Rohit Waghchaure
2025-01-14 12:36:22 +05:30
committed by Mergify
parent 1be8051f7a
commit 9ee5651848
2 changed files with 109 additions and 9 deletions

View File

@@ -2406,6 +2406,83 @@ class TestDeliveryNote(FrappeTestCase):
if row.item_code == serial_item.name:
self.assertTrue(row.serial_no)
<<<<<<< HEAD
=======
if row.item_code == batch_serial_item.name:
self.assertTrue(row.batch_no)
self.assertTrue(row.serial_no)
def test_delivery_note_return_for_batch_item_with_different_warehouse(self):
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_return
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
batch_item = make_item(
"_Test Delivery Note Return Valuation WITH Batch Item",
properties={
"has_batch_no": 1,
"create_new_batch": 1,
"is_stock_item": 1,
"batch_number_series": "BRTN-DNN-BIW-.#####",
},
).name
batches = []
for qty, rate in {5: 300}.items():
se = make_stock_entry(
item_code=batch_item, target="_Test Warehouse - _TC", qty=qty, basic_rate=rate
)
batches.append(get_batch_from_bundle(se.items[0].serial_and_batch_bundle))
warehouse = create_warehouse("Sales Return Test Warehouse 1", company="_Test Company")
dn = create_delivery_note(
item_code=batch_item,
qty=5,
rate=1000,
use_serial_batch_fields=1,
batch_no=batches[0],
do_not_submit=True,
)
self.assertEqual(dn.items[0].warehouse, "_Test Warehouse - _TC")
dn.save()
dn.submit()
dn.reload()
batch_no_valuation = defaultdict(float)
for row in dn.items:
if row.serial_and_batch_bundle:
bundle_data = frappe.get_all(
"Serial and Batch Entry",
filters={"parent": row.serial_and_batch_bundle},
fields=["incoming_rate", "serial_no", "batch_no"],
)
for d in bundle_data:
if d.batch_no:
batch_no_valuation[d.batch_no] = d.incoming_rate
return_entry = make_sales_return(dn.name)
return_entry.items[0].warehouse = warehouse
return_entry.save()
return_entry.submit()
return_entry.reload()
for row in return_entry.items:
self.assertEqual(row.warehouse, warehouse)
bundle_data = frappe.get_all(
"Serial and Batch Entry",
filters={"parent": row.serial_and_batch_bundle},
fields=["incoming_rate", "batch_no"],
)
for d in bundle_data:
self.assertEqual(d.incoming_rate, batch_no_valuation[d.batch_no])
>>>>>>> 3a2e816759 (fix: incorrect valuation for sales return with different warhouse)
def create_delivery_note(**args):
dn = frappe.new_doc("Delivery Note")

View File

@@ -251,7 +251,7 @@ class SerialandBatchBundle(Document):
return
if return_against := self.get_return_against(parent=parent):
self.set_valuation_rate_for_return_entry(return_against, save)
self.set_valuation_rate_for_return_entry(return_against, row, save)
elif self.type_of_transaction == "Outward":
self.set_incoming_rate_for_outward_transaction(
row, save, allow_negative_stock=allow_negative_stock
@@ -259,7 +259,7 @@ class SerialandBatchBundle(Document):
else:
self.set_incoming_rate_for_inward_transaction(row, save)
def set_valuation_rate_for_return_entry(self, return_against, save=False):
def set_valuation_rate_for_return_entry(self, return_against, row, save=False):
if valuation_details := self.get_valuation_rate_for_return_entry(return_against):
for row in self.entries:
if valuation_details:
@@ -281,6 +281,9 @@ class SerialandBatchBundle(Document):
}
)
elif self.type_of_transaction == "Inward":
self.set_incoming_rate_for_inward_transaction(row, save)
def validate_returned_serial_batch_no(self, return_against, row, original_inv_details):
if row.serial_no and row.serial_no not in original_inv_details["serial_nos"]:
self.throw_error_message(
@@ -297,6 +300,9 @@ class SerialandBatchBundle(Document):
)
def get_valuation_rate_for_return_entry(self, return_against):
if not self.voucher_detail_no:
return {}
valuation_details = frappe._dict(
{
"serial_nos": defaultdict(float),
@@ -304,6 +310,29 @@ class SerialandBatchBundle(Document):
}
)
field = {
"Sales Invoice": "sales_invoice_item",
"Purchase Invoice": "purchase_invoice_item",
"Delivery Note": "dn_detail",
"Purchase Receipt": "purchase_receipt_item",
}.get(self.voucher_type)
return_against_voucher_detail_no = frappe.db.get_value(
self.child_table, self.voucher_detail_no, field
)
filters = [
["Serial and Batch Bundle", "voucher_no", "=", return_against],
["Serial and Batch Entry", "docstatus", "=", 1],
["Serial and Batch Bundle", "is_cancelled", "=", 0],
["Serial and Batch Bundle", "item_code", "=", self.item_code],
["Serial and Batch Bundle", "voucher_detail_no", "=", return_against_voucher_detail_no],
]
if self.voucher_type in ["Purchase Receipt", "Purchase Invoice"]:
# Added to handle rejected warehouse case
filters.append(["Serial and Batch Entry", "warehouse", "=", self.warehouse])
bundle_data = frappe.get_all(
"Serial and Batch Bundle",
fields=[
@@ -311,13 +340,7 @@ class SerialandBatchBundle(Document):
"`tabSerial and Batch Entry`.`batch_no`",
"`tabSerial and Batch Entry`.`incoming_rate`",
],
filters=[
["Serial and Batch Bundle", "voucher_no", "=", return_against],
["Serial and Batch Entry", "docstatus", "=", 1],
["Serial and Batch Bundle", "is_cancelled", "=", 0],
["Serial and Batch Bundle", "item_code", "=", self.item_code],
["Serial and Batch Bundle", "warehouse", "=", self.warehouse],
],
filters=filters,
order_by="`tabSerial and Batch Bundle`.`creation`, `tabSerial and Batch Entry`.`idx`",
)