perf: use cached stock settings (#47945)

This commit is contained in:
Ankush Menat
2025-06-06 18:54:49 +05:30
committed by GitHub
parent 522b6ad49f
commit ea5c2c454b
20 changed files with 56 additions and 72 deletions

View File

@@ -75,7 +75,7 @@ class BuyingController(SubcontractingController):
if self.docstatus == 1 and self.doctype in ["Purchase Receipt", "Purchase Invoice"]:
self.set_onload(
"allow_to_make_qc_after_submission",
frappe.db.get_single_value(
frappe.get_settings(
"Stock Settings", "allow_to_make_quality_inspection_after_purchase_or_delivery"
),
)
@@ -545,7 +545,7 @@ class BuyingController(SubcontractingController):
item.bom = None
def set_qty_as_per_stock_uom(self):
allow_to_edit_stock_qty = frappe.db.get_single_value(
allow_to_edit_stock_qty = frappe.get_settings(
"Stock Settings", "allow_to_edit_stock_uom_qty_for_purchase"
)

View File

@@ -948,7 +948,7 @@ def get_filtered_child_rows(doctype, txt, searchfield, start, page_len, filters)
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_item_uom_query(doctype, txt, searchfield, start, page_len, filters):
if frappe.db.get_single_value("Stock Settings", "allow_uom_with_conversion_rate_defined_in_item"):
if frappe.get_settings("Stock Settings", "allow_uom_with_conversion_rate_defined_in_item"):
query_filters = {"parent": filters.get("item_code")}
if txt:

View File

@@ -38,7 +38,7 @@ class SellingController(StockController):
if self.docstatus == 1 and self.doctype in ["Delivery Note", "Sales Invoice"]:
self.set_onload(
"allow_to_make_qc_after_submission",
frappe.db.get_single_value(
frappe.get_settings(
"Stock Settings", "allow_to_make_quality_inspection_after_purchase_or_delivery"
),
)
@@ -224,7 +224,7 @@ class SellingController(StockController):
frappe.throw(_("Maximum discount for Item {0} is {1}%").format(d.item_code, discount))
def set_qty_as_per_stock_uom(self):
allow_to_edit_stock_qty = frappe.db.get_single_value(
allow_to_edit_stock_qty = frappe.get_settings(
"Stock Settings", "allow_to_edit_stock_uom_qty_for_sales"
)
@@ -960,7 +960,7 @@ def get_serial_and_batch_bundle(child, parent, delivery_note_child=None):
if child.get("use_serial_batch_fields"):
return
if not frappe.db.get_single_value("Stock Settings", "auto_create_serial_and_batch_bundle_for_outward"):
if not frappe.get_settings("Stock Settings", "auto_create_serial_and_batch_bundle_for_outward"):
return
item_details = frappe.db.get_value("Item", child.item_code, ["has_serial_no", "has_batch_no"], as_dict=1)

View File

@@ -336,7 +336,7 @@ class StatusUpdater(Document):
qty_or_amount,
)
role_allowed_to_over_deliver_receive = frappe.db.get_single_value(
role_allowed_to_over_deliver_receive = frappe.get_settings(
"Stock Settings", "role_allowed_to_over_deliver_receive"
)
role_allowed_to_over_bill = frappe.db.get_single_value(

View File

@@ -518,7 +518,7 @@ class StockController(AccountsController):
)
def set_use_serial_batch_fields(self):
if frappe.db.get_single_value("Stock Settings", "use_serial_batch_fields"):
if frappe.get_settings("Stock Settings", "use_serial_batch_fields"):
for row in self.items:
row.use_serial_batch_fields = 1
@@ -1076,7 +1076,7 @@ class StockController(AccountsController):
"Purchase Invoice",
"Sales Invoice",
"Delivery Note",
] and frappe.db.get_single_value(
] and frappe.get_settings(
"Stock Settings", "allow_to_make_quality_inspection_after_purchase_or_delivery"
):
return
@@ -1092,7 +1092,7 @@ class StockController(AccountsController):
def validate_qi_submission(self, row):
"""Check if QI is submitted on row level, during submission"""
action = frappe.db.get_single_value("Stock Settings", "action_if_quality_inspection_is_not_submitted")
action = frappe.get_settings("Stock Settings", "action_if_quality_inspection_is_not_submitted")
qa_docstatus = frappe.db.get_value("Quality Inspection", row.quality_inspection, "docstatus")
if qa_docstatus != 1:
@@ -1107,7 +1107,7 @@ class StockController(AccountsController):
def validate_qi_rejection(self, row):
"""Check if QI is rejected on row level, during submission"""
action = frappe.db.get_single_value("Stock Settings", "action_if_quality_inspection_is_rejected")
action = frappe.get_settings("Stock Settings", "action_if_quality_inspection_is_rejected")
qa_status = frappe.db.get_value("Quality Inspection", row.quality_inspection, "status")
if qa_status == "Rejected":
@@ -1206,9 +1206,7 @@ class StockController(AccountsController):
item_wise_received_qty = self.get_item_wise_inter_received_qty()
precision = frappe.get_precision(self.doctype + " Item", "qty")
over_receipt_allowance = frappe.db.get_single_value(
"Stock Settings", "over_delivery_receipt_allowance"
)
over_receipt_allowance = frappe.get_settings("Stock Settings", "over_delivery_receipt_allowance")
parent_doctype = {
"Purchase Receipt": "Delivery Note",

View File

@@ -590,7 +590,7 @@ class SubcontractingController(StockController):
rm_obj.reference_name = item_row.name
use_serial_batch_fields = frappe.db.get_single_value("Stock Settings", "use_serial_batch_fields")
use_serial_batch_fields = frappe.get_settings("Stock Settings", "use_serial_batch_fields")
if self.doctype == self.subcontract_data.order_doctype:
rm_obj.required_qty = flt(qty, rm_obj.precision("required_qty"))

View File

@@ -195,7 +195,7 @@ class SalesOrder(SellingController):
def onload(self) -> None:
super().onload()
if frappe.db.get_single_value("Stock Settings", "enable_stock_reservation"):
if frappe.get_settings("Stock Settings", "enable_stock_reservation"):
if self.has_unreserved_stock():
self.set_onload("has_unreserved_stock", True)
@@ -246,7 +246,7 @@ class SalesOrder(SellingController):
self.enable_auto_reserve_stock()
def enable_auto_reserve_stock(self):
if self.is_new() and frappe.db.get_single_value("Stock Settings", "auto_reserve_stock"):
if self.is_new() and frappe.get_settings("Stock Settings", "auto_reserve_stock"):
self.reserve_stock = 1
def set_has_unit_price_items(self):
@@ -633,7 +633,7 @@ class SalesOrder(SellingController):
if total_picked_qty and total_qty:
per_picked = total_picked_qty / total_qty * 100
pick_percentage = frappe.db.get_single_value("Stock Settings", "over_picking_allowance")
pick_percentage = frappe.get_settings("Stock Settings", "over_picking_allowance")
if pick_percentage:
total_qty += flt(total_qty) * (pick_percentage / 100)
@@ -729,7 +729,7 @@ class SalesOrder(SellingController):
def validate_reserved_stock(self):
"""Clean reserved stock flag for non-stock Item"""
enable_stock_reservation = frappe.db.get_single_value("Stock Settings", "enable_stock_reservation")
enable_stock_reservation = frappe.get_settings("Stock Settings", "enable_stock_reservation")
for item in self.items:
if item.reserve_stock and (not enable_stock_reservation or not cint(item.is_stock_item)):
@@ -1861,4 +1861,4 @@ def get_work_order_items(sales_order, for_raw_material_request=0):
@frappe.whitelist()
def get_stock_reservation_status():
return frappe.db.get_single_value("Stock Settings", "enable_stock_reservation")
return frappe.get_settings("Stock Settings", "enable_stock_reservation")

View File

@@ -37,7 +37,7 @@ def batch_uses_naming_series():
Verify if the Batch is to be named using a naming series
:return: bool
"""
use_naming_series = cint(frappe.db.get_single_value("Stock Settings", "use_naming_series"))
use_naming_series = cint(frappe.get_settings("Stock Settings", "use_naming_series"))
return bool(use_naming_series)
@@ -49,7 +49,7 @@ def _get_batch_prefix():
is set to use naming series.
:return: The naming series.
"""
naming_series_prefix = frappe.db.get_single_value("Stock Settings", "naming_series_prefix")
naming_series_prefix = frappe.get_settings("Stock Settings", "naming_series_prefix")
if not naming_series_prefix:
naming_series_prefix = "BATCH-"
@@ -160,7 +160,7 @@ class Batch(Document):
from erpnext.stock.utils import get_valuation_method
if self.is_new():
if get_valuation_method(self.item) == "Moving Average" and frappe.db.get_single_value(
if get_valuation_method(self.item) == "Moving Average" and frappe.get_settings(
"Stock Settings", "do_not_use_batchwise_valuation"
):
self.use_batchwise_valuation = 0

View File

@@ -227,7 +227,7 @@ class Item(Document):
def validate_description(self):
"""Clean HTML description if set"""
if (
cint(frappe.db.get_single_value("Stock Settings", "clean_description_html"))
cint(frappe.get_settings("Stock Settings", "clean_description_html"))
and self.description != self.item_name # perf: Avoid cleaning up a fallback
):
self.description = clean_html(self.description)
@@ -274,7 +274,7 @@ class Item(Document):
for default in self.item_defaults or [
frappe._dict({"company": frappe.defaults.get_defaults().company})
]:
default_warehouse = default.default_warehouse or frappe.db.get_single_value(
default_warehouse = default.default_warehouse or frappe.get_settings(
"Stock Settings", "default_warehouse"
)
if default_warehouse:
@@ -317,9 +317,7 @@ class Item(Document):
)
def validate_retain_sample(self):
if self.retain_sample and not frappe.db.get_single_value(
"Stock Settings", "sample_retention_warehouse"
):
if self.retain_sample and not frappe.get_settings("Stock Settings", "sample_retention_warehouse"):
frappe.throw(_("Please select Sample Retention Warehouse in Stock Settings first"))
if self.retain_sample and not self.has_batch_no:
frappe.throw(
@@ -664,7 +662,7 @@ class Item(Document):
def recalculate_bin_qty(self, new_name):
from erpnext.stock.stock_balance import repost_stock
existing_allow_negative_stock = frappe.db.get_single_value("Stock Settings", "allow_negative_stock")
existing_allow_negative_stock = frappe.get_settings("Stock Settings", "allow_negative_stock")
frappe.db.set_single_value("Stock Settings", "allow_negative_stock", 1)
repost_stock_for_warehouses = frappe.get_all(
@@ -963,9 +961,7 @@ class Item(Document):
return
if not values.get("valuation_method") and self.get("valuation_method"):
values["valuation_method"] = (
frappe.db.get_single_value("Stock Settings", "valuation_method") or "FIFO"
)
values["valuation_method"] = frappe.get_settings("Stock Settings", "valuation_method") or "FIFO"
changed_fields = [
field for field in restricted_fields if cstr(self.get(field)) != cstr(values.get(field))
@@ -1051,7 +1047,7 @@ class Item(Document):
def validate_auto_reorder_enabled_in_stock_settings(self):
if self.reorder_levels:
enabled = frappe.db.get_single_value("Stock Settings", "auto_indent")
enabled = frappe.get_settings("Stock Settings", "auto_indent")
if not enabled:
frappe.msgprint(
msg=_("You have to enable auto re-order in Stock Settings to maintain re-order levels."),

View File

@@ -234,7 +234,7 @@ def update_packed_item_stock_data(main_item_row, pi_row, packing_item, item_data
bin = get_packed_item_bin_qty(packing_item.item_code, pi_row.warehouse)
pi_row.actual_qty = flt(bin.get("actual_qty"))
pi_row.projected_qty = flt(bin.get("projected_qty"))
pi_row.use_serial_batch_fields = frappe.db.get_single_value("Stock Settings", "use_serial_batch_fields")
pi_row.use_serial_batch_fields = frappe.get_settings("Stock Settings", "use_serial_batch_fields")
def update_packed_item_price_data(pi_row, item_data, doc):

View File

@@ -440,7 +440,7 @@ class PickList(Document):
def validate_picked_qty(self, data):
over_delivery_receipt_allowance = 100 + flt(
frappe.db.get_single_value("Stock Settings", "over_delivery_receipt_allowance")
frappe.get_settings("Stock Settings", "over_delivery_receipt_allowance")
)
for row in data:
@@ -1102,7 +1102,7 @@ def get_available_item_locations_for_batched_item(
{
"item_code": item_code,
"warehouse": from_warehouses,
"based_on": frappe.db.get_single_value("Stock Settings", "pick_serial_and_batch_based_on"),
"based_on": frappe.get_settings("Stock Settings", "pick_serial_and_batch_based_on"),
}
)
)

View File

@@ -952,10 +952,8 @@ class PurchaseReceipt(BuyingController):
def reserve_stock_for_sales_order(self):
if (
self.is_return
or not frappe.db.get_single_value("Stock Settings", "enable_stock_reservation")
or not frappe.db.get_single_value(
"Stock Settings", "auto_reserve_stock_for_sales_order_on_purchase"
)
or not frappe.get_settings("Stock Settings", "enable_stock_reservation")
or not frappe.get_settings("Stock Settings", "auto_reserve_stock_for_sales_order_on_purchase")
):
return
@@ -990,7 +988,7 @@ class PurchaseReceipt(BuyingController):
)
def reserve_stock_for_production_plan(self):
if self.is_return or not frappe.db.get_single_value("Stock Settings", "enable_stock_reservation"):
if self.is_return or not frappe.get_settings("Stock Settings", "enable_stock_reservation"):
return
production_plan_references = self.get_production_plan_references()

View File

@@ -84,9 +84,7 @@ class SerialandBatchBundle(Document):
# end: auto-generated types
def autoname(self):
if frappe.db.get_single_value(
"Stock Settings", "set_serial_and_batch_bundle_naming_based_on_naming_series"
):
if frappe.get_settings("Stock Settings", "set_serial_and_batch_bundle_naming_based_on_naming_series"):
if not self.naming_series:
frappe.throw(_("Naming Series is mandatory"))
@@ -161,7 +159,7 @@ class SerialandBatchBundle(Document):
if self.type_of_transaction == "Outward" or not self.has_serial_no:
return
if frappe.db.get_single_value("Stock Settings", "allow_existing_serial_no"):
if frappe.get_settings("Stock Settings", "allow_existing_serial_no"):
return
if self.voucher_type not in ["Purchase Receipt", "Purchase Invoice", "Stock Entry"]:

View File

@@ -2457,7 +2457,7 @@ class StockEntry(StockController):
if not qty:
return
use_serial_batch_fields = frappe.db.get_single_value("Stock Settings", "use_serial_batch_fields")
use_serial_batch_fields = frappe.get_settings("Stock Settings", "use_serial_batch_fields")
ste_item_details = {
"from_warehouse": item.warehouse,
@@ -2935,7 +2935,7 @@ def move_sample_to_retention_warehouse(company, items):
if isinstance(items, str):
items = json.loads(items)
retention_warehouse = frappe.db.get_single_value("Stock Settings", "sample_retention_warehouse")
retention_warehouse = frappe.get_settings("Stock Settings", "sample_retention_warehouse")
stock_entry = frappe.new_doc("Stock Entry")
stock_entry.company = company
stock_entry.purpose = "Material Transfer"
@@ -2986,7 +2986,7 @@ def make_stock_in_entry(source_name, target_doc=None):
target.stock_entry_type = "Material Transfer"
target.set_missing_values()
if not frappe.db.get_single_value("Stock Settings", "use_serial_batch_fields"):
if not frappe.get_settings("Stock Settings", "use_serial_batch_fields"):
target.make_serial_and_batch_bundle_for_transfer()
def update_item(source_doc, target_doc, source_parent):
@@ -3215,7 +3215,7 @@ def validate_sample_quantity(item_code, sample_quantity, qty, batch_no=None):
frappe.throw(
_("Sample quantity {0} cannot be more than received quantity {1}").format(sample_quantity, qty)
)
retention_warehouse = frappe.db.get_single_value("Stock Settings", "sample_retention_warehouse")
retention_warehouse = frappe.get_settings("Stock Settings", "sample_retention_warehouse")
retainted_qty = 0
if batch_no:
retainted_qty = get_batch_qty(batch_no, retention_warehouse, item_code)

View File

@@ -299,7 +299,7 @@ class StockLedgerEntry(Document):
is_group_warehouse(self.warehouse)
def validate_with_last_transaction_posting_time(self):
authorized_role = frappe.db.get_single_value(
authorized_role = frappe.get_settings(
"Stock Settings", "role_allowed_to_create_edit_back_dated_transactions"
)
if authorized_role:

View File

@@ -162,7 +162,7 @@ class StockReservationEntry(Document):
not self.from_voucher_type
and (self.get("_action") == "submit")
and (self.has_serial_no or self.has_batch_no)
and cint(frappe.db.get_single_value("Stock Settings", "auto_reserve_serial_and_batch"))
and cint(frappe.get_settings("Stock Settings", "auto_reserve_serial_and_batch"))
):
from erpnext.stock.doctype.batch.batch import get_available_batches
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos_for_outward
@@ -176,7 +176,7 @@ class StockReservationEntry(Document):
"warehouse": self.warehouse,
"qty": abs(self.reserved_qty) or 0,
"based_on": based_on
or frappe.db.get_single_value("Stock Settings", "pick_serial_and_batch_based_on"),
or frappe.get_settings("Stock Settings", "pick_serial_and_batch_based_on"),
}
)
@@ -219,9 +219,7 @@ class StockReservationEntry(Document):
return
if self.reservation_based_on == "Serial and Batch":
allow_partial_reservation = frappe.db.get_single_value(
"Stock Settings", "allow_partial_reservation"
)
allow_partial_reservation = frappe.get_settings("Stock Settings", "allow_partial_reservation")
available_serial_nos = []
if self.has_serial_no:
@@ -570,7 +568,7 @@ class StockReservationEntry(Document):
def validate_stock_reservation_settings(voucher: object) -> None:
"""Raises an exception if `Stock Reservation` is not enabled or `Voucher Type` is not allowed."""
if not frappe.db.get_single_value("Stock Settings", "enable_stock_reservation"):
if not frappe.get_settings("Stock Settings", "enable_stock_reservation"):
msg = _("Please enable {0} in the {1}.").format(
frappe.bold(_("Stock Reservation")),
frappe.bold(_("Stock Settings")),
@@ -1347,7 +1345,7 @@ def create_stock_reservation_entries_for_so_items(
validate_stock_reservation_settings(sales_order)
allow_partial_reservation = frappe.db.get_single_value("Stock Settings", "allow_partial_reservation")
allow_partial_reservation = frappe.get_settings("Stock Settings", "allow_partial_reservation")
items = []
if items_details:

View File

@@ -136,7 +136,7 @@ def get_item_details(
out.update(data)
if (
frappe.db.get_single_value("Stock Settings", "auto_create_serial_and_batch_bundle_for_outward")
frappe.get_settings("Stock Settings", "auto_create_serial_and_batch_bundle_for_outward")
and not ctx.get("serial_and_batch_bundle")
and (ctx.get("use_serial_batch_fields") or ctx.get("doctype") == "POS Invoice")
):
@@ -201,7 +201,7 @@ def update_stock(ctx, out, doc=None):
{
"item_code": ctx.item_code,
"warehouse": ctx.warehouse,
"based_on": frappe.db.get_single_value("Stock Settings", "pick_serial_and_batch_based_on"),
"based_on": frappe.get_settings("Stock Settings", "pick_serial_and_batch_based_on"),
}
)
@@ -591,7 +591,7 @@ def get_item_warehouse_(ctx: ItemDetailsCtx, item, overwrite_warehouse, defaults
warehouse = ctx.warehouse
if not warehouse:
default_warehouse = frappe.db.get_single_value("Stock Settings", "default_warehouse")
default_warehouse = frappe.get_settings("Stock Settings", "default_warehouse")
if frappe.db.get_value("Warehouse", default_warehouse, "company") == ctx.company:
return default_warehouse

View File

@@ -151,14 +151,12 @@ class SerialBatchBundle:
if (
self.item_details.has_batch_no
and not self.item_details.batch_number_series
and not frappe.db.get_single_value("Stock Settings", "naming_series_prefix")
and not frappe.get_settings("Stock Settings", "naming_series_prefix")
):
msg += f". If you want auto pick batch bundle, then kindly set Batch Number Series in Item {self.item_code}"
elif self.sle.actual_qty < 0:
if not frappe.db.get_single_value(
"Stock Settings", "auto_create_serial_and_batch_bundle_for_outward"
):
if not frappe.get_settings("Stock Settings", "auto_create_serial_and_batch_bundle_for_outward"):
msg += ". If you want auto pick serial/batch bundle, then kindly enable 'Auto Create Serial and Batch Bundle' in Stock Settings."
if msg:
@@ -187,7 +185,7 @@ class SerialBatchBundle:
if self.sle.actual_qty < 0 and self.is_material_transfer():
values_to_update["valuation_rate"] = flt(sn_doc.avg_rate)
if not frappe.db.get_single_value(
if not frappe.get_settings(
"Stock Settings", "do_not_update_serial_batch_on_creation_of_auto_bundle"
):
if sn_doc.has_serial_no:
@@ -253,9 +251,7 @@ class SerialBatchBundle:
and (
self.item_details.create_new_batch
or (
frappe.db.get_single_value(
"Stock Settings", "auto_create_serial_and_batch_bundle_for_outward"
)
frappe.get_settings("Stock Settings", "auto_create_serial_and_batch_bundle_for_outward")
and self.sle.actual_qty < 0
)
)
@@ -724,7 +720,7 @@ class BatchNoValuation(DeprecatedBatchNoValuation):
self.batchwise_valuation_batches = []
self.non_batchwise_valuation_batches = []
if get_valuation_method(self.sle.item_code) == "Moving Average" and frappe.db.get_single_value(
if get_valuation_method(self.sle.item_code) == "Moving Average" and frappe.get_settings(
"Stock Settings", "do_not_use_batchwise_valuation"
):
self.non_batchwise_valuation_batches = self.batches
@@ -1029,7 +1025,7 @@ class SerialBatchCreation:
"item_code": self.item_code,
"warehouse": self.warehouse,
"qty": abs(self.actual_qty) if self.actual_qty else 0,
"based_on": frappe.db.get_single_value("Stock Settings", "pick_serial_and_batch_based_on"),
"based_on": frappe.get_settings("Stock Settings", "pick_serial_and_batch_based_on"),
}
)

View File

@@ -15,7 +15,7 @@ def repost(only_actual=False, allow_negative_stock=False, allow_zero_rate=False,
frappe.db.auto_commit_on_many_writes = 1
if allow_negative_stock:
existing_allow_negative_stock = frappe.db.get_single_value("Stock Settings", "allow_negative_stock")
existing_allow_negative_stock = frappe.get_settings("Stock Settings", "allow_negative_stock")
frappe.db.set_single_value("Stock Settings", "allow_negative_stock", 1)
item_warehouses = frappe.db.sql(

View File

@@ -252,7 +252,7 @@ def get_incoming_rate(args, raise_error_if_no_rate=True):
"Item", args.get("item_code"), ["has_serial_no", "has_batch_no"], as_dict=1
)
use_moving_avg_for_batch = frappe.db.get_single_value("Stock Settings", "do_not_use_batchwise_valuation")
use_moving_avg_for_batch = frappe.get_settings("Stock Settings", "do_not_use_batchwise_valuation")
if isinstance(args, dict):
args = frappe._dict(args)