mirror of
https://github.com/frappe/erpnext.git
synced 2026-02-16 16:15:02 +00:00
fix: valuation rate for old batch
This commit is contained in:
@@ -312,7 +312,7 @@ class SerialandBatchBundle(Document):
|
||||
def throw_error_message(self, message, exception=frappe.ValidationError):
|
||||
frappe.throw(_(message), exception, title=_("Error"))
|
||||
|
||||
def set_incoming_rate(self, parent=None, row=None, save=False, allow_negative_stock=False):
|
||||
def set_incoming_rate(self, parent=None, row=None, save=False, allow_negative_stock=False, prev_sle=None):
|
||||
if self.type_of_transaction not in ["Inward", "Outward"] or self.voucher_type in [
|
||||
"Installation Note",
|
||||
"Job Card",
|
||||
@@ -322,15 +322,15 @@ class SerialandBatchBundle(Document):
|
||||
return
|
||||
|
||||
if return_against := self.get_return_against(parent=parent):
|
||||
self.set_valuation_rate_for_return_entry(return_against, row, save)
|
||||
self.set_valuation_rate_for_return_entry(return_against, row, save, prev_sle=prev_sle)
|
||||
elif self.type_of_transaction == "Outward":
|
||||
self.set_incoming_rate_for_outward_transaction(
|
||||
row, save, allow_negative_stock=allow_negative_stock
|
||||
)
|
||||
else:
|
||||
self.set_incoming_rate_for_inward_transaction(row, save)
|
||||
self.set_incoming_rate_for_inward_transaction(row, save, prev_sle=prev_sle)
|
||||
|
||||
def set_valuation_rate_for_return_entry(self, return_against, row, save=False):
|
||||
def set_valuation_rate_for_return_entry(self, return_against, row, save=False, prev_sle=None):
|
||||
if valuation_details := self.get_valuation_rate_for_return_entry(return_against):
|
||||
for row in self.entries:
|
||||
if valuation_details:
|
||||
@@ -362,7 +362,7 @@ class SerialandBatchBundle(Document):
|
||||
)
|
||||
|
||||
elif self.type_of_transaction == "Inward":
|
||||
self.set_incoming_rate_for_inward_transaction(row, save)
|
||||
self.set_incoming_rate_for_inward_transaction(row, save, prev_sle=prev_sle)
|
||||
|
||||
def validate_returned_serial_batch_no(self, return_against, row, original_inv_details):
|
||||
if frappe.flags.through_repost_item_valuation:
|
||||
@@ -530,7 +530,11 @@ class SerialandBatchBundle(Document):
|
||||
|
||||
if save:
|
||||
d.db_set(
|
||||
{"incoming_rate": d.incoming_rate, "stock_value_difference": d.stock_value_difference}
|
||||
{
|
||||
"incoming_rate": d.incoming_rate,
|
||||
"stock_value_difference": d.stock_value_difference,
|
||||
"stock_queue": d.get("stock_queue"),
|
||||
}
|
||||
)
|
||||
|
||||
def validate_negative_batch(self, batch_no, available_qty):
|
||||
@@ -606,7 +610,11 @@ class SerialandBatchBundle(Document):
|
||||
|
||||
return return_against
|
||||
|
||||
def set_incoming_rate_for_inward_transaction(self, row=None, save=False):
|
||||
def set_incoming_rate_for_inward_transaction(self, row=None, save=False, prev_sle=None):
|
||||
from erpnext.stock.utils import get_valuation_method
|
||||
|
||||
valuation_method = get_valuation_method(self.item_code)
|
||||
|
||||
valuation_field = "valuation_rate"
|
||||
if self.voucher_type in ["Sales Invoice", "Delivery Note", "Quotation"]:
|
||||
valuation_field = "incoming_rate"
|
||||
@@ -630,19 +638,42 @@ class SerialandBatchBundle(Document):
|
||||
if not rate and self.voucher_detail_no and self.voucher_no:
|
||||
rate = frappe.db.get_value(child_table, self.voucher_detail_no, valuation_field)
|
||||
|
||||
stock_queue = []
|
||||
batches = []
|
||||
if prev_sle and prev_sle.stock_queue:
|
||||
batches = frappe.get_all(
|
||||
"Batch",
|
||||
filters={
|
||||
"name": ("in", [d.batch_no for d in self.entries if d.batch_no]),
|
||||
"use_batchwise_valuation": 0,
|
||||
},
|
||||
pluck="name",
|
||||
)
|
||||
|
||||
if batches and valuation_method == "FIFO":
|
||||
stock_queue = parse_json(prev_sle.stock_queue)
|
||||
|
||||
for d in self.entries:
|
||||
if self.is_rejected:
|
||||
rate = 0.0
|
||||
elif (d.incoming_rate == rate) and d.qty and d.stock_value_difference:
|
||||
elif (d.incoming_rate == rate) and not stock_queue and d.qty and d.stock_value_difference:
|
||||
continue
|
||||
|
||||
d.incoming_rate = flt(rate)
|
||||
if d.qty:
|
||||
d.stock_value_difference = flt(d.qty) * d.incoming_rate
|
||||
|
||||
if stock_queue and valuation_method == "FIFO" and d.batch_no in batches:
|
||||
stock_queue.append([d.qty, d.incoming_rate])
|
||||
d.stock_queue = json.dumps(stock_queue)
|
||||
|
||||
if save:
|
||||
d.db_set(
|
||||
{"incoming_rate": d.incoming_rate, "stock_value_difference": d.stock_value_difference}
|
||||
{
|
||||
"incoming_rate": d.incoming_rate,
|
||||
"stock_value_difference": d.stock_value_difference,
|
||||
"stock_queue": d.get("stock_queue"),
|
||||
}
|
||||
)
|
||||
|
||||
def set_serial_and_batch_values(self, parent, row, qty_field=None):
|
||||
|
||||
@@ -286,6 +286,25 @@ class TestSerialandBatchBundle(IntegrationTestCase):
|
||||
self.assertEqual(flt(sle.stock_value_difference), 1000.00 * -1)
|
||||
self.assertEqual(json.loads(sle.stock_queue), [[20, 200]])
|
||||
|
||||
se = make_stock_entry(
|
||||
item_code=batch_item_code,
|
||||
target="_Test Warehouse - _TC",
|
||||
qty=10,
|
||||
rate=100,
|
||||
batch_no=batch_id,
|
||||
use_serial_batch_fields=True,
|
||||
)
|
||||
|
||||
sle = frappe.db.get_value(
|
||||
"Serial and Batch Entry",
|
||||
{"parent": se.items[0].serial_and_batch_bundle, "docstatus": 1},
|
||||
["stock_value_difference", "stock_queue"],
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
self.assertEqual(flt(sle.stock_value_difference), 1000.00)
|
||||
self.assertEqual(json.loads(sle.stock_queue), [[20, 200], [10, 100]])
|
||||
|
||||
se = make_stock_entry(
|
||||
item_code=batch_item_code,
|
||||
target="_Test Warehouse - _TC",
|
||||
@@ -302,7 +321,7 @@ class TestSerialandBatchBundle(IntegrationTestCase):
|
||||
)
|
||||
|
||||
self.assertEqual(flt(sle.stock_value_difference), 1000.00)
|
||||
self.assertEqual(json.loads(sle.stock_queue), [[20, 200]])
|
||||
self.assertEqual(json.loads(sle.stock_queue), [[20, 200], [10, 100]])
|
||||
|
||||
se = make_stock_entry(
|
||||
item_code=batch_item_code,
|
||||
@@ -320,6 +339,24 @@ class TestSerialandBatchBundle(IntegrationTestCase):
|
||||
|
||||
self.assertEqual(flt(sle.stock_value_difference), 5000.00 * -1)
|
||||
self.assertFalse(json.loads(sle.stock_queue or "[]"))
|
||||
self.assertEqual(flt(sle.stock_value), 1000.0)
|
||||
|
||||
se = make_stock_entry(
|
||||
item_code=batch_item_code,
|
||||
source="_Test Warehouse - _TC",
|
||||
qty=10,
|
||||
use_serial_batch_fields=False,
|
||||
)
|
||||
|
||||
sle = frappe.db.get_value(
|
||||
"Stock Ledger Entry",
|
||||
{"item_code": batch_item_code, "is_cancelled": 0, "voucher_no": se.name},
|
||||
["stock_value_difference", "stock_queue", "stock_value"],
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
self.assertEqual(flt(sle.stock_value_difference), 1000.00 * -1)
|
||||
self.assertFalse(json.loads(sle.stock_queue or "[]"))
|
||||
self.assertEqual(flt(sle.stock_value), 0.0)
|
||||
|
||||
def test_old_serial_no_valuation(self):
|
||||
|
||||
@@ -1024,7 +1024,9 @@ class update_entries_after:
|
||||
)
|
||||
else:
|
||||
doc = frappe.get_doc("Serial and Batch Bundle", sle.serial_and_batch_bundle)
|
||||
doc.set_incoming_rate(save=True, allow_negative_stock=self.allow_negative_stock)
|
||||
doc.set_incoming_rate(
|
||||
save=True, allow_negative_stock=self.allow_negative_stock, prev_sle=self.wh_data
|
||||
)
|
||||
doc.calculate_qty_and_amount(save=True)
|
||||
|
||||
if stock_queue := frappe.get_all(
|
||||
|
||||
Reference in New Issue
Block a user