Merge pull request #39282 from ruthra-kumar/type_error_on_transaction_js

fix: possible typeerror on transaction.js
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index 82af85d..651599d 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -91,8 +91,8 @@
 			super(Account, self).on_update()
 
 	def onload(self):
-		frozen_accounts_modifier = frappe.db.get_value(
-			"Accounts Settings", "Accounts Settings", "frozen_accounts_modifier"
+		frozen_accounts_modifier = frappe.db.get_single_value(
+			"Accounts Settings", "frozen_accounts_modifier"
 		)
 		if not frozen_accounts_modifier or frozen_accounts_modifier in frappe.get_roles():
 			self.set_onload("can_freeze_account", True)
diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
index 8d82123..1d6cb8e 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
@@ -91,6 +91,7 @@
 		self.validate_duplicate_references()
 		self.allocate_payment_entries()
 		self.update_allocated_amount()
+		self.set_status()
 
 	def on_cancel(self):
 		for payment_entry in self.payment_entries:
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py
index 139f526..777a5bb 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.py
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py
@@ -435,8 +435,8 @@
 def validate_frozen_account(account, adv_adj=None):
 	frozen_account = frappe.get_cached_value("Account", account, "freeze_account")
 	if frozen_account == "Yes" and not adv_adj:
-		frozen_accounts_modifier = frappe.db.get_value(
-			"Accounts Settings", None, "frozen_accounts_modifier"
+		frozen_accounts_modifier = frappe.db.get_single_value(
+			"Accounts Settings", "frozen_accounts_modifier"
 		)
 
 		if not frozen_accounts_modifier:
diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py
index 18aa682..17293ad 100644
--- a/erpnext/accounts/doctype/pricing_rule/utils.py
+++ b/erpnext/accounts/doctype/pricing_rule/utils.py
@@ -527,7 +527,7 @@
 		values.extend(warehouses)
 
 	if items:
-		condition = " and `tab{child_doc}`.{apply_on} in ({items})".format(
+		condition += " and `tab{child_doc}`.{apply_on} in ({items})".format(
 			child_doc=child_doctype, apply_on=apply_on, items=",".join(["%s"] * len(items))
 		)
 
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index e676560..5338054 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -552,7 +552,7 @@
 		self.against_expense_account = ",".join(against_accounts)
 
 	def po_required(self):
-		if frappe.db.get_value("Buying Settings", None, "po_required") == "Yes":
+		if frappe.db.get_single_value("Buying Settings", "po_required") == "Yes":
 
 			if frappe.get_value(
 				"Supplier", self.supplier, "allow_purchase_invoice_creation_without_purchase_order"
@@ -572,7 +572,7 @@
 
 	def pr_required(self):
 		stock_items = self.get_stock_items()
-		if frappe.db.get_value("Buying Settings", None, "pr_required") == "Yes":
+		if frappe.db.get_single_value("Buying Settings", "pr_required") == "Yes":
 
 			if frappe.get_value(
 				"Supplier", self.supplier, "allow_purchase_invoice_creation_without_purchase_receipt"
@@ -1104,17 +1104,6 @@
 										item=item,
 									)
 								)
-
-						# update gross amount of asset bought through this document
-						assets = frappe.db.get_all(
-							"Asset", filters={"purchase_invoice": self.name, "item_code": item.item_code}
-						)
-						for asset in assets:
-							frappe.db.set_value("Asset", asset.name, "gross_purchase_amount", flt(item.valuation_rate))
-							frappe.db.set_value(
-								"Asset", asset.name, "purchase_receipt_amount", flt(item.valuation_rate)
-							)
-
 			if (
 				self.auto_accounting_for_stock
 				and self.is_opening == "No"
@@ -1156,17 +1145,24 @@
 							item.item_tax_amount, item.precision("item_tax_amount")
 						)
 
+			if item.is_fixed_asset and item.landed_cost_voucher_amount:
+				self.update_gross_purchase_amount_for_linked_assets(item)
+
+	def update_gross_purchase_amount_for_linked_assets(self, item):
 		assets = frappe.db.get_all(
 			"Asset",
 			filters={"purchase_invoice": self.name, "item_code": item.item_code},
 			fields=["name", "asset_quantity"],
 		)
 		for asset in assets:
+			purchase_amount = flt(item.valuation_rate) * asset.asset_quantity
 			frappe.db.set_value(
-				"Asset", asset.name, "gross_purchase_amount", flt(item.valuation_rate) * asset.asset_quantity
-			)
-			frappe.db.set_value(
-				"Asset", asset.name, "purchase_receipt_amount", flt(item.valuation_rate) * asset.asset_quantity
+				"Asset",
+				asset.name,
+				{
+					"gross_purchase_amount": purchase_amount,
+					"purchase_receipt_amount": purchase_amount,
+				},
 			)
 
 	def make_stock_adjustment_entry(
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 8aa95bf..5acd8b0 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -1237,8 +1237,8 @@
 
 	@change_settings("Accounts Settings", {"unlink_payment_on_cancellation_of_invoice": 1})
 	def test_gain_loss_with_advance_entry(self):
-		unlink_enabled = frappe.db.get_value(
-			"Accounts Settings", "Accounts Settings", "unlink_payment_on_cancel_of_invoice"
+		unlink_enabled = frappe.db.get_single_value(
+			"Accounts Settings", "unlink_payment_on_cancel_of_invoice"
 		)
 
 		frappe.db.set_single_value("Accounts Settings", "unlink_payment_on_cancel_of_invoice", 1)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index c8d92d0..ba2cd82 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -898,8 +898,8 @@
 				frm.events.append_time_log(frm, timesheet, 1.0);
 			}
 		});
-		frm.refresh_field("timesheets");
 		frm.trigger("calculate_timesheet_totals");
+		frm.refresh();
 	},
 
 	async get_exchange_rate(frm, from_currency, to_currency) {
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index 91ba239..b48a8e6 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -654,10 +654,10 @@
 	Hence stop admin to bypass if accounts are freezed
 	"""
 	if not adv_adj:
-		acc_frozen_upto = frappe.db.get_value("Accounts Settings", None, "acc_frozen_upto")
+		acc_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto")
 		if acc_frozen_upto:
-			frozen_accounts_modifier = frappe.db.get_value(
-				"Accounts Settings", None, "frozen_accounts_modifier"
+			frozen_accounts_modifier = frappe.db.get_single_value(
+				"Accounts Settings", "frozen_accounts_modifier"
 			)
 			if getdate(posting_date) <= getdate(acc_frozen_upto) and (
 				frozen_accounts_modifier not in frappe.get_roles() or frappe.session.user == "Administrator"
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 9feda11..3a70afc 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -55,8 +55,8 @@
 	def run(self, args):
 		self.filters.update(args)
 		self.set_defaults()
-		self.party_naming_by = frappe.db.get_value(
-			args.get("naming_by")[0], None, args.get("naming_by")[1]
+		self.party_naming_by = frappe.db.get_single_value(
+			args.get("naming_by")[0], args.get("naming_by")[1]
 		)
 		self.get_columns()
 		self.get_data()
diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
index 22b5c6b..0947cff 100644
--- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
+++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
@@ -24,8 +24,8 @@
 	def run(self, args):
 		self.account_type = args.get("account_type")
 		self.party_type = get_party_types_from_account_type(self.account_type)
-		self.party_naming_by = frappe.db.get_value(
-			args.get("naming_by")[0], None, args.get("naming_by")[1]
+		self.party_naming_by = frappe.db.get_single_value(
+			args.get("naming_by")[0], args.get("naming_by")[1]
 		)
 		self.get_columns()
 		self.get_data(args)
diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
index 0464f99..a2c0f86 100644
--- a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
+++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
@@ -21,8 +21,8 @@
 			frappe.throw(_("From Date must be before To Date"))
 
 		self.filters.party_type = args.get("party_type")
-		self.party_naming_by = frappe.db.get_value(
-			args.get("naming_by")[0], None, args.get("naming_by")[1]
+		self.party_naming_by = frappe.db.get_single_value(
+			args.get("naming_by")[0], args.get("naming_by")[1]
 		)
 
 		self.get_gl_entries()
diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js
index 58fd6d4..02e7a9b 100644
--- a/erpnext/assets/doctype/asset/asset.js
+++ b/erpnext/assets/doctype/asset/asset.js
@@ -571,10 +571,16 @@
 				indicator: 'red'
 			});
 		}
-		frm.set_value('gross_purchase_amount', item.base_net_rate + item.item_tax_amount);
-		frm.set_value('purchase_receipt_amount', item.base_net_rate + item.item_tax_amount);
-		item.asset_location && frm.set_value('location', item.asset_location);
+		var is_grouped_asset = frappe.db.get_value('Item', item.item_code, 'is_grouped_asset');
+		var asset_quantity = is_grouped_asset ? item.qty : 1;
+		var purchase_amount = flt(item.valuation_rate * asset_quantity, precision('gross_purchase_amount'));
+
+		frm.set_value('gross_purchase_amount', purchase_amount);
+		frm.set_value('purchase_receipt_amount', purchase_amount);
+		frm.set_value('asset_quantity', asset_quantity);
 		frm.set_value('cost_center', item.cost_center || purchase_doc.cost_center);
+		if(item.asset_location) { frm.set_value('location', item.asset_location); }
+
 	},
 
 	set_depreciation_rate: function(frm, row) {
diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py
index 66930c0..017df90 100644
--- a/erpnext/assets/doctype/asset/depreciation.py
+++ b/erpnext/assets/doctype/asset/depreciation.py
@@ -35,7 +35,7 @@
 def post_depreciation_entries(date=None):
 	# Return if automatic booking of asset depreciation is disabled
 	if not cint(
-		frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically")
+		frappe.db.get_single_value("Accounts Settings", "book_asset_depreciation_entry_automatically")
 	):
 		return
 
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json
index 3f8559e..b05de7d 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.json
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.json
@@ -214,7 +214,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2023-11-28 13:01:18.403492",
+ "modified": "2024-01-05 15:26:02.320942",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Buying Settings",
@@ -238,6 +238,41 @@
    "role": "Purchase Manager",
    "share": 1,
    "write": 1
+  },
+  {
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Accounts User",
+   "share": 1
+  },
+  {
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Accounts Manager",
+   "share": 1
+  },
+  {
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Stock Manager",
+   "share": 1
+  },
+  {
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Stock User",
+   "share": 1
+  },
+  {
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Purchase User",
+   "share": 1
   }
  ],
  "sort_field": "modified",
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
index 9aaf86b..eec996c 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
@@ -358,8 +358,8 @@
 			target_doc.currency = args.currency or get_party_account_currency(
 				"Supplier", for_supplier, source.company
 			)
-			target_doc.buying_price_list = args.buying_price_list or frappe.db.get_value(
-				"Buying Settings", None, "buying_price_list"
+			target_doc.buying_price_list = args.buying_price_list or frappe.db.get_single_value(
+				"Buying Settings", "buying_price_list"
 			)
 		set_missing_values(source, target_doc)
 
@@ -399,7 +399,7 @@
 				"currency": doc.get("currency")
 				or get_party_account_currency("Supplier", doc.get("supplier"), doc.get("company")),
 				"buying_price_list": doc.get("buying_price_list")
-				or frappe.db.get_value("Buying Settings", None, "buying_price_list"),
+				or frappe.db.get_single_value("Buying Settings", "buying_price_list"),
 			}
 		)
 		add_items(sq_doc, doc.get("supplier"), doc.get("items"))
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 572fa51..fb68010 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -744,11 +744,8 @@
 		item_data = frappe.db.get_value(
 			"Item", row.item_code, ["asset_naming_series", "asset_category"], as_dict=1
 		)
-
-		if is_grouped_asset:
-			purchase_amount = flt(row.base_amount + row.item_tax_amount)
-		else:
-			purchase_amount = flt(row.base_rate + row.item_tax_amount)
+		asset_quantity = row.qty if is_grouped_asset else 1
+		purchase_amount = flt(row.valuation_rate) * asset_quantity
 
 		asset = frappe.get_doc(
 			{
@@ -764,7 +761,7 @@
 				"calculate_depreciation": 0,
 				"purchase_receipt_amount": purchase_amount,
 				"gross_purchase_amount": purchase_amount,
-				"asset_quantity": row.qty if is_grouped_asset else 1,
+				"asset_quantity": asset_quantity,
 				"purchase_receipt": self.name if self.doctype == "Purchase Receipt" else None,
 				"purchase_invoice": self.name if self.doctype == "Purchase Invoice" else None,
 			}
diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py
index e7bd2a7..6e50279 100644
--- a/erpnext/controllers/sales_and_purchase_return.py
+++ b/erpnext/controllers/sales_and_purchase_return.py
@@ -10,7 +10,7 @@
 import erpnext
 from erpnext.stock.serial_batch_bundle import get_batches_from_bundle
 from erpnext.stock.serial_batch_bundle import get_serial_nos as get_serial_nos_from_bundle
-from erpnext.stock.utils import get_incoming_rate
+from erpnext.stock.utils import get_incoming_rate, get_valuation_method
 
 
 class StockOverReturnError(frappe.ValidationError):
@@ -116,7 +116,12 @@
 				ref = valid_items.get(d.item_code, frappe._dict())
 				validate_quantity(doc, d, ref, valid_items, already_returned_items)
 
-				if ref.rate and doc.doctype in ("Delivery Note", "Sales Invoice") and flt(d.rate) > ref.rate:
+				if (
+					ref.rate
+					and flt(d.rate) > ref.rate
+					and doc.doctype in ("Delivery Note", "Sales Invoice")
+					and get_valuation_method(ref.item_code) != "Moving Average"
+				):
 					frappe.throw(
 						_("Row # {0}: Rate cannot be greater than the rate used in {1} {2}").format(
 							d.idx, doc.doctype, doc.return_against
diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py
index a735510..541f77b 100644
--- a/erpnext/crm/doctype/appointment/appointment.py
+++ b/erpnext/crm/doctype/appointment/appointment.py
@@ -76,7 +76,7 @@
 			self.create_calendar_event()
 		else:
 			# Set status to unverified
-			self.status = "Unverified"
+			self.db_set("status", "Unverified")
 			# Send email to confirm
 			self.send_confirmation_email()
 
diff --git a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py
index 8ebca54..ba1fae9 100644
--- a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py
+++ b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py
@@ -129,9 +129,7 @@
 		self.default_cost_center, self.default_round_off_account = frappe.db.get_value(
 			"Company", self.erpnext_company, ["cost_center", "round_off_account"]
 		)
-		self.default_warehouse = frappe.db.get_value(
-			"Stock Settings", "Stock Settings", "default_warehouse"
-		)
+		self.default_warehouse = frappe.db.get_single_value("Stock Settings", "default_warehouse")
 
 	def _process_master_data(self):
 		def get_company_name(collection):
diff --git a/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py b/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py
index a2919b7..f013b88 100644
--- a/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py
+++ b/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py
@@ -86,10 +86,12 @@
 		if new_bom == d.parent:
 			frappe.throw(_("BOM recursion: {0} cannot be child of {1}").format(new_bom, d.parent))
 
-		bom_list.append(d.parent)
+		if d.parent not in tuple(bom_list):
+			bom_list.append(d.parent)
+
 		get_ancestor_boms(d.parent, bom_list)
 
-	return list(set(bom_list))
+	return bom_list
 
 
 def update_new_bom_in_bom_items(unit_cost: float, current_bom: str, new_bom: str) -> None:
diff --git a/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py b/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py
index b38fc89..30e6f5e 100644
--- a/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py
+++ b/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py
@@ -57,6 +57,68 @@
 		log.reload()
 		self.assertEqual(log.status, "Completed")
 
+	def test_bom_replace_for_root_bom(self):
+		"""
+		- B-Item A (Root Item)
+		        - B-Item B
+		                - B-Item C
+		        - B-Item D
+		                - B-Item E
+		                        - B-Item F
+
+		Create New BOM for B-Item E with B-Item G and replace it in the above BOM.
+		"""
+
+		from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom
+		from erpnext.stock.doctype.item.test_item import make_item
+
+		items = ["B-Item A", "B-Item B", "B-Item C", "B-Item D", "B-Item E", "B-Item F", "B-Item G"]
+
+		for item_code in items:
+			if not frappe.db.exists("Item", item_code):
+				make_item(item_code)
+
+		for item_code in items:
+			remove_bom(item_code)
+
+		bom_tree = {
+			"B-Item A": {"B-Item B": {"B-Item C": {}}, "B-Item D": {"B-Item E": {"B-Item F": {}}}}
+		}
+
+		root_bom = create_nested_bom(bom_tree, prefix="")
+
+		exploded_items = frappe.get_all(
+			"BOM Explosion Item", filters={"parent": root_bom.name}, fields=["item_code"]
+		)
+
+		exploded_items = [item.item_code for item in exploded_items]
+		expected_exploded_items = ["B-Item C", "B-Item F"]
+		self.assertEqual(sorted(exploded_items), sorted(expected_exploded_items))
+
+		old_bom = frappe.db.get_value("BOM", {"item": "B-Item E"}, "name")
+		bom_tree = {"B-Item E": {"B-Item G": {}}}
+
+		new_bom = create_nested_bom(bom_tree, prefix="")
+		enqueue_replace_bom(boms=frappe._dict(current_bom=old_bom, new_bom=new_bom.name))
+
+		exploded_items = frappe.get_all(
+			"BOM Explosion Item", filters={"parent": root_bom.name}, fields=["item_code"]
+		)
+
+		exploded_items = [item.item_code for item in exploded_items]
+		expected_exploded_items = ["B-Item C", "B-Item G"]
+		self.assertEqual(sorted(exploded_items), sorted(expected_exploded_items))
+
+
+def remove_bom(item_code):
+	boms = frappe.get_all("BOM", fields=["docstatus", "name"], filters={"item": item_code})
+
+	for row in boms:
+		if row.docstatus == 1:
+			frappe.get_doc("BOM", row.name).cancel()
+
+		frappe.delete_doc("BOM", row.name)
+
 
 def update_cost_in_all_boms_in_test():
 	"""
diff --git a/erpnext/manufacturing/doctype/workstation/workstation.py b/erpnext/manufacturing/doctype/workstation/workstation.py
index 0a247fc..0f05eaa 100644
--- a/erpnext/manufacturing/doctype/workstation/workstation.py
+++ b/erpnext/manufacturing/doctype/workstation/workstation.py
@@ -156,7 +156,7 @@
 		if not frappe.db.get_single_value("Manufacturing Settings", "allow_production_on_holidays"):
 			check_workstation_for_holiday(workstation, from_datetime, to_datetime)
 
-		if not cint(frappe.db.get_value("Manufacturing Settings", None, "allow_overtime")):
+		if not cint(frappe.db.get_single_value("Manufacturing Settings", "allow_overtime")):
 			is_within_operating_hours(workstation, operation, from_datetime, to_datetime)
 
 
diff --git a/erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py b/erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py
index 0f77afd..8e58d79 100644
--- a/erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py
+++ b/erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py
@@ -45,7 +45,7 @@
 			message=json.dumps(purchase_invoices + sales_invoices, indent=2),
 		)
 
-	acc_frozen_upto = frappe.db.get_value("Accounts Settings", None, "acc_frozen_upto")
+	acc_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto")
 	if acc_frozen_upto:
 		frappe.db.set_single_value("Accounts Settings", "acc_frozen_upto", None)
 
diff --git a/erpnext/patches/v14_0/migrate_crm_settings.py b/erpnext/patches/v14_0/migrate_crm_settings.py
index 2477255..d093bc3 100644
--- a/erpnext/patches/v14_0/migrate_crm_settings.py
+++ b/erpnext/patches/v14_0/migrate_crm_settings.py
@@ -2,8 +2,7 @@
 
 
 def execute():
-	settings = frappe.db.get_value(
-		"Selling Settings",
+	settings = frappe.db.get_single_value(
 		"Selling Settings",
 		["campaign_naming_by", "close_opportunity_after_days", "default_valid_till"],
 		as_dict=True,
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index d17d21c..382437f 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -370,18 +370,16 @@
 def get_project_list(
 	doctype, txt, filters, limit_start, limit_page_length=20, order_by="modified"
 ):
-	user = frappe.session.user
 	customers, suppliers = get_customers_suppliers("Project", frappe.session.user)
 
 	ignore_permissions = False
-	if is_website_user():
+	if is_website_user() and frappe.session.user != "Guest":
 		if not filters:
 			filters = []
 
 		if customers:
 			filters.append([doctype, "customer", "in", customers])
-
-		ignore_permissions = True
+			ignore_permissions = True
 
 	meta = frappe.get_meta(doctype)
 
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 09941ea..9542361 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -582,17 +582,17 @@
 
 	def set_indicator(self):
 		"""Set indicator for portal"""
-		if self.per_billed < 100 and self.per_delivered < 100:
-			self.indicator_color = "orange"
-			self.indicator_title = _("Not Paid and Not Delivered")
+		self.indicator_color = {
+			"Draft": "red",
+			"On Hold": "orange",
+			"To Deliver and Bill": "orange",
+			"To Bill": "orange",
+			"To Deliver": "orange",
+			"Completed": "green",
+			"Cancelled": "red",
+		}.get(self.status, "blue")
 
-		elif self.per_billed == 100 and self.per_delivered < 100:
-			self.indicator_color = "orange"
-			self.indicator_title = _("Paid and Not Delivered")
-
-		else:
-			self.indicator_color = "green"
-			self.indicator_title = _("Paid")
+		self.indicator_title = _(self.status)
 
 	def on_recurring(self, reference_doc, auto_repeat_doc):
 		def _get_delivery_date(ref_doc_delivery_date, red_doc_transaction_date, transaction_date):
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index a6c86a6..ac7fdb1 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -35,8 +35,8 @@
 	def setUpClass(cls):
 		super().setUpClass()
 		cls.unlink_setting = int(
-			frappe.db.get_value(
-				"Accounts Settings", "Accounts Settings", "unlink_advance_payment_on_cancelation_of_order"
+			frappe.db.get_single_value(
+				"Accounts Settings", "unlink_advance_payment_on_cancelation_of_order"
 			)
 		)
 
diff --git a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py
index 98633cb..a584d3a 100644
--- a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py
+++ b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py
@@ -13,7 +13,7 @@
 	if not filters:
 		filters = {}
 	# Check if customer id is according to naming series or customer name
-	customer_naming_type = frappe.db.get_value("Selling Settings", None, "cust_master_name")
+	customer_naming_type = frappe.db.get_single_value("Selling Settings", "cust_master_name")
 	columns = get_columns(customer_naming_type)
 
 	data = []
diff --git a/erpnext/startup/boot.py b/erpnext/startup/boot.py
index 4b4d14f..d2be1a0 100644
--- a/erpnext/startup/boot.py
+++ b/erpnext/startup/boot.py
@@ -9,8 +9,6 @@
 def boot_session(bootinfo):
 	"""boot session - send website info if guest"""
 
-	bootinfo.custom_css = frappe.db.get_value("Style Settings", None, "custom_css") or ""
-
 	if frappe.session["user"] != "Guest":
 		update_page_info(bootinfo)
 
diff --git a/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py b/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py
index f71d21d..1c70183 100644
--- a/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py
+++ b/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py
@@ -65,7 +65,7 @@
 				& (
 					(table.from_date.between(self.from_date, self.to_date))
 					| (table.to_date.between(self.from_date, self.to_date))
-					| (table.from_date >= self.from_date and table.to_date <= self.to_date)
+					| (table.from_date >= self.from_date and table.to_date >= self.to_date)
 				)
 			)
 		)
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 2d9e11a..feb4583 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -635,8 +635,8 @@
 	def recalculate_bin_qty(self, new_name):
 		from erpnext.stock.stock_balance import repost_stock
 
-		existing_allow_negative_stock = frappe.db.get_value(
-			"Stock Settings", None, "allow_negative_stock"
+		existing_allow_negative_stock = frappe.db.get_single_value(
+			"Stock Settings", "allow_negative_stock"
 		)
 		frappe.db.set_single_value("Stock Settings", "allow_negative_stock", 1)
 
diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
index 30b26a0..b4f7708 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
@@ -194,7 +194,8 @@
 		for d in self.get("purchase_receipts"):
 			doc = frappe.get_doc(d.receipt_document_type, d.receipt_document)
 			# check if there are {qty} assets created and linked to this receipt document
-			self.validate_asset_qty_and_status(d.receipt_document_type, doc)
+			if self.docstatus != 2:
+				self.validate_asset_qty_and_status(d.receipt_document_type, doc)
 
 			# set landed cost voucher amount in pr item
 			doc.set_landed_cost_voucher_amount()
@@ -239,20 +240,20 @@
 					},
 					fields=["name", "docstatus"],
 				)
-				if not docs or len(docs) != item.qty:
+				if not docs or len(docs) < item.qty:
 					frappe.throw(
 						_(
-							"There are not enough asset created or linked to {0}. Please create or link {1} Assets with respective document."
-						).format(item.receipt_document, item.qty)
+							"There are only {0} asset created or linked to {1}. Please create or link {2} Assets with respective document."
+						).format(len(docs), item.receipt_document, item.qty)
 					)
 				if docs:
 					for d in docs:
 						if d.docstatus == 1:
 							frappe.throw(
 								_(
-									"{2} <b>{0}</b> has submitted Assets. Remove Item <b>{1}</b> from table to continue."
+									"{0} <b>{1}</b> has submitted Assets. Remove Item <b>{2}</b> from table to continue."
 								).format(
-									item.receipt_document, item.item_code, item.receipt_document_type
+									item.receipt_document_type, item.receipt_document, item.item_code
 								)
 							)
 
diff --git a/erpnext/stock/doctype/price_list/price_list.py b/erpnext/stock/doctype/price_list/price_list.py
index 580c7c0..882c3f5 100644
--- a/erpnext/stock/doctype/price_list/price_list.py
+++ b/erpnext/stock/doctype/price_list/price_list.py
@@ -39,11 +39,11 @@
 
 	def set_default_if_missing(self):
 		if cint(self.selling):
-			if not frappe.db.get_value("Selling Settings", None, "selling_price_list"):
+			if not frappe.db.get_single_value("Selling Settings", "selling_price_list"):
 				frappe.set_value("Selling Settings", "Selling Settings", "selling_price_list", self.name)
 
 		elif cint(self.buying):
-			if not frappe.db.get_value("Buying Settings", None, "buying_price_list"):
+			if not frappe.db.get_single_value("Buying Settings", "buying_price_list"):
 				frappe.set_value("Buying Settings", "Buying Settings", "buying_price_list", self.name)
 
 	def update_item_price(self):
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index c7e36e9..6a92988 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -13,6 +13,7 @@
 import erpnext
 from erpnext.accounts.utils import get_account_currency
 from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_enabled
+from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
 from erpnext.buying.utils import check_on_hold_or_closed_status
 from erpnext.controllers.buying_controller import BuyingController
 from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_transaction
@@ -302,7 +303,7 @@
 			)
 
 	def po_required(self):
-		if frappe.db.get_value("Buying Settings", None, "po_required") == "Yes":
+		if frappe.db.get_single_value("Buying Settings", "po_required") == "Yes":
 			for d in self.get("items"):
 				if not d.purchase_order:
 					frappe.throw(_("Purchase Order number required for Item {0}").format(d.item_code))
@@ -674,15 +675,16 @@
 				landed_cost_entries = get_item_account_wise_additional_cost(self.name)
 
 				if d.is_fixed_asset:
-					account_type = (
-						"capital_work_in_progress_account"
-						if is_cwip_accounting_enabled(d.asset_category)
-						else "fixed_asset_account"
-					)
-
-					stock_asset_account_name = get_asset_account(
-						account_type, asset_category=d.asset_category, company=self.company
-					)
+					if is_cwip_accounting_enabled(d.asset_category):
+						stock_asset_account_name = get_asset_account(
+							"capital_work_in_progress_account",
+							asset_category=d.asset_category,
+							company=self.company,
+						)
+					else:
+						stock_asset_account_name = get_asset_category_account(
+							"fixed_asset_account", asset_category=d.asset_category, company=self.company
+						)
 
 					stock_value_diff = (
 						flt(d.base_net_amount)
@@ -719,7 +721,7 @@
 			):
 				warehouse_with_no_account.append(d.warehouse or d.rejected_warehouse)
 
-			if d.is_fixed_asset:
+			if d.is_fixed_asset and d.landed_cost_voucher_amount:
 				self.update_assets(d, d.valuation_rate)
 
 		if warehouse_with_no_account:
@@ -852,11 +854,14 @@
 		)
 
 		for asset in assets:
+			purchase_amount = flt(valuation_rate) * asset.asset_quantity
 			frappe.db.set_value(
-				"Asset", asset.name, "gross_purchase_amount", flt(valuation_rate) * asset.asset_quantity
-			)
-			frappe.db.set_value(
-				"Asset", asset.name, "purchase_receipt_amount", flt(valuation_rate) * asset.asset_quantity
+				"Asset",
+				asset.name,
+				{
+					"gross_purchase_amount": purchase_amount,
+					"purchase_receipt_amount": purchase_amount,
+				},
 			)
 
 	def update_status(self, status):
diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
index 79b8ee3..112c226 100644
--- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
+++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
@@ -140,12 +140,7 @@
 		return query[0][0] if query else None
 
 	def validate_accounts_freeze(self):
-		acc_settings = frappe.db.get_value(
-			"Accounts Settings",
-			"Accounts Settings",
-			["acc_frozen_upto", "frozen_accounts_modifier"],
-			as_dict=1,
-		)
+		acc_settings = frappe.get_cached_doc("Account Settings")
 		if not acc_settings.acc_frozen_upto:
 			return
 		if getdate(self.posting_date) <= getdate(acc_settings.acc_frozen_upto):
@@ -224,7 +219,7 @@
 
 		transaction_status = frappe.db.get_value(self.voucher_type, self.voucher_no, "docstatus")
 		if transaction_status == 2:
-			msg = _("Cannot cancel as processing of cancelled documents is  pending.")
+			msg = _("Cannot cancel as processing of cancelled documents is pending.")
 			msg += "<br>" + _("Please try again in an hour.")
 			frappe.throw(msg, title=_("Pending processing"))
 
diff --git a/erpnext/stock/reorder_item.py b/erpnext/stock/reorder_item.py
index a6f52f3..4cd9cbb 100644
--- a/erpnext/stock/reorder_item.py
+++ b/erpnext/stock/reorder_item.py
@@ -18,7 +18,7 @@
 	if not (frappe.db.a_row_exists("Company") and frappe.db.a_row_exists("Fiscal Year")):
 		return
 
-	if cint(frappe.db.get_value("Stock Settings", None, "auto_indent")):
+	if cint(frappe.db.get_single_value("Stock Settings", "auto_indent")):
 		return _reorder_item()
 
 
@@ -212,7 +212,7 @@
 	if mr_list:
 		if getattr(frappe.local, "reorder_email_notify", None) is None:
 			frappe.local.reorder_email_notify = cint(
-				frappe.db.get_value("Stock Settings", None, "reorder_email_notify")
+				frappe.db.get_single_value("Stock Settings", "reorder_email_notify")
 			)
 
 		if frappe.local.reorder_email_notify:
diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py
index a4fe2ee..ba03ff2 100644
--- a/erpnext/stock/stock_balance.py
+++ b/erpnext/stock/stock_balance.py
@@ -15,8 +15,8 @@
 	frappe.db.auto_commit_on_many_writes = 1
 
 	if allow_negative_stock:
-		existing_allow_negative_stock = frappe.db.get_value(
-			"Stock Settings", None, "allow_negative_stock"
+		existing_allow_negative_stock = frappe.db.get_single_value(
+			"Stock Settings", "allow_negative_stock"
 		)
 		frappe.db.set_single_value("Stock Settings", "allow_negative_stock", 1)
 
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index 4b0e284..f29e7ea 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -338,7 +338,7 @@
 	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", cache=True) or "FIFO"
+			frappe.db.get_single_value("Stock Settings", "valuation_method", cache=True) or "FIFO"
 		)
 	return val_method
 
diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py
index c03fb3e..dc1529b 100644
--- a/erpnext/support/doctype/issue/issue.py
+++ b/erpnext/support/doctype/issue/issue.py
@@ -230,7 +230,7 @@
 def auto_close_tickets():
 	"""Auto-close replied support tickets after 7 days"""
 	auto_close_after_days = (
-		frappe.db.get_value("Support Settings", "Support Settings", "close_issue_after_days") or 7
+		frappe.db.get_single_value("Support Settings", "close_issue_after_days") or 7
 	)
 
 	table = frappe.qb.DocType("Issue")
diff --git a/erpnext/utilities/doctype/video/video.py b/erpnext/utilities/doctype/video/video.py
index 1a9fe19..c3a653a 100644
--- a/erpnext/utilities/doctype/video/video.py
+++ b/erpnext/utilities/doctype/video/video.py
@@ -78,9 +78,8 @@
 
 def update_youtube_data():
 	# Called every 30 minutes via hooks
-	enable_youtube_tracking, frequency = frappe.db.get_value(
-		"Video Settings", "Video Settings", ["enable_youtube_tracking", "frequency"]
-	)
+	enable_youtube_tracking = frappe.db.get_single_value("Video Settings", "enable_youtube_tracking")
+	frequency = frappe.db.get_single_value("Video Settings", "frequency")
 
 	if not cint(enable_youtube_tracking):
 		return