mirror of
https://github.com/frappe/erpnext.git
synced 2026-02-17 00:25:01 +00:00
fix: non batch-wise valuation for batch item
(cherry picked from commit 11b82ba008)
This commit is contained in:
committed by
Mergify
parent
eb631d6e75
commit
affe09ee0b
@@ -1,4 +1,5 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
import json
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
@@ -197,6 +198,9 @@ class DeprecatedBatchNoValuation:
|
|||||||
@deprecated
|
@deprecated
|
||||||
def set_balance_value_for_non_batchwise_valuation_batches(self):
|
def set_balance_value_for_non_batchwise_valuation_batches(self):
|
||||||
self.last_sle = self.get_last_sle_for_non_batch()
|
self.last_sle = self.get_last_sle_for_non_batch()
|
||||||
|
if self.last_sle and self.last_sle.stock_value:
|
||||||
|
self.stock_queue = json.loads(self.last_sle.stock_queue or "[]") or []
|
||||||
|
|
||||||
self.set_balance_value_from_sl_entries()
|
self.set_balance_value_from_sl_entries()
|
||||||
self.set_balance_value_from_bundle()
|
self.set_balance_value_from_bundle()
|
||||||
|
|
||||||
@@ -271,6 +275,7 @@ class DeprecatedBatchNoValuation:
|
|||||||
.select(
|
.select(
|
||||||
sle.stock_value,
|
sle.stock_value,
|
||||||
sle.qty_after_transaction,
|
sle.qty_after_transaction,
|
||||||
|
sle.stock_queue,
|
||||||
)
|
)
|
||||||
.where(
|
.where(
|
||||||
(sle.item_code == self.sle.item_code)
|
(sle.item_code == self.sle.item_code)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
import collections
|
import collections
|
||||||
import csv
|
import csv
|
||||||
|
import json
|
||||||
from collections import Counter, defaultdict
|
from collections import Counter, defaultdict
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
@@ -29,6 +30,7 @@ from erpnext.stock.serial_batch_bundle import (
|
|||||||
get_batches_from_bundle,
|
get_batches_from_bundle,
|
||||||
)
|
)
|
||||||
from erpnext.stock.serial_batch_bundle import get_serial_nos as get_serial_nos_from_bundle
|
from erpnext.stock.serial_batch_bundle import get_serial_nos as get_serial_nos_from_bundle
|
||||||
|
from erpnext.stock.valuation import FIFOValuation
|
||||||
|
|
||||||
|
|
||||||
class SerialNoExistsInFutureTransactionError(frappe.ValidationError):
|
class SerialNoExistsInFutureTransactionError(frappe.ValidationError):
|
||||||
@@ -463,6 +465,8 @@ class SerialandBatchBundle(Document):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def set_incoming_rate_for_outward_transaction(self, row=None, save=False, allow_negative_stock=False):
|
def set_incoming_rate_for_outward_transaction(self, row=None, save=False, allow_negative_stock=False):
|
||||||
|
from erpnext.stock.utils import get_valuation_method
|
||||||
|
|
||||||
sle = self.get_sle_for_outward_transaction()
|
sle = self.get_sle_for_outward_transaction()
|
||||||
|
|
||||||
if self.has_serial_no:
|
if self.has_serial_no:
|
||||||
@@ -479,13 +483,40 @@ class SerialandBatchBundle(Document):
|
|||||||
warehouse=self.warehouse,
|
warehouse=self.warehouse,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
stock_queue = []
|
||||||
|
if hasattr(sn_obj, "stock_queue") and sn_obj.stock_queue:
|
||||||
|
stock_queue = parse_json(sn_obj.stock_queue)
|
||||||
|
|
||||||
|
val_method = get_valuation_method(self.item_code)
|
||||||
|
|
||||||
for d in self.entries:
|
for d in self.entries:
|
||||||
available_qty = 0
|
available_qty = 0
|
||||||
|
|
||||||
if self.has_serial_no:
|
if self.has_serial_no:
|
||||||
d.incoming_rate = abs(sn_obj.serial_no_incoming_rate.get(d.serial_no, 0.0))
|
d.incoming_rate = abs(sn_obj.serial_no_incoming_rate.get(d.serial_no, 0.0))
|
||||||
else:
|
else:
|
||||||
d.incoming_rate = abs(flt(sn_obj.batch_avg_rate.get(d.batch_no)))
|
actual_qty = d.qty
|
||||||
|
if (
|
||||||
|
stock_queue
|
||||||
|
and val_method == "FIFO"
|
||||||
|
and d.batch_no in sn_obj.non_batchwise_valuation_batches
|
||||||
|
):
|
||||||
|
if actual_qty < 0:
|
||||||
|
stock_queue = FIFOValuation(stock_queue)
|
||||||
|
_prev_qty, prev_stock_value = stock_queue.get_total_stock_and_value()
|
||||||
|
|
||||||
|
stock_queue.remove_stock(qty=abs(actual_qty))
|
||||||
|
_qty, stock_value = stock_queue.get_total_stock_and_value()
|
||||||
|
|
||||||
|
stock_value_difference = stock_value - prev_stock_value
|
||||||
|
d.incoming_rate = abs(flt(stock_value_difference) / abs(flt(actual_qty)))
|
||||||
|
stock_queue = stock_queue.state
|
||||||
|
else:
|
||||||
|
d.incoming_rate = abs(flt(sn_obj.batch_avg_rate.get(d.batch_no)))
|
||||||
|
stock_queue.append([d.qty, d.incoming_rate])
|
||||||
|
d.stock_queue = json.dumps(stock_queue)
|
||||||
|
else:
|
||||||
|
d.incoming_rate = abs(flt(sn_obj.batch_avg_rate.get(d.batch_no)))
|
||||||
|
|
||||||
available_qty = flt(sn_obj.available_qty.get(d.batch_no), d.precision("qty"))
|
available_qty = flt(sn_obj.available_qty.get(d.batch_no), d.precision("qty"))
|
||||||
if self.docstatus == 1:
|
if self.docstatus == 1:
|
||||||
|
|||||||
@@ -674,6 +674,7 @@ class BatchNoValuation(DeprecatedBatchNoValuation):
|
|||||||
for key, value in kwargs.items():
|
for key, value in kwargs.items():
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
|
|
||||||
|
self.stock_queue = []
|
||||||
self.batch_nos = self.get_batch_nos()
|
self.batch_nos = self.get_batch_nos()
|
||||||
self.prepare_batches()
|
self.prepare_batches()
|
||||||
self.calculate_avg_rate()
|
self.calculate_avg_rate()
|
||||||
@@ -770,15 +771,12 @@ class BatchNoValuation(DeprecatedBatchNoValuation):
|
|||||||
self.non_batchwise_valuation_batches = self.batches
|
self.non_batchwise_valuation_batches = self.batches
|
||||||
return
|
return
|
||||||
|
|
||||||
if get_valuation_method(self.sle.item_code) == "FIFO":
|
batches = frappe.get_all(
|
||||||
self.batchwise_valuation_batches = self.batches
|
"Batch", filters={"name": ("in", self.batches), "use_batchwise_valuation": 1}, fields=["name"]
|
||||||
else:
|
)
|
||||||
batches = frappe.get_all(
|
|
||||||
"Batch", filters={"name": ("in", self.batches), "use_batchwise_valuation": 1}, fields=["name"]
|
|
||||||
)
|
|
||||||
|
|
||||||
for batch in batches:
|
for batch in batches:
|
||||||
self.batchwise_valuation_batches.append(batch.name)
|
self.batchwise_valuation_batches.append(batch.name)
|
||||||
|
|
||||||
self.non_batchwise_valuation_batches = list(set(self.batches) - set(self.batchwise_valuation_batches))
|
self.non_batchwise_valuation_batches = list(set(self.batches) - set(self.batchwise_valuation_batches))
|
||||||
|
|
||||||
|
|||||||
@@ -1042,6 +1042,15 @@ class update_entries_after:
|
|||||||
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)
|
||||||
doc.calculate_qty_and_amount(save=True)
|
doc.calculate_qty_and_amount(save=True)
|
||||||
|
|
||||||
|
if stock_queue := frappe.get_all(
|
||||||
|
"Serial and Batch Entry",
|
||||||
|
filters={"parent": sle.serial_and_batch_bundle, "stock_queue": ("is", "set")},
|
||||||
|
pluck="stock_queue",
|
||||||
|
order_by="idx desc",
|
||||||
|
limit=1,
|
||||||
|
):
|
||||||
|
self.wh_data.stock_queue = json.loads(stock_queue[0]) if stock_queue else []
|
||||||
|
|
||||||
self.wh_data.stock_value = round_off_if_near_zero(self.wh_data.stock_value + doc.total_amount)
|
self.wh_data.stock_value = round_off_if_near_zero(self.wh_data.stock_value + doc.total_amount)
|
||||||
self.wh_data.qty_after_transaction += flt(doc.total_qty, self.flt_precision)
|
self.wh_data.qty_after_transaction += flt(doc.total_qty, self.flt_precision)
|
||||||
if flt(self.wh_data.qty_after_transaction, self.flt_precision):
|
if flt(self.wh_data.qty_after_transaction, self.flt_precision):
|
||||||
|
|||||||
@@ -373,6 +373,7 @@ def get_avg_purchase_rate(serial_nos):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.request_cache
|
||||||
def get_valuation_method(item_code):
|
def get_valuation_method(item_code):
|
||||||
"""get valuation method from item or default"""
|
"""get valuation method from item or default"""
|
||||||
val_method = frappe.db.get_value("Item", item_code, "valuation_method", cache=True)
|
val_method = frappe.db.get_value("Item", item_code, "valuation_method", cache=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user