From f38690f7037c75bb1c5a5d946d686b40392a111a Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Sun, 20 Feb 2022 12:58:53 +0530 Subject: [PATCH] fix: check if Moving average item can use batchwise valuation --- erpnext/stock/doctype/batch/batch.py | 32 ++++++++++++++++++++++++++++ erpnext/stock/utils.py | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index 96751d6eae..b5e56ad301 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -6,6 +6,7 @@ import frappe from frappe import _ from frappe.model.document import Document from frappe.model.naming import make_autoname, revert_series_if_last +from frappe.query_builder.functions import Sum from frappe.utils import cint, flt, get_link_to_form from frappe.utils.data import add_days from frappe.utils.jinja import render_template @@ -110,11 +111,15 @@ class Batch(Document): def validate(self): self.item_has_batch_enabled() + self.set_batchwise_valuation() def item_has_batch_enabled(self): if frappe.db.get_value("Item", self.item, "has_batch_no") == 0: frappe.throw(_("The selected item cannot have Batch")) + def set_batchwise_valuation(self): + self.use_batchwise_valuation = int(can_use_batchwise_valuation(self.item)) + def before_save(self): has_expiry_date, shelf_life_in_days = frappe.db.get_value('Item', self.item, ['has_expiry_date', 'shelf_life_in_days']) if not self.expiry_date and has_expiry_date and shelf_life_in_days: @@ -338,3 +343,30 @@ def get_pos_reserved_batch_qty(filters): flt_reserved_batch_qty = flt(reserved_batch_qty[0][0]) return flt_reserved_batch_qty + +def can_use_batchwise_valuation(item_code: str) -> bool: + """ Check if item can use batchwise valuation. + + Note: Item with existing moving average batches can't use batchwise valuation + until they are exhausted. + """ + from erpnext.stock.stock_ledger import get_valuation_method + batch = frappe.qb.DocType("Batch") + + if get_valuation_method(item_code) != "Moving Average": + return True + + batch_qty = ( + frappe.qb + .from_(batch) + .select(Sum(batch.batch_qty)) + .where( + (batch.use_batchwise_valuation == 0) + & (batch.item == item_code) + ) + ).run() + + if batch_qty and batch_qty[0][0]: + return False + + return True diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index e2bd2f197d..f85a04f944 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -261,7 +261,7 @@ def get_valuation_method(item_code): """get valuation method from item or default""" val_method = frappe.db.get_value('Item', item_code, 'valuation_method', cache=True) if not val_method: - val_method = frappe.db.get_value("Stock Settings", None, "valuation_method") or "FIFO" + val_method = frappe.db.get_value("Stock Settings", None, "valuation_method", cache=True) or "FIFO" return val_method def get_fifo_rate(previous_stock_queue, qty):