Merge pull request #37644 from bosue/fix_typo_overrridden

chore: Fix typo followup to #37636
diff --git a/.github/workflows/initiate_release.yml b/.github/workflows/initiate_release.yml
index 7034773..e51c194 100644
--- a/.github/workflows/initiate_release.yml
+++ b/.github/workflows/initiate_release.yml
@@ -15,7 +15,7 @@
     strategy:
       fail-fast: false
       matrix:
-        version: ["13", "14"]
+        version: ["13", "14", "15"]
 
     steps:
       - uses: octokit/request-action@v2.x
diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
index 9a7a9a3..7e2f763 100644
--- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
+++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
@@ -18,6 +18,7 @@
 	get_entries,
 )
 from erpnext.accounts.utils import get_account_currency, get_balance_on
+from erpnext.setup.utils import get_exchange_rate
 
 
 class BankReconciliationTool(Document):
@@ -130,7 +131,7 @@
 	bank_transaction = frappe.db.get_values(
 		"Bank Transaction",
 		bank_transaction_name,
-		fieldname=["name", "deposit", "withdrawal", "bank_account"],
+		fieldname=["name", "deposit", "withdrawal", "bank_account", "currency"],
 		as_dict=True,
 	)[0]
 	company_account = frappe.get_value("Bank Account", bank_transaction.bank_account, "account")
@@ -144,29 +145,94 @@
 			)
 
 	company = frappe.get_value("Account", company_account, "company")
+	company_default_currency = frappe.get_cached_value("Company", company, "default_currency")
+	company_account_currency = frappe.get_cached_value("Account", company_account, "account_currency")
+	second_account_currency = frappe.get_cached_value("Account", second_account, "account_currency")
+
+	# determine if multi-currency Journal or not
+	is_multi_currency = (
+		True
+		if company_default_currency != company_account_currency
+		or company_default_currency != second_account_currency
+		or company_default_currency != bank_transaction.currency
+		else False
+	)
 
 	accounts = []
-	# Multi Currency?
-	accounts.append(
-		{
-			"account": second_account,
-			"credit_in_account_currency": bank_transaction.deposit,
-			"debit_in_account_currency": bank_transaction.withdrawal,
-			"party_type": party_type,
-			"party": party,
-			"cost_center": get_default_cost_center(company),
-		}
-	)
+	second_account_dict = {
+		"account": second_account,
+		"account_currency": second_account_currency,
+		"credit_in_account_currency": bank_transaction.deposit,
+		"debit_in_account_currency": bank_transaction.withdrawal,
+		"party_type": party_type,
+		"party": party,
+		"cost_center": get_default_cost_center(company),
+	}
 
-	accounts.append(
-		{
-			"account": company_account,
-			"bank_account": bank_transaction.bank_account,
-			"credit_in_account_currency": bank_transaction.withdrawal,
-			"debit_in_account_currency": bank_transaction.deposit,
-			"cost_center": get_default_cost_center(company),
-		}
-	)
+	company_account_dict = {
+		"account": company_account,
+		"account_currency": company_account_currency,
+		"bank_account": bank_transaction.bank_account,
+		"credit_in_account_currency": bank_transaction.withdrawal,
+		"debit_in_account_currency": bank_transaction.deposit,
+		"cost_center": get_default_cost_center(company),
+	}
+
+	# convert transaction amount to company currency
+	if is_multi_currency:
+		exc_rate = get_exchange_rate(bank_transaction.currency, company_default_currency, posting_date)
+		withdrawal_in_company_currency = flt(exc_rate * abs(bank_transaction.withdrawal))
+		deposit_in_company_currency = flt(exc_rate * abs(bank_transaction.deposit))
+	else:
+		withdrawal_in_company_currency = bank_transaction.withdrawal
+		deposit_in_company_currency = bank_transaction.deposit
+
+	# if second account is of foreign currency, convert and set debit and credit fields.
+	if second_account_currency != company_default_currency:
+		exc_rate = get_exchange_rate(second_account_currency, company_default_currency, posting_date)
+		second_account_dict.update(
+			{
+				"exchange_rate": exc_rate,
+				"credit": deposit_in_company_currency,
+				"debit": withdrawal_in_company_currency,
+				"credit_in_account_currency": flt(deposit_in_company_currency / exc_rate) or 0,
+				"debit_in_account_currency": flt(withdrawal_in_company_currency / exc_rate) or 0,
+			}
+		)
+	else:
+		second_account_dict.update(
+			{
+				"exchange_rate": 1,
+				"credit": deposit_in_company_currency,
+				"debit": withdrawal_in_company_currency,
+				"credit_in_account_currency": deposit_in_company_currency,
+				"debit_in_account_currency": withdrawal_in_company_currency,
+			}
+		)
+
+	# if company account is of foreign currency, convert and set debit and credit fields.
+	if company_account_currency != company_default_currency:
+		exc_rate = get_exchange_rate(company_account_currency, company_default_currency, posting_date)
+		company_account_dict.update(
+			{
+				"exchange_rate": exc_rate,
+				"credit": withdrawal_in_company_currency,
+				"debit": deposit_in_company_currency,
+			}
+		)
+	else:
+		company_account_dict.update(
+			{
+				"exchange_rate": 1,
+				"credit": withdrawal_in_company_currency,
+				"debit": deposit_in_company_currency,
+				"credit_in_account_currency": withdrawal_in_company_currency,
+				"debit_in_account_currency": deposit_in_company_currency,
+			}
+		)
+
+	accounts.append(second_account_dict)
+	accounts.append(company_account_dict)
 
 	journal_entry_dict = {
 		"voucher_type": entry_type,
@@ -176,6 +242,9 @@
 		"cheque_no": reference_number,
 		"mode_of_payment": mode_of_payment,
 	}
+	if is_multi_currency:
+		journal_entry_dict.update({"multi_currency": True})
+
 	journal_entry = frappe.new_doc("Journal Entry")
 	journal_entry.update(journal_entry_dict)
 	journal_entry.set("accounts", accounts)
diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
index 6a47562..4649d23 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
@@ -89,7 +89,6 @@
 		    - 0 > a: Error: already over-allocated
 		- clear means: set the latest transaction date as clearance date
 		"""
-		gl_bank_account = frappe.db.get_value("Bank Account", self.bank_account, "account")
 		remaining_amount = self.unallocated_amount
 		for payment_entry in self.payment_entries:
 			if payment_entry.allocated_amount == 0.0:
diff --git a/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json b/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json
index 9cf2ac6..4ae8135 100644
--- a/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json
+++ b/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json
@@ -30,7 +30,8 @@
   {
    "fieldname": "posting_date",
    "fieldtype": "Date",
-   "label": "Posting Date"
+   "label": "Posting Date",
+   "search_index": 1
   },
   {
    "fieldname": "account_type",
@@ -153,7 +154,7 @@
  "in_create": 1,
  "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2023-06-29 12:24:20.500632",
+ "modified": "2023-10-30 16:15:00.470283",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Payment Ledger Entry",
diff --git a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py
index 1d843ab..71bc498 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py
@@ -14,6 +14,7 @@
 from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
 from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
 from erpnext.accounts.party import get_party_account
+from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
 from erpnext.stock.doctype.item.test_item import create_item
 
 test_dependencies = ["Item"]
@@ -85,26 +86,44 @@
 		self.customer5 = make_customer("_Test PR Customer 5", "EUR")
 
 	def create_account(self):
-		account_name = "Debtors EUR"
-		if not frappe.db.get_value(
-			"Account", filters={"account_name": account_name, "company": self.company}
-		):
-			acc = frappe.new_doc("Account")
-			acc.account_name = account_name
-			acc.parent_account = "Accounts Receivable - _PR"
-			acc.company = self.company
-			acc.account_currency = "EUR"
-			acc.account_type = "Receivable"
-			acc.insert()
-		else:
-			name = frappe.db.get_value(
-				"Account",
-				filters={"account_name": account_name, "company": self.company},
-				fieldname="name",
-				pluck=True,
-			)
-			acc = frappe.get_doc("Account", name)
-		self.debtors_eur = acc.name
+		accounts = [
+			{
+				"attribute": "debtors_eur",
+				"account_name": "Debtors EUR",
+				"parent_account": "Accounts Receivable - _PR",
+				"account_currency": "EUR",
+				"account_type": "Receivable",
+			},
+			{
+				"attribute": "creditors_usd",
+				"account_name": "Payable USD",
+				"parent_account": "Accounts Payable - _PR",
+				"account_currency": "USD",
+				"account_type": "Payable",
+			},
+		]
+
+		for x in accounts:
+			x = frappe._dict(x)
+			if not frappe.db.get_value(
+				"Account", filters={"account_name": x.account_name, "company": self.company}
+			):
+				acc = frappe.new_doc("Account")
+				acc.account_name = x.account_name
+				acc.parent_account = x.parent_account
+				acc.company = self.company
+				acc.account_currency = x.account_currency
+				acc.account_type = x.account_type
+				acc.insert()
+			else:
+				name = frappe.db.get_value(
+					"Account",
+					filters={"account_name": x.account_name, "company": self.company},
+					fieldname="name",
+					pluck=True,
+				)
+				acc = frappe.get_doc("Account", name)
+			setattr(self, x.attribute, acc.name)
 
 	def create_sales_invoice(
 		self, qty=1, rate=100, posting_date=nowdate(), do_not_save=False, do_not_submit=False
@@ -151,6 +170,64 @@
 		payment.posting_date = posting_date
 		return payment
 
+	def create_purchase_invoice(
+		self, qty=1, rate=100, posting_date=nowdate(), do_not_save=False, do_not_submit=False
+	):
+		"""
+		Helper function to populate default values in sales invoice
+		"""
+		pinv = make_purchase_invoice(
+			qty=qty,
+			rate=rate,
+			company=self.company,
+			customer=self.supplier,
+			item_code=self.item,
+			item_name=self.item,
+			cost_center=self.cost_center,
+			warehouse=self.warehouse,
+			debit_to=self.debit_to,
+			parent_cost_center=self.cost_center,
+			update_stock=0,
+			currency="INR",
+			is_pos=0,
+			is_return=0,
+			return_against=None,
+			income_account=self.income_account,
+			expense_account=self.expense_account,
+			do_not_save=do_not_save,
+			do_not_submit=do_not_submit,
+		)
+		return pinv
+
+	def create_purchase_order(
+		self, qty=1, rate=100, posting_date=nowdate(), do_not_save=False, do_not_submit=False
+	):
+		"""
+		Helper function to populate default values in sales invoice
+		"""
+		pord = create_purchase_order(
+			qty=qty,
+			rate=rate,
+			company=self.company,
+			customer=self.supplier,
+			item_code=self.item,
+			item_name=self.item,
+			cost_center=self.cost_center,
+			warehouse=self.warehouse,
+			debit_to=self.debit_to,
+			parent_cost_center=self.cost_center,
+			update_stock=0,
+			currency="INR",
+			is_pos=0,
+			is_return=0,
+			return_against=None,
+			income_account=self.income_account,
+			expense_account=self.expense_account,
+			do_not_save=do_not_save,
+			do_not_submit=do_not_submit,
+		)
+		return pord
+
 	def clear_old_entries(self):
 		doctype_list = [
 			"GL Entry",
@@ -163,13 +240,11 @@
 		for doctype in doctype_list:
 			qb.from_(qb.DocType(doctype)).delete().where(qb.DocType(doctype).company == self.company).run()
 
-	def create_payment_reconciliation(self):
+	def create_payment_reconciliation(self, party_is_customer=True):
 		pr = frappe.new_doc("Payment Reconciliation")
 		pr.company = self.company
-		pr.party_type = (
-			self.party_type if hasattr(self, "party_type") and self.party_type else "Customer"
-		)
-		pr.party = self.customer
+		pr.party_type = "Customer" if party_is_customer else "Supplier"
+		pr.party = self.customer if party_is_customer else self.supplier
 		pr.receivable_payable_account = get_party_account(pr.party_type, pr.party, pr.company)
 		pr.from_invoice_date = pr.to_invoice_date = pr.from_payment_date = pr.to_payment_date = nowdate()
 		return pr
@@ -906,9 +981,13 @@
 		self.assertEqual(pr.allocation[0].difference_amount, 0)
 
 	def test_reconciliation_purchase_invoice_against_return(self):
-		pi = make_purchase_invoice(
-			supplier="_Test Supplier USD", currency="USD", conversion_rate=50
-		).submit()
+		self.supplier = "_Test Supplier USD"
+		pi = self.create_purchase_invoice(qty=5, rate=50, do_not_submit=True)
+		pi.supplier = self.supplier
+		pi.currency = "USD"
+		pi.conversion_rate = 50
+		pi.credit_to = self.creditors_usd
+		pi.save().submit()
 
 		pi_return = frappe.get_doc(pi.as_dict())
 		pi_return.name = None
@@ -918,11 +997,12 @@
 		pi_return.items[0].qty = -pi_return.items[0].qty
 		pi_return.submit()
 
-		self.company = "_Test Company"
-		self.party_type = "Supplier"
-		self.customer = "_Test Supplier USD"
-
-		pr = self.create_payment_reconciliation()
+		pr = frappe.get_doc("Payment Reconciliation")
+		pr.company = self.company
+		pr.party_type = "Supplier"
+		pr.party = self.supplier
+		pr.receivable_payable_account = self.creditors_usd
+		pr.from_invoice_date = pr.to_invoice_date = pr.from_payment_date = pr.to_payment_date = nowdate()
 		pr.get_unreconciled_entries()
 
 		invoices = []
@@ -931,6 +1011,7 @@
 			if invoice.invoice_number == pi.name:
 				invoices.append(invoice.as_dict())
 				break
+
 		for payment in pr.payments:
 			if payment.reference_name == pi_return.name:
 				payments.append(payment.as_dict())
@@ -941,6 +1022,121 @@
 		# Should not raise frappe.exceptions.ValidationError: Total Debit must be equal to Total Credit.
 		pr.reconcile()
 
+	def test_reconciliation_from_purchase_order_to_multiple_invoices(self):
+		"""
+		Reconciling advance payment from PO/SO to multiple invoices should not cause overallocation
+		"""
+
+		self.supplier = "_Test Supplier"
+
+		pi1 = self.create_purchase_invoice(qty=10, rate=100)
+		pi2 = self.create_purchase_invoice(qty=10, rate=100)
+		po = self.create_purchase_order(qty=20, rate=100)
+		pay = get_payment_entry(po.doctype, po.name)
+		# Overpay Puchase Order
+		pay.paid_amount = 3000
+		pay.save().submit()
+		# assert total allocated and unallocated before reconciliation
+		self.assertEqual(
+			(
+				pay.references[0].reference_doctype,
+				pay.references[0].reference_name,
+				pay.references[0].allocated_amount,
+			),
+			(po.doctype, po.name, 2000),
+		)
+		self.assertEqual(pay.total_allocated_amount, 2000)
+		self.assertEqual(pay.unallocated_amount, 1000)
+		self.assertEqual(pay.difference_amount, 0)
+
+		pr = self.create_payment_reconciliation(party_is_customer=False)
+		pr.get_unreconciled_entries()
+
+		self.assertEqual(len(pr.invoices), 2)
+		self.assertEqual(len(pr.payments), 2)
+
+		for x in pr.payments:
+			self.assertEqual((x.reference_type, x.reference_name), (pay.doctype, pay.name))
+
+		invoices = [x.as_dict() for x in pr.invoices]
+		payments = [x.as_dict() for x in pr.payments]
+		pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
+		# partial allocation on pi1 and full allocate on pi2
+		pr.allocation[0].allocated_amount = 100
+		pr.reconcile()
+
+		# assert references and total allocated and unallocated amount
+		pay.reload()
+		self.assertEqual(len(pay.references), 3)
+		self.assertEqual(
+			(
+				pay.references[0].reference_doctype,
+				pay.references[0].reference_name,
+				pay.references[0].allocated_amount,
+			),
+			(po.doctype, po.name, 900),
+		)
+		self.assertEqual(
+			(
+				pay.references[1].reference_doctype,
+				pay.references[1].reference_name,
+				pay.references[1].allocated_amount,
+			),
+			(pi1.doctype, pi1.name, 100),
+		)
+		self.assertEqual(
+			(
+				pay.references[2].reference_doctype,
+				pay.references[2].reference_name,
+				pay.references[2].allocated_amount,
+			),
+			(pi2.doctype, pi2.name, 1000),
+		)
+		self.assertEqual(pay.total_allocated_amount, 2000)
+		self.assertEqual(pay.unallocated_amount, 1000)
+		self.assertEqual(pay.difference_amount, 0)
+
+		pr.get_unreconciled_entries()
+		self.assertEqual(len(pr.invoices), 1)
+		self.assertEqual(len(pr.payments), 2)
+
+		invoices = [x.as_dict() for x in pr.invoices]
+		payments = [x.as_dict() for x in pr.payments]
+		pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
+		pr.reconcile()
+
+		# assert references and total allocated and unallocated amount
+		pay.reload()
+		self.assertEqual(len(pay.references), 3)
+		# PO references should be removed now
+		self.assertEqual(
+			(
+				pay.references[0].reference_doctype,
+				pay.references[0].reference_name,
+				pay.references[0].allocated_amount,
+			),
+			(pi1.doctype, pi1.name, 100),
+		)
+		self.assertEqual(
+			(
+				pay.references[1].reference_doctype,
+				pay.references[1].reference_name,
+				pay.references[1].allocated_amount,
+			),
+			(pi2.doctype, pi2.name, 1000),
+		)
+		self.assertEqual(
+			(
+				pay.references[2].reference_doctype,
+				pay.references[2].reference_name,
+				pay.references[2].allocated_amount,
+			),
+			(pi1.doctype, pi1.name, 900),
+		)
+		self.assertEqual(pay.total_allocated_amount, 2000)
+		self.assertEqual(pay.unallocated_amount, 1000)
+		self.assertEqual(pay.difference_amount, 0)
+
 
 def make_customer(customer_name, currency=None):
 	if not frappe.db.exists("Customer", customer_name):
diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
index 887f1ea..982bdc1 100644
--- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
+++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
@@ -771,19 +771,28 @@
 		)
 
 		create_batch_item_with_batch("_BATCH ITEM Test For Reserve", "TestBatch-RS 02")
-		make_stock_entry(
+		se = make_stock_entry(
 			target="_Test Warehouse - _TC",
 			item_code="_BATCH ITEM Test For Reserve",
-			qty=20,
+			qty=30,
 			basic_rate=100,
-			batch_no="TestBatch-RS 02",
 		)
 
+		se.reload()
+
+		batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle)
+
+		# POS Invoice 1, for the batch without bundle
 		pos_inv1 = create_pos_invoice(
-			item="_BATCH ITEM Test For Reserve", rate=300, qty=15, batch_no="TestBatch-RS 02"
+			item="_BATCH ITEM Test For Reserve", rate=300, qty=15, do_not_save=1
 		)
+
+		pos_inv1.items[0].batch_no = batch_no
 		pos_inv1.save()
 		pos_inv1.submit()
+		pos_inv1.reload()
+
+		self.assertFalse(pos_inv1.items[0].serial_and_batch_bundle)
 
 		batches = get_auto_batch_nos(
 			frappe._dict(
@@ -792,7 +801,24 @@
 		)
 
 		for batch in batches:
-			if batch.batch_no == "TestBatch-RS 02" and batch.warehouse == "_Test Warehouse - _TC":
+			if batch.batch_no == batch_no and batch.warehouse == "_Test Warehouse - _TC":
+				self.assertEqual(batch.qty, 15)
+
+		# POS Invoice 2, for the batch with bundle
+		pos_inv2 = create_pos_invoice(
+			item="_BATCH ITEM Test For Reserve", rate=300, qty=10, batch_no=batch_no
+		)
+		pos_inv2.reload()
+		self.assertTrue(pos_inv2.items[0].serial_and_batch_bundle)
+
+		batches = get_auto_batch_nos(
+			frappe._dict(
+				{"item_code": "_BATCH ITEM Test For Reserve", "warehouse": "_Test Warehouse - _TC"}
+			)
+		)
+
+		for batch in batches:
+			if batch.batch_no == batch_no and batch.warehouse == "_Test Warehouse - _TC":
 				self.assertEqual(batch.qty, 5)
 
 	def test_pos_batch_item_qty_validation(self):
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 97ee5cc..e1f0f19 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -585,7 +585,6 @@
 
 	def get_gl_entries(self, warehouse_account=None):
 		self.auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
-		self.asset_received_but_not_billed = self.get_company_default("asset_received_but_not_billed")
 
 		if self.auto_accounting_for_stock:
 			self.stock_received_but_not_billed = self.get_company_default("stock_received_but_not_billed")
@@ -937,10 +936,11 @@
 					)
 
 					stock_rbnb = (
-						self.asset_received_but_not_billed
+						self.get_company_default("asset_received_but_not_billed")
 						if item.is_fixed_asset
 						else self.stock_received_but_not_billed
 					)
+
 					if not negative_expense_booked_in_pr:
 						gl_entries.append(
 							self.get_gl_dict(
@@ -1664,6 +1664,7 @@
 					"po_detail": "purchase_order_item",
 					"material_request": "material_request",
 					"material_request_item": "material_request_item",
+					"wip_composite_asset": "wip_composite_asset",
 				},
 				"postprocess": update_item,
 				"condition": lambda doc: abs(doc.received_qty) < abs(doc.qty),
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 231b3bf..21cc253 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -2539,6 +2539,37 @@
 		frappe.local.enable_perpetual_inventory["_Test Company 1"] = old_perpetual_inventory
 		frappe.db.set_single_value("Stock Settings", "allow_negative_stock", old_negative_stock)
 
+	def test_sle_for_target_warehouse(self):
+		se = make_stock_entry(
+			item_code="138-CMS Shoe",
+			target="Finished Goods - _TC",
+			company="_Test Company",
+			qty=1,
+			basic_rate=500,
+		)
+
+		si = frappe.copy_doc(test_records[0])
+		si.customer = "_Test Internal Customer 3"
+		si.update_stock = 1
+		si.set_warehouse = "Finished Goods - _TC"
+		si.set_target_warehouse = "Stores - _TC"
+		si.get("items")[0].warehouse = "Finished Goods - _TC"
+		si.get("items")[0].target_warehouse = "Stores - _TC"
+		si.insert()
+		si.submit()
+
+		sles = frappe.get_all(
+			"Stock Ledger Entry", filters={"voucher_no": si.name}, fields=["name", "actual_qty"]
+		)
+
+		# check if both SLEs are created
+		self.assertEqual(len(sles), 2)
+		self.assertEqual(sum(d.actual_qty for d in sles), 0.0)
+
+		# tear down
+		si.cancel()
+		se.cancel()
+
 	def test_internal_transfer_gl_entry(self):
 		si = create_sales_invoice(
 			company="_Test Company with perpetual inventory",
@@ -3662,6 +3693,20 @@
 		allowed_to_interact_with="_Test Company with perpetual inventory",
 	)
 
+	create_internal_customer(
+		customer_name="_Test Internal Customer 3",
+		represents_company="_Test Company",
+		allowed_to_interact_with="_Test Company",
+	)
+
+	account = create_account(
+		account_name="Unrealized Profit",
+		parent_account="Current Liabilities - _TC",
+		company="_Test Company",
+	)
+
+	frappe.db.set_value("Company", "_Test Company", "unrealized_profit_loss_account", account)
+
 	create_internal_supplier(
 		supplier_name="_Test Internal Supplier",
 		represents_company="Wind Power LLC",
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 310e412..16e73ea 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -5,7 +5,7 @@
 from typing import Optional
 
 import frappe
-from frappe import _, msgprint, scrub
+from frappe import _, msgprint, qb, scrub
 from frappe.contacts.doctype.address.address import get_company_address, get_default_address
 from frappe.core.doctype.user_permission.user_permission import get_permitted_documents
 from frappe.model.utils import get_fetch_values
@@ -480,11 +480,19 @@
 
 def get_party_gle_currency(party_type, party, company):
 	def generator():
-		existing_gle_currency = frappe.db.sql(
-			"""select account_currency from `tabGL Entry`
-			where docstatus=1 and company=%(company)s and party_type=%(party_type)s and party=%(party)s
-			limit 1""",
-			{"company": company, "party_type": party_type, "party": party},
+		gl = qb.DocType("GL Entry")
+		existing_gle_currency = (
+			qb.from_(gl)
+			.select(gl.account_currency)
+			.where(
+				(gl.docstatus == 1)
+				& (gl.company == company)
+				& (gl.party_type == party_type)
+				& (gl.party == party)
+				& (gl.is_cancelled == 0)
+			)
+			.limit(1)
+			.run()
 		)
 
 		return existing_gle_currency[0][0] if existing_gle_currency else None
diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
index 4a3d9bb..b6bbd97 100644
--- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
+++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
@@ -32,13 +32,6 @@
 			"label": __("Accounting Dimension"),
 			"fieldtype": "Link",
 			"options": "Accounting Dimension",
-			"get_query": () =>{
-				return {
-					filters: {
-						"disabled": 0
-					}
-				}
-			}
 		},
 		{
 			"fieldname": "fiscal_year",
diff --git a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py
index f2ec31c..eac5426 100644
--- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py
+++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py
@@ -68,7 +68,7 @@
 				tax_amount += entry.credit - entry.debit
 
 			if net_total_map.get(name):
-				if voucher_type == "Journal Entry":
+				if voucher_type == "Journal Entry" and tax_amount and rate:
 					# back calcalute total amount from rate and tax_amount
 					total_amount = grand_total = base_total = tax_amount / (rate / 100)
 				else:
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index f2691fb..1c7052f 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -645,7 +645,7 @@
 		"outstanding_amount": d.outstanding_amount,
 		"allocated_amount": d.allocated_amount,
 		"exchange_rate": d.exchange_rate if d.exchange_gain_loss else payment_entry.get_exchange_rate(),
-		"exchange_gain_loss": d.exchange_gain_loss,  # only populated from invoice in case of advance allocation
+		"exchange_gain_loss": d.exchange_gain_loss,
 		"account": d.account,
 	}
 
@@ -658,22 +658,21 @@
 				existing_row.reference_doctype, existing_row.reference_name
 			).set_total_advance_paid()
 
-		original_row = existing_row.as_dict().copy()
-		existing_row.update(reference_details)
+		if d.allocated_amount <= existing_row.allocated_amount:
+			existing_row.allocated_amount -= d.allocated_amount
 
-		if d.allocated_amount < original_row.allocated_amount:
 			new_row = payment_entry.append("references")
 			new_row.docstatus = 1
 			for field in list(reference_details):
-				new_row.set(field, original_row[field])
+				new_row.set(field, reference_details[field])
 
-			new_row.allocated_amount = original_row.allocated_amount - d.allocated_amount
 	else:
 		new_row = payment_entry.append("references")
 		new_row.docstatus = 1
 		new_row.update(reference_details)
 
 	payment_entry.flags.ignore_validate_update_after_submit = True
+	payment_entry.clear_unallocated_reference_document_rows()
 	payment_entry.setup_party_account_field()
 	payment_entry.set_missing_values()
 	if not skip_ref_details_update_for_pe:
diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js
index f0e4c82..d378fbd 100644
--- a/erpnext/assets/doctype/asset/asset.js
+++ b/erpnext/assets/doctype/asset/asset.js
@@ -9,7 +9,6 @@
 		frm.set_query("item_code", function() {
 			return {
 				"filters": {
-					"disabled": 0,
 					"is_fixed_asset": 1,
 					"is_stock_item": 0
 				}
diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json
index c7d08e2..40f51ab 100644
--- a/erpnext/assets/doctype/asset/asset.json
+++ b/erpnext/assets/doctype/asset/asset.json
@@ -221,11 +221,11 @@
    "read_only": 1
   },
   {
+   "depends_on": "eval:!(doc.is_composite_asset && !doc.capitalized_in)",
    "fieldname": "gross_purchase_amount",
    "fieldtype": "Currency",
    "label": "Gross Purchase Amount",
    "options": "Company:company:default_currency",
-   "read_only": 1,
    "read_only_depends_on": "eval:!doc.is_existing_asset",
    "reqd": 1
   },
@@ -399,6 +399,7 @@
    "fieldtype": "Column Break"
   },
   {
+   "depends_on": "eval:!doc.is_composite_asset && !doc.is_existing_asset",
    "fieldname": "purchase_receipt",
    "fieldtype": "Link",
    "label": "Purchase Receipt",
@@ -416,6 +417,7 @@
    "read_only": 1
   },
   {
+   "depends_on": "eval:!doc.is_composite_asset && !doc.is_existing_asset",
    "fieldname": "purchase_invoice",
    "fieldtype": "Link",
    "label": "Purchase Invoice",
@@ -479,10 +481,11 @@
    "read_only": 1
   },
   {
+   "depends_on": "eval.doc.asset_quantity",
    "fieldname": "asset_quantity",
    "fieldtype": "Int",
    "label": "Asset Quantity",
-   "read_only_depends_on": "eval:!doc.is_existing_asset && !doc.is_composite_asset"
+   "read_only": 1
   },
   {
    "fieldname": "depr_entry_posting_status",
@@ -562,9 +565,14 @@
    "link_doctype": "Journal Entry",
    "link_fieldname": "reference_name",
    "table_fieldname": "accounts"
+  },
+  {
+   "group": "Asset Capitalization",
+   "link_doctype": "Asset Capitalization",
+   "link_fieldname": "target_asset"
   }
  ],
- "modified": "2023-10-03 23:28:26.732269",
+ "modified": "2023-10-27 17:03:46.629617",
  "modified_by": "Administrator",
  "module": "Assets",
  "name": "Asset",
@@ -608,4 +616,4 @@
  "states": [],
  "title_field": "asset_name",
  "track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index 99824b7..d69f5ef 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -1789,6 +1789,7 @@
 			"fixed_asset_account": "_Test Fixed Asset - _TC",
 			"accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC",
 			"depreciation_expense_account": "_Test Depreciations - _TC",
+			"capital_work_in_progress_account": "CWIP Account - _TC",
 		},
 	)
 	asset_category.append(
diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
index 0d6f6b4..728764b 100644
--- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
+++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
@@ -876,12 +876,8 @@
 		"amount",
 	]
 
-	pi_items = frappe.get_all(
-		"Purchase Invoice Item", filters={"wip_composite_asset": asset}, fields=fields
-	)
-
 	pr_items = frappe.get_all(
 		"Purchase Receipt Item", filters={"wip_composite_asset": asset}, fields=fields
 	)
 
-	return pi_items + pr_items
+	return pr_items
diff --git a/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py b/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py
index 23088c9..a33acfd 100644
--- a/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py
+++ b/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py
@@ -13,25 +13,22 @@
 class TestAssetMaintenance(unittest.TestCase):
 	def setUp(self):
 		set_depreciation_settings_in_company()
-		create_asset_data()
-		create_maintenance_team()
-
-	def test_create_asset_maintenance(self):
-		pr = make_purchase_receipt(
+		self.pr = make_purchase_receipt(
 			item_code="Photocopier", qty=1, rate=100000.0, location="Test Location"
 		)
+		self.asset_name = frappe.db.get_value("Asset", {"purchase_receipt": self.pr.name}, "name")
+		self.asset_doc = frappe.get_doc("Asset", self.asset_name)
 
-		asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, "name")
-		asset_doc = frappe.get_doc("Asset", asset_name)
+	def test_create_asset_maintenance_with_log(self):
 		month_end_date = get_last_day(nowdate())
 
 		purchase_date = nowdate() if nowdate() != month_end_date else add_days(nowdate(), -15)
 
-		asset_doc.available_for_use_date = purchase_date
-		asset_doc.purchase_date = purchase_date
+		self.asset_doc.available_for_use_date = purchase_date
+		self.asset_doc.purchase_date = purchase_date
 
-		asset_doc.calculate_depreciation = 1
-		asset_doc.append(
+		self.asset_doc.calculate_depreciation = 1
+		self.asset_doc.append(
 			"finance_books",
 			{
 				"expected_value_after_useful_life": 200,
@@ -42,97 +39,40 @@
 			},
 		)
 
-		asset_doc.save()
+		self.asset_doc.save()
 
-		if not frappe.db.exists("Asset Maintenance", "Photocopier"):
-			asset_maintenance = frappe.get_doc(
-				{
-					"doctype": "Asset Maintenance",
-					"asset_name": "Photocopier",
-					"maintenance_team": "Team Awesome",
-					"company": "_Test Company",
-					"asset_maintenance_tasks": get_maintenance_tasks(),
-				}
-			).insert()
+		asset_maintenance = frappe.get_doc(
+			{
+				"doctype": "Asset Maintenance",
+				"asset_name": self.asset_name,
+				"maintenance_team": "Team Awesome",
+				"company": "_Test Company",
+				"asset_maintenance_tasks": get_maintenance_tasks(),
+			}
+		).insert()
 
-			next_due_date = calculate_next_due_date(nowdate(), "Monthly")
-			self.assertEqual(asset_maintenance.asset_maintenance_tasks[0].next_due_date, next_due_date)
-
-	def test_create_asset_maintenance_log(self):
-		if not frappe.db.exists("Asset Maintenance Log", "Photocopier"):
-			asset_maintenance_log = frappe.get_doc(
-				{
-					"doctype": "Asset Maintenance Log",
-					"asset_maintenance": "Photocopier",
-					"task": "Change Oil",
-					"completion_date": add_days(nowdate(), 2),
-					"maintenance_status": "Completed",
-				}
-			).insert()
-		asset_maintenance = frappe.get_doc("Asset Maintenance", "Photocopier")
-		next_due_date = calculate_next_due_date(asset_maintenance_log.completion_date, "Monthly")
+		next_due_date = calculate_next_due_date(nowdate(), "Monthly")
 		self.assertEqual(asset_maintenance.asset_maintenance_tasks[0].next_due_date, next_due_date)
 
+		asset_maintenance_log = frappe.db.get_value(
+			"Asset Maintenance Log",
+			{"asset_maintenance": asset_maintenance.name, "task_name": "Change Oil"},
+			"name",
+		)
 
-def create_asset_data():
-	if not frappe.db.exists("Asset Category", "Equipment"):
-		create_asset_category()
-
-	if not frappe.db.exists("Location", "Test Location"):
-		frappe.get_doc({"doctype": "Location", "location_name": "Test Location"}).insert()
-
-	if not frappe.db.exists("Item", "Photocopier"):
-		meta = frappe.get_meta("Asset")
-		naming_series = meta.get_field("naming_series").options
-		frappe.get_doc(
+		asset_maintenance_log_doc = frappe.get_doc("Asset Maintenance Log", asset_maintenance_log)
+		asset_maintenance_log_doc.update(
 			{
-				"doctype": "Item",
-				"item_code": "Photocopier",
-				"item_name": "Photocopier",
-				"item_group": "All Item Groups",
-				"company": "_Test Company",
-				"is_fixed_asset": 1,
-				"is_stock_item": 0,
-				"asset_category": "Equipment",
-				"auto_create_assets": 1,
-				"asset_naming_series": naming_series,
+				"completion_date": add_days(nowdate(), 2),
+				"maintenance_status": "Completed",
 			}
-		).insert()
+		)
 
+		asset_maintenance_log_doc.save()
+		next_due_date = calculate_next_due_date(asset_maintenance_log_doc.completion_date, "Monthly")
 
-def create_maintenance_team():
-	user_list = ["marcus@abc.com", "thalia@abc.com", "mathias@abc.com"]
-	if not frappe.db.exists("Role", "Technician"):
-		frappe.get_doc({"doctype": "Role", "role_name": "Technician"}).insert()
-	for user in user_list:
-		if not frappe.db.get_value("User", user):
-			frappe.get_doc(
-				{
-					"doctype": "User",
-					"email": user,
-					"first_name": user,
-					"new_password": "password",
-					"roles": [{"doctype": "Has Role", "role": "Technician"}],
-				}
-			).insert()
-
-	if not frappe.db.exists("Asset Maintenance Team", "Team Awesome"):
-		frappe.get_doc(
-			{
-				"doctype": "Asset Maintenance Team",
-				"maintenance_manager": "marcus@abc.com",
-				"maintenance_team_name": "Team Awesome",
-				"company": "_Test Company",
-				"maintenance_team_members": get_maintenance_team(user_list),
-			}
-		).insert()
-
-
-def get_maintenance_team(user_list):
-	return [
-		{"team_member": user, "full_name": user, "maintenance_role": "Technician"}
-		for user in user_list[1:]
-	]
+		asset_maintenance.reload()
+		self.assertEqual(asset_maintenance.asset_maintenance_tasks[0].next_due_date, next_due_date)
 
 
 def get_maintenance_tasks():
@@ -156,23 +96,6 @@
 	]
 
 
-def create_asset_category():
-	asset_category = frappe.new_doc("Asset Category")
-	asset_category.asset_category_name = "Equipment"
-	asset_category.total_number_of_depreciations = 3
-	asset_category.frequency_of_depreciation = 3
-	asset_category.append(
-		"accounts",
-		{
-			"company_name": "_Test Company",
-			"fixed_asset_account": "_Test Fixed Asset - _TC",
-			"accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC",
-			"depreciation_expense_account": "_Test Depreciations - _TC",
-		},
-	)
-	asset_category.insert()
-
-
 def set_depreciation_settings_in_company():
 	company = frappe.get_doc("Company", "_Test Company")
 	company.accumulated_depreciation_account = "_Test Accumulated Depreciations - _TC"
diff --git a/erpnext/assets/doctype/asset_maintenance/test_records.json b/erpnext/assets/doctype/asset_maintenance/test_records.json
new file mode 100644
index 0000000..8306fad
--- /dev/null
+++ b/erpnext/assets/doctype/asset_maintenance/test_records.json
@@ -0,0 +1,68 @@
+[
+  {
+     "doctype": "Asset Category",
+     "asset_category_name": "Equipment",
+     "total_number_of_depreciations": 3,
+     "frequency_of_depreciation": 3,
+     "accounts": [
+        {
+	  "company_name": "_Test Company",
+	  "fixed_asset_account": "_Test Fixed Asset - _TC",
+	  "accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC",
+	  "depreciation_expense_account": "_Test Depreciations - _TC"
+	}
+     ]
+  },
+  {
+     "doctype": "Location",
+     "location_name": "Test Location"
+  },
+  {
+     "doctype": "Role",
+     "role_name": "Technician"
+  },
+  {
+    "doctype": "User",
+    "email": "marcus@abc.com",
+    "first_name": "marcus@abc.com",
+    "new_password": "password",
+    "roles": [{"doctype": "Has Role", "role": "Technician"}]
+  },
+  {
+    "doctype": "User",
+    "email": "thalia@abc.com",
+    "first_name": "thalia@abc.com",
+    "new_password": "password",
+    "roles": [{"doctype": "Has Role", "role": "Technician"}]
+  },
+  {
+    "doctype": "User",
+    "email": "mathias@abc.com",
+    "first_name": "mathias@abc.com",
+    "new_password": "password",
+    "roles": [{"doctype": "Has Role", "role": "Technician"}]
+  },
+  {
+    "doctype": "Asset Maintenance Team",
+    "maintenance_manager": "marcus@abc.com",
+    "maintenance_team_name": "Team Awesome",
+    "company": "_Test Company",
+    "maintenance_team_members": [
+      {"team_member": "marcus@abc.com", "full_name": "marcus@abc.com", "maintenance_role": "Technician"},
+      {"team_member": "thalia@abc.com", "full_name": "thalia@abc.com", "maintenance_role": "Technician"},
+      {"team_member": "mathias@abc.com", "full_name": "mathias@abc.com", "maintenance_role": "Technician"}
+    ]
+  },
+  {
+    "doctype": "Item",
+    "item_code": "Photocopier",
+    "item_name": "Photocopier",
+    "item_group": "All Item Groups",
+    "company": "_Test Company",
+    "is_fixed_asset": 1,
+    "is_stock_item": 0,
+    "asset_category": "Equipment",
+    "auto_create_assets": 1,
+    "asset_naming_series": "ABC.###"
+  }
+]
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json
index 71cb01b..0599992 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.json
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.json
@@ -16,7 +16,7 @@
   "transaction_settings_section",
   "po_required",
   "pr_required",
-  "over_order_allowance",
+  "blanket_order_allowance",
   "column_break_12",
   "maintain_same_rate",
   "set_landed_cost_based_on_purchase_invoice_rate",
@@ -161,17 +161,17 @@
   },
   {
    "default": "0",
-   "description": "Percentage you are allowed to order more against the Blanket Order Quantity. For example: If you have a Blanket Order of Quantity 100 units. and your Allowance is 10% then you are allowed to order 110 units.",
-   "fieldname": "over_order_allowance",
-   "fieldtype": "Float",
-   "label": "Over Order Allowance (%)"
-  },
-  {
-   "default": "0",
    "description": "While making Purchase Invoice from Purchase Order, use Exchange Rate on Invoice's transaction date rather than inheriting it from Purchase Order. Only applies for Purchase Invoice.",
    "fieldname": "use_transaction_date_exchange_rate",
    "fieldtype": "Check",
    "label": "Use Transaction Date Exchange Rate"
+  },
+  {
+   "default": "0",
+   "description": "Percentage you are allowed to order beyond the Blanket Order quantity.",
+   "fieldname": "blanket_order_allowance",
+   "fieldtype": "Float",
+   "label": "Blanket Order Allowance (%)"
   }
  ],
  "icon": "fa fa-cog",
@@ -179,7 +179,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2023-10-16 16:22:03.201078",
+ "modified": "2023-10-25 14:03:32.520418",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Buying Settings",
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index 465fe96..961697c 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -556,6 +556,9 @@
 					"bom": "bom",
 					"material_request": "material_request",
 					"material_request_item": "material_request_item",
+					"sales_order": "sales_order",
+					"sales_order_item": "sales_order_item",
+					"wip_composite_asset": "wip_composite_asset",
 				},
 				"postprocess": update_item,
 				"condition": lambda doc: abs(doc.received_qty) < abs(doc.qty)
@@ -632,6 +635,7 @@
 			"field_map": {
 				"name": "po_detail",
 				"parent": "purchase_order",
+				"wip_composite_asset": "wip_composite_asset",
 			},
 			"postprocess": update_item,
 			"condition": lambda doc: (doc.base_amount == 0 or abs(doc.billed_amt) < abs(doc.amount)),
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
index 6b29984..b1da97d 100644
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
@@ -86,6 +86,8 @@
   "billed_amt",
   "accounting_details",
   "expense_account",
+  "column_break_fyqr",
+  "wip_composite_asset",
   "manufacture_details",
   "manufacturer",
   "manufacturer_part_no",
@@ -896,13 +898,23 @@
    "fieldname": "apply_tds",
    "fieldtype": "Check",
    "label": "Apply TDS"
+  },
+  {
+   "fieldname": "wip_composite_asset",
+   "fieldtype": "Link",
+   "label": "WIP Composite Asset",
+   "options": "Asset"
+  },
+  {
+   "fieldname": "column_break_fyqr",
+   "fieldtype": "Column Break"
   }
  ],
  "idx": 1,
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2023-09-13 16:22:40.825092",
+ "modified": "2023-10-27 15:50:42.655573",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Purchase Order Item",
@@ -915,4 +927,4 @@
  "sort_order": "DESC",
  "states": [],
  "track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.js b/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.js
index fd73b87..579c0a6 100644
--- a/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.js
+++ b/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.js
@@ -44,11 +44,6 @@
 						}
 					}
 				}
-				else {
-					return {
-						filters: { "disabled": 0 }
-					}
-				}
 			}
 		},
 		{
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index a40976b..a7330ec 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -76,8 +76,6 @@
 					gl_entries = self.get_gl_entries(warehouse_account)
 				make_gl_entries(gl_entries, from_repost=from_repost)
 
-		update_regional_gl_entries(gl_entries, self)
-
 	def validate_serialized_batch(self):
 		from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
 
@@ -1226,8 +1224,3 @@
 		repost_entries.append(repost_entry)
 
 	return repost_entries
-
-
-@erpnext.allow_regional
-def update_regional_gl_entries(gl_list, doc):
-	return
diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
index 11d5f6a..eb99345 100644
--- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
+++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
@@ -7,7 +7,7 @@
 from frappe import _
 from frappe.desk.doctype.tag.tag import add_tag
 from frappe.model.document import Document
-from frappe.utils import add_months, formatdate, getdate, today
+from frappe.utils import add_months, formatdate, getdate, sbool, today
 from plaid.errors import ItemError
 
 from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
@@ -237,8 +237,6 @@
 		deposit = abs(amount)
 		withdrawal = 0.0
 
-	status = "Pending" if transaction["pending"] == True else "Settled"
-
 	tags = []
 	if transaction["category"]:
 		try:
@@ -247,13 +245,14 @@
 		except KeyError:
 			pass
 
-	if not frappe.db.exists("Bank Transaction", dict(transaction_id=transaction["transaction_id"])):
+	if not frappe.db.exists(
+		"Bank Transaction", dict(transaction_id=transaction["transaction_id"])
+	) and not sbool(transaction["pending"]):
 		try:
 			new_transaction = frappe.get_doc(
 				{
 					"doctype": "Bank Transaction",
 					"date": getdate(transaction["date"]),
-					"status": status,
 					"bank_account": bank_account,
 					"deposit": deposit,
 					"withdrawal": withdrawal,
diff --git a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py
index 32f1c36..0135a4f 100644
--- a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py
+++ b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py
@@ -107,7 +107,7 @@
 			allowance = flt(
 				frappe.db.get_single_value(
 					"Selling Settings" if order_doc.doctype == "Sales Order" else "Buying Settings",
-					"over_order_allowance",
+					"blanket_order_allowance",
 				)
 			)
 			for bo_name, item_data in order_data.items():
diff --git a/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py b/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py
index 58f3c95..e9fc25b 100644
--- a/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py
+++ b/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py
@@ -63,7 +63,7 @@
 		po1.currency = get_company_currency(po1.company)
 		self.assertEqual(po1.items[0].qty, (bo.items[0].qty - bo.items[0].ordered_qty))
 
-	def test_over_order_allowance(self):
+	def test_blanket_order_allowance(self):
 		# Sales Order
 		bo = make_blanket_order(blanket_order_type="Selling", quantity=100)
 
@@ -74,7 +74,7 @@
 		so.items[0].qty = 110
 		self.assertRaises(frappe.ValidationError, so.submit)
 
-		frappe.db.set_single_value("Selling Settings", "over_order_allowance", 10)
+		frappe.db.set_single_value("Selling Settings", "blanket_order_allowance", 10)
 		so.submit()
 
 		# Purchase Order
@@ -87,7 +87,7 @@
 		po.items[0].qty = 110
 		self.assertRaises(frappe.ValidationError, po.submit)
 
-		frappe.db.set_single_value("Buying Settings", "over_order_allowance", 10)
+		frappe.db.set_single_value("Buying Settings", "blanket_order_allowance", 10)
 		po.submit()
 
 
diff --git a/erpnext/manufacturing/doctype/job_card/job_card_calendar.js b/erpnext/manufacturing/doctype/job_card/job_card_calendar.js
index f4877fd..9e32085 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card_calendar.js
+++ b/erpnext/manufacturing/doctype/job_card/job_card_calendar.js
@@ -10,8 +10,8 @@
 	},
 	gantt: {
 		field_map: {
-			"start": "started_time",
-			"end": "started_time",
+			"start": "expected_start_date",
+			"end": "expected_end_date",
 			"id": "name",
 			"title": "subject",
 			"color": "color",
diff --git a/erpnext/manufacturing/doctype/job_card/job_card_list.js b/erpnext/manufacturing/doctype/job_card/job_card_list.js
index 5d883bf..99fca95 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card_list.js
+++ b/erpnext/manufacturing/doctype/job_card/job_card_list.js
@@ -1,6 +1,6 @@
 frappe.listview_settings['Job Card'] = {
 	has_indicator_for_draft: true,
-
+	add_fields: ["expected_start_date", "expected_end_date"],
 	get_indicator: function(doc) {
 		const status_colors = {
 			"Work In Progress": "orange",
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index ddd9375..1850d1e 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -1735,7 +1735,10 @@
 			if not item.conversion_factor and item.purchase_uom:
 				item.conversion_factor = get_uom_conversion_factor(item.item_code, item.purchase_uom)
 
-			item_details.setdefault(item.get("item_code"), item)
+			if details := item_details.get(item.get("item_code")):
+				details.qty += item.get("qty")
+			else:
+				item_details.setdefault(item.get("item_code"), item)
 
 	return item_details
 
diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
index 6ab9232..d414988 100644
--- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
@@ -1332,6 +1332,33 @@
 				self.assertTrue(row.warehouse == mrp_warhouse)
 				self.assertEqual(row.quantity, 12)
 
+	def test_mr_qty_for_same_rm_with_different_sub_assemblies(self):
+		from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom
+
+		bom_tree = {
+			"Fininshed Goods2 For SUB Test": {
+				"SubAssembly2 For SUB Test": {"ChildPart2 For SUB Test": {}},
+				"SubAssembly3 For SUB Test": {"ChildPart2 For SUB Test": {}},
+			}
+		}
+
+		parent_bom = create_nested_bom(bom_tree, prefix="")
+		plan = create_production_plan(
+			item_code=parent_bom.item,
+			planned_qty=1,
+			ignore_existing_ordered_qty=1,
+			do_not_submit=1,
+			skip_available_sub_assembly_item=1,
+			warehouse="_Test Warehouse - _TC",
+		)
+
+		plan.get_sub_assembly_items()
+		plan.make_material_request()
+
+		for row in plan.mr_items:
+			if row.item_code == "ChildPart2 For SUB Test":
+				self.assertEqual(row.quantity, 2)
+
 
 def create_production_plan(**args):
 	"""
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index c828c87..0ae7657 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -494,6 +494,7 @@
 						"from_time": row.from_time,
 						"to_time": row.to_time,
 						"time_in_mins": row.time_in_mins,
+						"completed_qty": 0,
 					},
 				)
 
diff --git a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js
index 34edb9d..8729775 100644
--- a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js
+++ b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js
@@ -12,7 +12,7 @@
 			"options": "Item",
 			"get_query": () =>{
 				return {
-					filters: { "disabled": 0, "is_stock_item": 1 }
+					filters: { "is_stock_item": 1 }
 				}
 			}
 		},
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index d59fe0e..d7f33ad 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -316,7 +316,7 @@
 execute:frappe.db.set_single_value("Accounts Settings", "merge_similar_account_heads", 0)
 erpnext.patches.v14_0.update_reference_type_in_journal_entry_accounts
 erpnext.patches.v14_0.update_subscription_details
-execute:frappe.delete_doc_if_exists("Report", "Tax Detail")
+execute:frappe.delete_doc("Report", "Tax Detail", force=True)
 erpnext.patches.v15_0.enable_all_leads
 erpnext.patches.v14_0.update_company_in_ldc
 erpnext.patches.v14_0.set_packed_qty_in_draft_delivery_notes
@@ -340,5 +340,8 @@
 execute:frappe.delete_doc("Page", "welcome-to-erpnext")
 erpnext.patches.v15_0.delete_payment_gateway_doctypes
 erpnext.patches.v14_0.create_accounting_dimensions_in_sales_order_item
+erpnext.patches.v15_0.update_sre_from_voucher_details
+erpnext.patches.v14_0.rename_over_order_allowance_field
+erpnext.patches.v14_0.migrate_delivery_stop_lock_field
 # below migration patch should always run last
-erpnext.patches.v14_0.migrate_gl_to_payment_ledger
\ No newline at end of file
+erpnext.patches.v14_0.migrate_gl_to_payment_ledger
diff --git a/erpnext/patches/v14_0/migrate_delivery_stop_lock_field.py b/erpnext/patches/v14_0/migrate_delivery_stop_lock_field.py
new file mode 100644
index 0000000..c9ec1e1
--- /dev/null
+++ b/erpnext/patches/v14_0/migrate_delivery_stop_lock_field.py
@@ -0,0 +1,7 @@
+import frappe
+from frappe.model.utils.rename_field import rename_field
+
+
+def execute():
+	if frappe.db.has_column("Delivery Stop", "lock"):
+		rename_field("Delivery Stop", "lock", "locked")
diff --git a/erpnext/patches/v14_0/rename_over_order_allowance_field.py b/erpnext/patches/v14_0/rename_over_order_allowance_field.py
new file mode 100644
index 0000000..a81fe88
--- /dev/null
+++ b/erpnext/patches/v14_0/rename_over_order_allowance_field.py
@@ -0,0 +1,15 @@
+from frappe.model.utils.rename_field import rename_field
+
+
+def execute():
+	rename_field(
+		"Buying Settings",
+		"over_order_allowance",
+		"blanket_order_allowance",
+	)
+
+	rename_field(
+		"Selling Settings",
+		"over_order_allowance",
+		"blanket_order_allowance",
+	)
diff --git a/erpnext/patches/v15_0/update_sre_from_voucher_details.py b/erpnext/patches/v15_0/update_sre_from_voucher_details.py
new file mode 100644
index 0000000..06ba553
--- /dev/null
+++ b/erpnext/patches/v15_0/update_sre_from_voucher_details.py
@@ -0,0 +1,18 @@
+import frappe
+from frappe.query_builder.functions import IfNull
+
+
+def execute():
+	columns = frappe.db.get_table_columns("Stock Reservation Entry")
+
+	if set(["against_pick_list", "against_pick_list_item"]).issubset(set(columns)):
+		sre = frappe.qb.DocType("Stock Reservation Entry")
+		(
+			frappe.qb.update(sre)
+			.set(sre.from_voucher_type, "Pick List")
+			.set(sre.from_voucher_no, sre.against_pick_list)
+			.set(sre.from_voucher_detail_no, sre.against_pick_list_item)
+			.where(
+				(IfNull(sre.against_pick_list, "") != "") & (IfNull(sre.against_pick_list_item, "") != "")
+			)
+		).run()
diff --git a/erpnext/public/js/controllers/accounts.js b/erpnext/public/js/controllers/accounts.js
index 3545521..7879173 100644
--- a/erpnext/public/js/controllers/accounts.js
+++ b/erpnext/public/js/controllers/accounts.js
@@ -30,7 +30,6 @@
 							filters: {
 								"account_type": account_type,
 								"company": doc.company,
-								"disabled": 0
 							}
 						}
 					});
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index ba8bc33..3ad18da 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -87,17 +87,13 @@
 				frm.events.get_items_from_internal_purchase_order(frm);
 			}
 
-			if (frm.is_new()) {
+			if (frm.doc.docstatus === 0) {
 				frappe.db.get_single_value("Stock Settings", "enable_stock_reservation").then((value) => {
-					if (value) {
-						frappe.db.get_single_value("Stock Settings", "auto_reserve_stock_for_sales_order").then((value) => {
-							// If `Reserve Stock on Sales Order Submission` is enabled in Stock Settings, set Reserve Stock to 1 else 0.
-							frm.set_value("reserve_stock", value ? 1 : 0);
-						})
-					} else {
-						// If `Stock Reservation` is disabled in Stock Settings, set Reserve Stock to 0 and read only.
+					if (!value) {
+						// If `Stock Reservation` is disabled in Stock Settings, set Reserve Stock to 0 and make the field read-only and hidden.
 						frm.set_value("reserve_stock", 0);
 						frm.set_df_property("reserve_stock", "read_only", 1);
+						frm.set_df_property("reserve_stock", "hidden", 1);
 					}
 				})
 			}
diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json
index a74084d..01d047c 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.json
+++ b/erpnext/selling/doctype/sales_order/sales_order.json
@@ -1631,10 +1631,9 @@
   {
    "default": "0",
    "depends_on": "eval: (doc.docstatus == 0 || doc.reserve_stock)",
-   "description": "If checked, Stock Reservation Entries will be created on <b>Submit</b>",
+   "description": "If checked, Stock will be reserved on <b>Submit</b>",
    "fieldname": "reserve_stock",
    "fieldtype": "Check",
-   "hidden": 1,
    "label": "Reserve Stock",
    "no_copy": 1,
    "print_hide": 1,
@@ -1645,7 +1644,7 @@
  "idx": 105,
  "is_submittable": 1,
  "links": [],
- "modified": "2023-07-24 08:59:11.599875",
+ "modified": "2023-10-18 12:41:54.813462",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Sales Order",
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index b91002e..a40cde1 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -3,6 +3,7 @@
 
 
 import json
+from typing import Literal
 
 import frappe
 import frappe.utils
@@ -534,14 +535,24 @@
 		return False
 
 	@frappe.whitelist()
-	def create_stock_reservation_entries(self, items_details=None, notify=True) -> None:
+	def create_stock_reservation_entries(
+		self,
+		items_details: list[dict] = None,
+		from_voucher_type: Literal["Pick List", "Purchase Receipt"] = None,
+		notify=True,
+	) -> None:
 		"""Creates Stock Reservation Entries for Sales Order Items."""
 
 		from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
 			create_stock_reservation_entries_for_so_items as create_stock_reservation_entries,
 		)
 
-		create_stock_reservation_entries(so=self, items_details=items_details, notify=notify)
+		create_stock_reservation_entries(
+			sales_order=self,
+			items_details=items_details,
+			from_voucher_type=from_voucher_type,
+			notify=notify,
+		)
 
 	@frappe.whitelist()
 	def cancel_stock_reservation_entries(self, sre_list=None, notify=True) -> None:
@@ -748,6 +759,8 @@
 		if target.company_address:
 			target.update(get_fetch_values("Delivery Note", "company_address", target.company_address))
 
+		# set target items names to ensure proper linking with packed_items
+		target.set_new_name()
 		make_packing_list(target)
 
 	def condition(doc):
@@ -820,6 +833,7 @@
 							"postprocess": update_dn_item,
 						}
 					},
+					ignore_permissions=True,
 				)
 
 				dn_item.qty = flt(sre.reserved_qty) * flt(dn_item.get("conversion_factor", 1))
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index 83689a2..d8b5878 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -1784,10 +1784,10 @@
 		si.submit()
 		pe.load_from_db()
 
-		self.assertEqual(pe.references[0].reference_name, si.name)
-		self.assertEqual(pe.references[0].allocated_amount, 200)
-		self.assertEqual(pe.references[1].reference_name, so.name)
-		self.assertEqual(pe.references[1].allocated_amount, 300)
+		self.assertEqual(pe.references[0].reference_name, so.name)
+		self.assertEqual(pe.references[0].allocated_amount, 300)
+		self.assertEqual(pe.references[1].reference_name, si.name)
+		self.assertEqual(pe.references[1].allocated_amount, 200)
 
 	def test_delivered_item_material_request(self):
 		"SO -> MR (Manufacture) -> WO. Test if WO Qty is updated in SO."
diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.json b/erpnext/selling/doctype/selling_settings/selling_settings.json
index 6855012..d6829ce 100644
--- a/erpnext/selling/doctype/selling_settings/selling_settings.json
+++ b/erpnext/selling/doctype/selling_settings/selling_settings.json
@@ -25,7 +25,7 @@
   "so_required",
   "dn_required",
   "sales_update_frequency",
-  "over_order_allowance",
+  "blanket_order_allowance",
   "column_break_5",
   "allow_multiple_items",
   "allow_against_multiple_purchase_orders",
@@ -184,12 +184,6 @@
    "label": "Allow Sales Order Creation For Expired Quotation"
   },
   {
-   "description": "Percentage you are allowed to order more against the Blanket Order Quantity. For example: If you have a Blanket Order of Quantity 100 units. and your Allowance is 10% then you are allowed to order 110 units.",
-   "fieldname": "over_order_allowance",
-   "fieldtype": "Float",
-   "label": "Over Order Allowance (%)"
-  },
-  {
    "default": "0",
    "fieldname": "dont_reserve_sales_order_qty_on_sales_return",
    "fieldtype": "Check",
@@ -200,6 +194,12 @@
    "fieldname": "allow_negative_rates_for_items",
    "fieldtype": "Check",
    "label": "Allow Negative rates for Items"
+  },
+  {
+   "description": "Percentage you are allowed to sell beyond the Blanket Order quantity.",
+   "fieldname": "blanket_order_allowance",
+   "fieldtype": "Float",
+   "label": "Blanket Order Allowance (%)"
   }
  ],
  "icon": "fa fa-cog",
@@ -207,7 +207,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2023-08-14 20:33:05.693667",
+ "modified": "2023-10-25 14:03:03.966701",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Selling Settings",
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 23b93dc..1bd469b 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -40,7 +40,7 @@
 				filters:{
 					'warehouse_type' : 'Transit',
 					'is_group': 0,
-					'company': frm.doc.company
+					'company': frm.doc.company_name
 				}
 			};
 		});
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index d068192..1eecf6d 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -1230,16 +1230,16 @@
 		frappe.db.rollback()
 		frappe.db.set_single_value("Selling Settings", "dont_reserve_sales_order_qty_on_sales_return", 0)
 
-	def non_internal_transfer_delivery_note(self):
+	def test_non_internal_transfer_delivery_note(self):
 		from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
 
 		dn = create_delivery_note(do_not_submit=True)
-		warehouse = create_warehouse("Internal Transfer Warehouse", dn.company)
-		dn.items[0].db_set("target_warehouse", "warehouse")
+		warehouse = create_warehouse("Internal Transfer Warehouse", company=dn.company)
+		dn.items[0].db_set("target_warehouse", warehouse)
 
 		dn.reload()
 
-		self.assertEqual(dn.items[0].target_warehouse, warehouse.name)
+		self.assertEqual(dn.items[0].target_warehouse, warehouse)
 
 		dn.save()
 		dn.reload()
diff --git a/erpnext/stock/doctype/delivery_stop/delivery_stop.json b/erpnext/stock/doctype/delivery_stop/delivery_stop.json
index 5610a81..42560e6 100644
--- a/erpnext/stock/doctype/delivery_stop/delivery_stop.json
+++ b/erpnext/stock/doctype/delivery_stop/delivery_stop.json
@@ -1,815 +1,197 @@
 {
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2017-10-16 16:46:28.166950", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "creation": "2017-10-16 16:46:28.166950",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "customer",
+  "address",
+  "locked",
+  "column_break_6",
+  "customer_address",
+  "visited",
+  "order_information_section",
+  "delivery_note",
+  "cb_order",
+  "grand_total",
+  "section_break_7",
+  "contact",
+  "email_sent_to",
+  "column_break_7",
+  "customer_contact",
+  "section_break_9",
+  "distance",
+  "estimated_arrival",
+  "lat",
+  "column_break_19",
+  "uom",
+  "lng",
+  "more_information_section",
+  "details"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 2, 
-   "fieldname": "customer", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Customer", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Customer", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "columns": 2,
+   "fieldname": "customer",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Customer",
+   "options": "Customer"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "address", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Address Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Address", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "address",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Address Name",
+   "options": "Address",
+   "print_hide": 1,
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "lock", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Lock", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "default": "0",
+   "fieldname": "locked",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Locked"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_6", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "column_break_6",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "customer_address", 
-   "fieldtype": "Small Text", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Customer Address", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "customer_address",
+   "fieldtype": "Small Text",
+   "label": "Customer Address",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 1, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "eval:doc.docstatus==1", 
-   "fieldname": "visited", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Visited", 
-   "length": 0, 
-   "no_copy": 1, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "allow_on_submit": 1,
+   "default": "0",
+   "depends_on": "eval:doc.docstatus==1",
+   "fieldname": "visited",
+   "fieldtype": "Check",
+   "label": "Visited",
+   "no_copy": 1,
+   "print_hide": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "order_information_section", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Order Information", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "order_information_section",
+   "fieldtype": "Section Break",
+   "label": "Order Information"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "delivery_note", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Delivery Note", 
-   "length": 0, 
-   "no_copy": 1, 
-   "options": "Delivery Note", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "delivery_note",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Delivery Note",
+   "no_copy": 1,
+   "options": "Delivery Note",
+   "print_hide": 1,
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "cb_order", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "cb_order",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "grand_total", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Grand Total", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "grand_total",
+   "fieldtype": "Currency",
+   "label": "Grand Total",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_7", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Contact Information", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "section_break_7",
+   "fieldtype": "Section Break",
+   "label": "Contact Information"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "contact", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Contact Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Contact", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "contact",
+   "fieldtype": "Link",
+   "label": "Contact Name",
+   "options": "Contact",
+   "print_hide": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "email_sent_to", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Email sent to", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "email_sent_to",
+   "fieldtype": "Data",
+   "label": "Email sent to",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_7", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "column_break_7",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "customer_contact", 
-   "fieldtype": "Small Text", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Customer Contact", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "customer_contact",
+   "fieldtype": "Small Text",
+   "label": "Customer Contact",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_9", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Dispatch Information", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "section_break_9",
+   "fieldtype": "Section Break",
+   "label": "Dispatch Information"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "distance", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Distance", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "2", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "distance",
+   "fieldtype": "Float",
+   "label": "Distance",
+   "precision": "2",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "estimated_arrival", 
-   "fieldtype": "Datetime", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Estimated Arrival", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "estimated_arrival",
+   "fieldtype": "Datetime",
+   "in_list_view": 1,
+   "label": "Estimated Arrival"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "lat", 
-   "fieldtype": "Float", 
-   "hidden": 1, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Latitude", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "lat",
+   "fieldtype": "Float",
+   "hidden": 1,
+   "label": "Latitude"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_19", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "column_break_19",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "", 
-   "depends_on": "eval:doc.distance", 
-   "fieldname": "uom", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "UOM", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "UOM", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "depends_on": "eval:doc.distance",
+   "fieldname": "uom",
+   "fieldtype": "Link",
+   "label": "UOM",
+   "options": "UOM",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "lng", 
-   "fieldtype": "Float", 
-   "hidden": 1, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Longitude", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "lng",
+   "fieldtype": "Float",
+   "hidden": 1,
+   "label": "Longitude"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "more_information_section", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "More Information", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "more_information_section",
+   "fieldtype": "Section Break",
+   "label": "More Information"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "details", 
-   "fieldtype": "Text Editor", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Details", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
+   "fieldname": "details",
+   "fieldtype": "Text Editor",
+   "label": "Details"
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-10-16 05:23:25.661542", 
- "modified_by": "Administrator", 
- "module": "Stock", 
- "name": "Delivery Stop", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2023-09-29 09:22:53.435161",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Delivery Stop",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "states": [],
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.js b/erpnext/stock/doctype/delivery_trip/delivery_trip.js
index 4a72d77..158bd0c 100755
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.js
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.js
@@ -64,6 +64,11 @@
 				})
 			}, __("Get stops from"));
 		}
+		frm.add_custom_button(__("Delivery Notes"), function () {
+			frappe.set_route("List", "Delivery Note",
+					{'name': ["in", frm.doc.delivery_stops.map((stop) => {return stop.delivery_note;})]}
+			);
+		}, __("View"));
 	},
 
 	calculate_arrival_time: function (frm) {
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
index af2f411..c531a87 100644
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.py
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
@@ -170,7 +170,7 @@
 		for stop in self.delivery_stops:
 			leg.append(stop.customer_address)
 
-			if optimize and stop.lock:
+			if optimize and stop.locked:
 				route_list.append(leg)
 				leg = [stop.customer_address]
 
diff --git a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py
index ed699e3..9b8b46e 100644
--- a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py
+++ b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py
@@ -46,7 +46,7 @@
 		self.assertEqual(len(route_list[0]), 4)
 
 	def test_unoptimized_route_list_with_locks(self):
-		self.delivery_trip.delivery_stops[0].lock = 1
+		self.delivery_trip.delivery_stops[0].locked = 1
 		self.delivery_trip.save()
 		route_list = self.delivery_trip.form_route_list(optimize=False)
 
@@ -65,7 +65,7 @@
 		self.assertEqual(len(route_list[0]), 4)
 
 	def test_optimized_route_list_with_locks(self):
-		self.delivery_trip.delivery_stops[0].lock = 1
+		self.delivery_trip.delivery_stops[0].locked = 1
 		self.delivery_trip.save()
 		route_list = self.delivery_trip.form_route_list(optimize=True)
 
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 9e28199..d8935fe 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -255,7 +255,7 @@
 
 		# add item taxes from template
 		for d in template.get("taxes"):
-			self.append("taxes", {"item_tax_template": d.item_tax_template})
+			self.append("taxes", d)
 
 		# copy re-order table if empty
 		if not self.get("reorder_levels"):
diff --git a/erpnext/stock/doctype/item_price/item_price.js b/erpnext/stock/doctype/item_price/item_price.js
index ce489ff..8a4b4ee 100644
--- a/erpnext/stock/doctype/item_price/item_price.js
+++ b/erpnext/stock/doctype/item_price/item_price.js
@@ -6,7 +6,6 @@
 		frm.set_query("item_code", function() {
 			return {
 				filters: {
-					"disabled": 0,
 					"has_variants": 0
 				}
 			};
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index a51028d..ecdec80 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -401,6 +401,7 @@
 					["uom", "uom"],
 					["sales_order", "sales_order"],
 					["sales_order_item", "sales_order_item"],
+					["wip_composite_asset", "wip_composite_asset"],
 				],
 				"postprocess": update_item,
 				"condition": select_item,
diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.json b/erpnext/stock/doctype/material_request_item/material_request_item.json
index c585d6c..9912be1 100644
--- a/erpnext/stock/doctype/material_request_item/material_request_item.json
+++ b/erpnext/stock/doctype/material_request_item/material_request_item.json
@@ -37,6 +37,10 @@
   "rate",
   "col_break3",
   "amount",
+  "accounting_details_section",
+  "expense_account",
+  "column_break_glru",
+  "wip_composite_asset",
   "manufacture_details",
   "manufacturer",
   "manufacturer_part_no",
@@ -50,11 +54,10 @@
   "lead_time_date",
   "sales_order",
   "sales_order_item",
+  "col_break4",
   "production_plan",
   "material_request_plan_item",
   "job_card_item",
-  "col_break4",
-  "expense_account",
   "section_break_46",
   "page_break"
  ],
@@ -454,13 +457,28 @@
    "label": "Job Card Item",
    "no_copy": 1,
    "print_hide": 1
+  },
+  {
+   "fieldname": "accounting_details_section",
+   "fieldtype": "Section Break",
+   "label": "Accounting Details"
+  },
+  {
+   "fieldname": "column_break_glru",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "wip_composite_asset",
+   "fieldtype": "Link",
+   "label": "WIP Composite Asset",
+   "options": "Asset"
   }
  ],
  "idx": 1,
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2023-05-07 20:23:31.250252",
+ "modified": "2023-10-27 15:53:41.444236",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Material Request Item",
@@ -471,4 +489,4 @@
  "sort_order": "DESC",
  "states": [],
  "track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/pick_list/pick_list.js b/erpnext/stock/doctype/pick_list/pick_list.js
index ae05b80..7cd171e 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.js
+++ b/erpnext/stock/doctype/pick_list/pick_list.js
@@ -265,7 +265,8 @@
 			from_date: moment(frm.doc.creation).format('YYYY-MM-DD'),
 			to_date: to_date,
 			voucher_type: "Sales Order",
-			against_pick_list: frm.doc.name,
+			from_voucher_type: "Pick List",
+			from_voucher_no: frm.doc.name,
 		}
 		frappe.set_route("query-report", "Reserved Stock");
 	}
diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py
index 2fcd102..ed20209 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.py
+++ b/erpnext/stock/doctype/pick_list/pick_list.py
@@ -229,20 +229,27 @@
 	def create_stock_reservation_entries(self, notify=True) -> None:
 		"""Creates Stock Reservation Entries for Sales Order Items against Pick List."""
 
-		from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
-			create_stock_reservation_entries_for_so_items,
-		)
-
-		so_details = {}
+		so_items_details_map = {}
 		for location in self.locations:
 			if location.warehouse and location.sales_order and location.sales_order_item:
-				so_details.setdefault(location.sales_order, []).append(location)
+				item_details = {
+					"name": location.sales_order_item,
+					"item_code": location.item_code,
+					"warehouse": location.warehouse,
+					"qty_to_reserve": (flt(location.picked_qty) - flt(location.stock_reserved_qty)),
+					"from_voucher_no": location.parent,
+					"from_voucher_detail_no": location.name,
+					"serial_and_batch_bundle": location.serial_and_batch_bundle,
+				}
+				so_items_details_map.setdefault(location.sales_order, []).append(item_details)
 
-		if so_details:
-			for so, locations in so_details.items():
+		if so_items_details_map:
+			for so, items_details in so_items_details_map.items():
 				so_doc = frappe.get_doc("Sales Order", so)
-				create_stock_reservation_entries_for_so_items(
-					so=so_doc, items_details=locations, against_pick_list=True, notify=notify
+				so_doc.create_stock_reservation_entries(
+					items_details=items_details,
+					from_voucher_type="Pick List",
+					notify=notify,
 				)
 
 	@frappe.whitelist()
@@ -253,7 +260,9 @@
 			cancel_stock_reservation_entries,
 		)
 
-		cancel_stock_reservation_entries(against_pick_list=self.name, notify=notify)
+		cancel_stock_reservation_entries(
+			from_voucher_type="Pick List", from_voucher_no=self.name, notify=notify
+		)
 
 	def validate_picked_qty(self, data):
 		over_delivery_receipt_allowance = 100 + flt(
diff --git a/erpnext/stock/doctype/pick_list/pick_list_dashboard.py b/erpnext/stock/doctype/pick_list/pick_list_dashboard.py
index 0830fa2..29571a5 100644
--- a/erpnext/stock/doctype/pick_list/pick_list_dashboard.py
+++ b/erpnext/stock/doctype/pick_list/pick_list_dashboard.py
@@ -2,7 +2,7 @@
 	return {
 		"fieldname": "pick_list",
 		"non_standard_fieldnames": {
-			"Stock Reservation Entry": "against_pick_list",
+			"Stock Reservation Entry": "from_voucher_no",
 		},
 		"internal_links": {
 			"Sales Order": ["locations", "sales_order"],
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index d89d805..2a4b6f3 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -263,6 +263,7 @@
 		self.make_gl_entries()
 		self.repost_future_sle_and_gle()
 		self.set_consumed_qty_in_subcontract_order()
+		self.reserve_stock_for_sales_order()
 
 	def check_next_docstatus(self):
 		submit_rv = frappe.db.sql(
@@ -541,17 +542,19 @@
 					d, gl_entries, self.posting_date, d.get("provisional_expense_account")
 				)
 			elif flt(d.qty) and (flt(d.valuation_rate) or self.is_return):
-				is_asset_pr = any(d.is_fixed_asset for d in self.get("items"))
 				remarks = self.get("remarks") or _("Accounting Entry for {0}").format(
-					"Asset" if is_asset_pr else "Stock"
+					"Asset" if d.is_fixed_asset else "Stock"
 				)
 
-				if not (erpnext.is_perpetual_inventory_enabled(self.company) or is_asset_pr):
-					return
+				if not (
+					(erpnext.is_perpetual_inventory_enabled(self.company) and d.item_code in stock_items)
+					or d.is_fixed_asset
+				):
+					continue
 
 				stock_asset_rbnb = (
 					self.get_company_default("asset_received_but_not_billed")
-					if is_asset_pr
+					if d.is_fixed_asset
 					else self.get_company_default("stock_received_but_not_billed")
 				)
 				landed_cost_entries = get_item_account_wise_additional_cost(self.name)
@@ -757,7 +760,36 @@
 			pr_doc = self if (pr == self.name) else frappe.get_doc("Purchase Receipt", pr)
 			update_billing_percentage(pr_doc, update_modified=update_modified)
 
-		self.load_from_db()
+	def reserve_stock_for_sales_order(self):
+		if self.is_return or not cint(
+			frappe.db.get_single_value("Stock Settings", "auto_reserve_stock_for_sales_order_on_purchase")
+		):
+			return
+
+		self.reload()  # reload to get the Serial and Batch Bundle Details
+
+		so_items_details_map = {}
+		for item in self.items:
+			if item.sales_order and item.sales_order_item:
+				item_details = {
+					"name": item.sales_order_item,
+					"item_code": item.item_code,
+					"warehouse": item.warehouse,
+					"qty_to_reserve": item.stock_qty,
+					"from_voucher_no": item.parent,
+					"from_voucher_detail_no": item.name,
+					"serial_and_batch_bundle": item.serial_and_batch_bundle,
+				}
+				so_items_details_map.setdefault(item.sales_order, []).append(item_details)
+
+		if so_items_details_map:
+			for so, items_details in so_items_details_map.items():
+				so_doc = frappe.get_doc("Sales Order", so)
+				so_doc.create_stock_reservation_entries(
+					items_details=items_details,
+					from_voucher_type="Purchase Receipt",
+					notify=True,
+				)
 
 
 def get_stock_value_difference(voucher_no, voucher_detail_no, warehouse):
@@ -1037,6 +1069,7 @@
 					"is_fixed_asset": "is_fixed_asset",
 					"asset_location": "asset_location",
 					"asset_category": "asset_category",
+					"wip_composite_asset": "wip_composite_asset",
 				},
 				"postprocess": update_item,
 				"filter": lambda d: get_pending_qty(d)[0] <= 0
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py
index b3ae7b5..71489fb 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py
@@ -10,6 +10,7 @@
 			"Landed Cost Voucher": "receipt_document",
 			"Auto Repeat": "reference_document",
 			"Purchase Receipt": "return_against",
+			"Stock Reservation Entry": "from_voucher_no",
 		},
 		"internal_links": {
 			"Material Request": ["items", "material_request"],
@@ -18,7 +19,10 @@
 			"Quality Inspection": ["items", "quality_inspection"],
 		},
 		"transactions": [
-			{"label": _("Related"), "items": ["Purchase Invoice", "Landed Cost Voucher", "Asset"]},
+			{
+				"label": _("Related"),
+				"items": ["Purchase Invoice", "Landed Cost Voucher", "Asset", "Stock Reservation Entry"],
+			},
 			{
 				"label": _("Reference"),
 				"items": ["Material Request", "Purchase Order", "Quality Inspection", "Project"],
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index e998b84..146cbff 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -957,6 +957,119 @@
 		pr1.reload()
 		pr1.cancel()
 
+	def test_stock_transfer_from_purchase_receipt(self):
+		from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt
+		from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
+
+		prepare_data_for_internal_transfer()
+
+		customer = "_Test Internal Customer 2"
+		company = "_Test Company with perpetual inventory"
+
+		pr1 = make_purchase_receipt(
+			warehouse="Stores - TCP1", company="_Test Company with perpetual inventory"
+		)
+
+		dn1 = create_delivery_note(
+			item_code=pr1.items[0].item_code,
+			company=company,
+			customer=customer,
+			cost_center="Main - TCP1",
+			expense_account="Cost of Goods Sold - TCP1",
+			qty=5,
+			rate=500,
+			warehouse="Stores - TCP1",
+			target_warehouse="Work In Progress - TCP1",
+		)
+
+		pr = make_inter_company_purchase_receipt(dn1.name)
+		pr.items[0].from_warehouse = "Work In Progress - TCP1"
+		pr.items[0].warehouse = "Stores - TCP1"
+		pr.submit()
+
+		gl_entries = get_gl_entries("Purchase Receipt", pr.name)
+		sl_entries = get_sl_entries("Purchase Receipt", pr.name)
+
+		self.assertFalse(gl_entries)
+
+		expected_sle = {"Work In Progress - TCP1": -5, "Stores - TCP1": 5}
+
+		for sle in sl_entries:
+			self.assertEqual(expected_sle[sle.warehouse], sle.actual_qty)
+
+		pr.cancel()
+
+	def test_stock_transfer_from_purchase_receipt_with_valuation(self):
+		from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt
+		from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
+
+		prepare_data_for_internal_transfer()
+
+		create_warehouse(
+			"_Test Warehouse for Valuation",
+			company="_Test Company with perpetual inventory",
+			properties={"account": "_Test Account Stock In Hand - TCP1"},
+		)
+
+		pr1 = make_purchase_receipt(
+			warehouse="Stores - TCP1",
+			company="_Test Company with perpetual inventory",
+		)
+
+		customer = "_Test Internal Customer 2"
+		company = "_Test Company with perpetual inventory"
+
+		dn1 = create_delivery_note(
+			item_code=pr1.items[0].item_code,
+			company=company,
+			customer=customer,
+			cost_center="Main - TCP1",
+			expense_account="Cost of Goods Sold - TCP1",
+			qty=5,
+			rate=50,
+			warehouse="Stores - TCP1",
+			target_warehouse="_Test Warehouse for Valuation - TCP1",
+		)
+
+		pr = make_inter_company_purchase_receipt(dn1.name)
+		pr.items[0].from_warehouse = "_Test Warehouse for Valuation - TCP1"
+		pr.items[0].warehouse = "Stores - TCP1"
+
+		pr.append(
+			"taxes",
+			{
+				"charge_type": "On Net Total",
+				"account_head": "_Test Account Shipping Charges - TCP1",
+				"category": "Valuation and Total",
+				"cost_center": "Main - TCP1",
+				"description": "Test",
+				"rate": 9,
+			},
+		)
+
+		pr.submit()
+
+		gl_entries = get_gl_entries("Purchase Receipt", pr.name)
+		sl_entries = get_sl_entries("Purchase Receipt", pr.name)
+
+		expected_gle = [
+			["Stock In Hand - TCP1", 272.5, 0.0],
+			["_Test Account Stock In Hand - TCP1", 0.0, 250.0],
+			["_Test Account Shipping Charges - TCP1", 0.0, 22.5],
+		]
+
+		expected_sle = {"_Test Warehouse for Valuation - TCP1": -5, "Stores - TCP1": 5}
+
+		for sle in sl_entries:
+			self.assertEqual(expected_sle[sle.warehouse], sle.actual_qty)
+
+		for i, gle in enumerate(gl_entries):
+			self.assertEqual(gle.account, expected_gle[i][0])
+			self.assertEqual(gle.debit, expected_gle[i][1])
+			self.assertEqual(gle.credit, expected_gle[i][2])
+
+		pr.cancel()
+
 	def test_po_to_pi_and_po_to_pr_worflow_full(self):
 		"""Test following behaviour:
 		- Create PO
diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
index d93d21c..718f007 100644
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -125,7 +125,9 @@
   "dimension_col_break",
   "cost_center",
   "section_break_80",
-  "page_break"
+  "page_break",
+  "sales_order",
+  "sales_order_item"
  ],
  "fields": [
   {
@@ -898,7 +900,8 @@
    "label": "Delivery Note Item",
    "no_copy": 1,
    "print_hide": 1,
-   "read_only": 1
+   "read_only": 1,
+   "search_index": 1
   },
   {
    "collapsible": 1,
@@ -1062,12 +1065,32 @@
    "fieldtype": "Link",
    "label": "WIP Composite Asset",
    "options": "Asset"
+  },
+  {
+   "fieldname": "sales_order",
+   "fieldtype": "Link",
+   "label": "Sales Order",
+   "no_copy": 1,
+   "options": "Sales Order",
+   "print_hide": 1,
+   "read_only": 1,
+   "search_index": 1
+  },
+  {
+   "fieldname": "sales_order_item",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Sales Order Item",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1,
+   "search_index": 1
   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2023-10-03 21:11:50.547261",
+ "modified": "2023-10-30 17:32:24.560337",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Purchase Receipt Item",
@@ -1078,4 +1101,4 @@
  "sort_field": "modified",
  "sort_order": "DESC",
  "states": []
-}
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/quality_inspection_template/test_records.json b/erpnext/stock/doctype/quality_inspection_template/test_records.json
index 980f49a..2da99f6 100644
--- a/erpnext/stock/doctype/quality_inspection_template/test_records.json
+++ b/erpnext/stock/doctype/quality_inspection_template/test_records.json
@@ -1,5 +1,9 @@
 [
  {
+     "doctype": "Quality Inspection Parameter",
+     "parameter" : "_Test Param"
+ },
+ {
      "quality_inspection_template_name" : "_Test Quality Inspection Template",
      "doctype": "Quality Inspection Template",
      "item_quality_inspection_parameter" : [
diff --git a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py
index 1853f45..623e8fa 100644
--- a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py
+++ b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py
@@ -137,8 +137,6 @@
 			item_code="_Test Item",
 			warehouse="_Test Warehouse - _TC",
 			based_on="Item and Warehouse",
-			voucher_type="Sales Invoice",
-			voucher_no="SI-1",
 			posting_date="2021-01-02",
 			posting_time="00:01:00",
 		)
@@ -148,8 +146,6 @@
 		riv1.flags.dont_run_in_test = True
 		riv1.submit()
 		_assert_status(riv1, "Queued")
-		self.assertEqual(riv1.voucher_type, "Sales Invoice")  # traceability
-		self.assertEqual(riv1.voucher_no, "SI-1")
 
 		# newer than existing duplicate - riv1
 		riv2 = frappe.get_doc(riv_args.update({"posting_date": "2021-01-03"}))
diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py
index 96e4a55..f96c184 100644
--- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py
+++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py
@@ -658,7 +658,7 @@
 		if not available_batches:
 			return
 
-		available_batches = get_availabel_batches_qty(available_batches)
+		available_batches = get_available_batches_qty(available_batches)
 		for batch_no in batches:
 			if batch_no not in available_batches or available_batches[batch_no] < 0:
 				self.throw_error_message(
@@ -1074,7 +1074,7 @@
 		return get_auto_batch_nos(kwargs)
 
 
-def get_availabel_batches_qty(available_batches):
+def get_available_batches_qty(available_batches):
 	available_batches_qty = defaultdict(float)
 	for batch in available_batches:
 		available_batches_qty[batch.batch_no] += batch.qty
@@ -1301,6 +1301,7 @@
 		"POS Invoice",
 		fields=[
 			"`tabPOS Invoice Item`.batch_no",
+			"`tabPOS Invoice Item`.qty",
 			"`tabPOS Invoice`.is_return",
 			"`tabPOS Invoice Item`.warehouse",
 			"`tabPOS Invoice Item`.name as child_docname",
@@ -1321,9 +1322,6 @@
 		if pos_invoice.serial_and_batch_bundle
 	]
 
-	if not ids:
-		return {}
-
 	if ids:
 		for d in get_serial_batch_ledgers(kwargs.item_code, docstatus=1, name=ids):
 			key = (d.batch_no, d.warehouse)
@@ -1337,6 +1335,7 @@
 			else:
 				pos_batches[key].qty += d.qty
 
+	# POS invoices having batch without bundle (to handle old POS invoices)
 	for row in pos_invoices:
 		if not row.batch_no:
 			continue
@@ -1346,11 +1345,11 @@
 
 		key = (row.batch_no, row.warehouse)
 		if key in pos_batches:
-			pos_batches[key] -= row.qty * -1 if row.is_return else row.qty
+			pos_batches[key]["qty"] -= row.qty * -1 if row.is_return else row.qty
 		else:
 			pos_batches[key] = frappe._dict(
 				{
-					"qty": (row.qty * -1 if row.is_return else row.qty),
+					"qty": (row.qty * -1 if not row.is_return else row.qty),
 					"warehouse": row.warehouse,
 				}
 			)
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index a2cae7f..c41349f 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -438,31 +438,37 @@
 								item_code.append(item.item_code)
 
 	def validate_fg_completed_qty(self):
-		item_wise_qty = {}
-		if self.purpose == "Manufacture" and self.work_order:
-			for d in self.items:
-				if d.is_finished_item:
-					if self.process_loss_qty:
-						d.qty = self.fg_completed_qty - self.process_loss_qty
+		if self.purpose != "Manufacture":
+			return
 
-					item_wise_qty.setdefault(d.item_code, []).append(d.qty)
+		fg_qty = defaultdict(float)
+		for d in self.items:
+			if d.is_finished_item:
+				fg_qty[d.item_code] += flt(d.qty)
+
+		if not fg_qty:
+			return
 
 		precision = frappe.get_precision("Stock Entry Detail", "qty")
-		for item_code, qty_list in item_wise_qty.items():
-			total = flt(sum(qty_list), precision)
+		fg_item = list(fg_qty.keys())[0]
+		fg_item_qty = flt(fg_qty[fg_item], precision)
+		fg_completed_qty = flt(self.fg_completed_qty, precision)
 
-			if (self.fg_completed_qty - total) > 0 and not self.process_loss_qty:
-				self.process_loss_qty = flt(self.fg_completed_qty - total, precision)
-				self.process_loss_percentage = flt(self.process_loss_qty * 100 / self.fg_completed_qty)
+		for d in self.items:
+			if not fg_qty.get(d.item_code):
+				continue
 
-			if self.process_loss_qty:
-				total += flt(self.process_loss_qty, precision)
+			if (fg_completed_qty - fg_item_qty) > 0:
+				self.process_loss_qty = fg_completed_qty - fg_item_qty
 
-			if self.fg_completed_qty != total:
+			if not self.process_loss_qty:
+				continue
+
+			if fg_completed_qty != (flt(fg_item_qty) + flt(self.process_loss_qty, precision)):
 				frappe.throw(
-					_("The finished product {0} quantity {1} and For Quantity {2} cannot be different").format(
-						frappe.bold(item_code), frappe.bold(total), frappe.bold(self.fg_completed_qty)
-					)
+					_(
+						"Since there is a process loss of {0} units for the finished good {1}, you should reduce the quantity by {0} units for the finished good {1} in the Items Table."
+					).format(frappe.bold(self.process_loss_qty), frappe.bold(d.item_code))
 				)
 
 	def validate_difference_account(self):
@@ -1014,14 +1020,34 @@
 						& (se.docstatus == 1)
 						& (se_detail.item_code == se_item.item_code)
 						& (
-							(se.purchase_order == self.purchase_order)
+							((se.purchase_order == self.purchase_order) & (se_detail.po_detail == se_item.po_detail))
 							if self.subcontract_data.order_doctype == "Purchase Order"
-							else (se.subcontracting_order == self.subcontracting_order)
+							else (
+								(se.subcontracting_order == self.subcontracting_order)
+								& (se_detail.sco_rm_detail == se_item.sco_rm_detail)
+							)
 						)
 					)
-				).run()[0][0]
+				).run()[0][0] or 0
 
-				if flt(total_supplied, precision) > flt(total_allowed, precision):
+				total_returned = 0
+				if self.subcontract_data.order_doctype == "Subcontracting Order":
+					total_returned = (
+						frappe.qb.from_(se)
+						.inner_join(se_detail)
+						.on(se.name == se_detail.parent)
+						.select(Sum(se_detail.transfer_qty))
+						.where(
+							(se.purpose == "Material Transfer")
+							& (se.docstatus == 1)
+							& (se.is_return == 1)
+							& (se_detail.item_code == se_item.item_code)
+							& (se_detail.sco_rm_detail == se_item.sco_rm_detail)
+							& (se.subcontracting_order == self.subcontracting_order)
+						)
+					).run()[0][0] or 0
+
+				if flt(total_supplied - total_returned, precision) > flt(total_allowed, precision):
 					frappe.throw(
 						_("Row {0}# Item {1} cannot be transferred more than {2} against {3} {4}").format(
 							se_item.idx,
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
index 5452692..b3998b7 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
@@ -123,13 +123,6 @@
 				fieldname: "item_code",
 				fieldtype: "Link",
 				options: "Item",
-				"get_query": function() {
-					return {
-						"filters": {
-							"disabled": 0,
-						}
-					};
-				}
 			},
 			{
 				label: __("Ignore Empty Stock"),
diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.js b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.js
index c5df319..f60a037 100644
--- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.js
+++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.js
@@ -92,7 +92,7 @@
 			'qty', 'read_only', frm.doc.has_serial_no
 		);
 
-		frm.set_df_property('sb_entries', 'allow_on_submit', frm.doc.against_pick_list ? 0 : 1);
+		frm.set_df_property('sb_entries', 'allow_on_submit', frm.doc.from_voucher_type == "Pick List" ? 0 : 1);
 	},
 
 	hide_rate_related_fields(frm) {
diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json
index 5c3018f..76cedd4 100644
--- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json
+++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json
@@ -17,8 +17,9 @@
   "voucher_no",
   "voucher_detail_no",
   "column_break_7dxj",
-  "against_pick_list",
-  "against_pick_list_item",
+  "from_voucher_type",
+  "from_voucher_no",
+  "from_voucher_detail_no",
   "section_break_xt4m",
   "stock_uom",
   "column_break_grdt",
@@ -158,7 +159,7 @@
    "oldfieldname": "actual_qty",
    "oldfieldtype": "Currency",
    "print_width": "150px",
-   "read_only_depends_on": "eval: ((doc.reservation_based_on == \"Serial and Batch\") || (doc.against_pick_list) || (doc.delivered_qty > 0))",
+   "read_only_depends_on": "eval: ((doc.reservation_based_on == \"Serial and Batch\") || (doc.from_voucher_type == \"Pick List\") || (doc.delivered_qty > 0))",
    "width": "150px"
   },
   {
@@ -268,27 +269,7 @@
    "label": "Reservation Based On",
    "no_copy": 1,
    "options": "Qty\nSerial and Batch",
-   "read_only_depends_on": "eval: (doc.delivered_qty > 0 || doc.against_pick_list)"
-  },
-  {
-   "fieldname": "against_pick_list",
-   "fieldtype": "Link",
-   "label": "Against Pick List",
-   "no_copy": 1,
-   "options": "Pick List",
-   "print_hide": 1,
-   "read_only": 1,
-   "report_hide": 1,
-   "search_index": 1
-  },
-  {
-   "fieldname": "against_pick_list_item",
-   "fieldtype": "Data",
-   "label": "Against Pick List Item",
-   "no_copy": 1,
-   "print_hide": 1,
-   "read_only": 1,
-   "report_hide": 1
+   "read_only_depends_on": "eval: (doc.delivered_qty > 0 || doc.from_voucher_type == \"Pick List\")"
   },
   {
    "fieldname": "column_break_7dxj",
@@ -297,6 +278,36 @@
   {
    "fieldname": "column_break_grdt",
    "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "from_voucher_type",
+   "fieldtype": "Select",
+   "label": "From Voucher Type",
+   "no_copy": 1,
+   "options": "\nPick List\nPurchase Receipt",
+   "print_hide": 1,
+   "read_only": 1,
+   "report_hide": 1
+  },
+  {
+   "fieldname": "from_voucher_detail_no",
+   "fieldtype": "Data",
+   "label": "From Voucher Detail No",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1,
+   "report_hide": 1
+  },
+  {
+   "fieldname": "from_voucher_no",
+   "fieldtype": "Dynamic Link",
+   "label": "From Voucher No",
+   "no_copy": 1,
+   "options": "from_voucher_type",
+   "print_hide": 1,
+   "read_only": 1,
+   "report_hide": 1,
+   "search_index": 1
   }
  ],
  "hide_toolbar": 1,
@@ -304,7 +315,7 @@
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2023-08-08 17:15:13.317706",
+ "modified": "2023-10-19 16:41:16.545416",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Reservation Entry",
diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py
index 936be3f..6b39965 100644
--- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py
+++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py
@@ -1,6 +1,8 @@
 # Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
 # For license information, please see license.txt
 
+from typing import Literal
+
 import frappe
 from frappe import _
 from frappe.model.document import Document
@@ -113,7 +115,7 @@
 		"""Auto pick Serial and Batch Nos to reserve when `Reservation Based On` is `Serial and Batch`."""
 
 		if (
-			not self.against_pick_list
+			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"))
@@ -239,7 +241,7 @@
 
 					if available_qty_to_reserve <= 0:
 						msg = _(
-							"Row #{0}: Stock not availabe to reserve for Item {1} against Batch {2} in Warehouse {3}."
+							"Row #{0}: Stock not available to reserve for Item {1} against Batch {2} in Warehouse {3}."
 						).format(
 							entry.idx,
 							frappe.bold(self.item_code),
@@ -316,21 +318,24 @@
 	) -> None:
 		"""Updates total reserved qty in the Pick List."""
 
-		if self.against_pick_list and self.against_pick_list_item:
+		if (
+			self.from_voucher_type == "Pick List" and self.from_voucher_no and self.from_voucher_detail_no
+		):
 			sre = frappe.qb.DocType("Stock Reservation Entry")
 			reserved_qty = (
 				frappe.qb.from_(sre)
 				.select(Sum(sre.reserved_qty))
 				.where(
 					(sre.docstatus == 1)
-					& (sre.against_pick_list == self.against_pick_list)
-					& (sre.against_pick_list_item == self.against_pick_list_item)
+					& (sre.from_voucher_type == "Pick List")
+					& (sre.from_voucher_no == self.from_voucher_no)
+					& (sre.from_voucher_detail_no == self.from_voucher_detail_no)
 				)
 			).run(as_list=True)[0][0] or 0
 
 			frappe.db.set_value(
 				"Pick List Item",
-				self.against_pick_list_item,
+				self.from_voucher_detail_no,
 				reserved_qty_field,
 				reserved_qty,
 				update_modified=update_modified,
@@ -365,7 +370,7 @@
 			).format(self.status, self.doctype)
 			frappe.throw(msg)
 
-		if self.against_pick_list:
+		if self.from_voucher_type == "Pick List":
 			msg = _(
 				"Stock Reservation Entry created against a Pick List cannot be updated. If you need to make changes, we recommend canceling the existing entry and creating a new one."
 			)
@@ -761,25 +766,27 @@
 
 
 def create_stock_reservation_entries_for_so_items(
-	so: object,
+	sales_order: object,
 	items_details: list[dict] = None,
-	against_pick_list: bool = False,
+	from_voucher_type: Literal["Pick List", "Purchase Receipt"] = None,
 	notify=True,
 ) -> None:
 	"""Creates Stock Reservation Entries for Sales Order Items."""
 
 	from erpnext.selling.doctype.sales_order.sales_order import get_unreserved_qty
 
-	if not against_pick_list and (
-		so.get("_action") == "submit"
-		and so.set_warehouse
-		and cint(frappe.get_cached_value("Warehouse", so.set_warehouse, "is_group"))
+	if not from_voucher_type and (
+		sales_order.get("_action") == "submit"
+		and sales_order.set_warehouse
+		and cint(frappe.get_cached_value("Warehouse", sales_order.set_warehouse, "is_group"))
 	):
 		return frappe.msgprint(
-			_("Stock cannot be reserved in the group warehouse {0}.").format(frappe.bold(so.set_warehouse))
+			_("Stock cannot be reserved in the group warehouse {0}.").format(
+				frappe.bold(sales_order.set_warehouse)
+			)
 		)
 
-	validate_stock_reservation_settings(so)
+	validate_stock_reservation_settings(sales_order)
 
 	allow_partial_reservation = frappe.db.get_single_value(
 		"Stock Settings", "allow_partial_reservation"
@@ -788,38 +795,36 @@
 	items = []
 	if items_details:
 		for item in items_details:
-			so_item = frappe.get_doc(
-				"Sales Order Item", item.get("sales_order_item") if against_pick_list else item.get("name")
-			)
-			so_item.reserve_stock = 1
+			so_item = frappe.get_doc("Sales Order Item", item.get("name"))
 			so_item.warehouse = item.get("warehouse")
 			so_item.qty_to_reserve = (
-				item.get("picked_qty") - item.get("stock_reserved_qty", 0)
-				if against_pick_list
-				else (flt(item.get("qty_to_reserve")) * flt(so_item.conversion_factor, 1))
+				flt(item.get("qty_to_reserve"))
+				if from_voucher_type in ["Pick List", "Purchase Receipt"]
+				else (
+					flt(item.get("qty_to_reserve"))
+					* (flt(item.get("conversion_factor")) or flt(so_item.conversion_factor) or 1)
+				)
 			)
-
-			if against_pick_list:
-				so_item.pick_list = item.get("parent")
-				so_item.pick_list_item = item.get("name")
-				so_item.pick_list_sbb = item.get("serial_and_batch_bundle")
+			so_item.from_voucher_no = item.get("from_voucher_no")
+			so_item.from_voucher_detail_no = item.get("from_voucher_detail_no")
+			so_item.serial_and_batch_bundle = item.get("serial_and_batch_bundle")
 
 			items.append(so_item)
 
 	sre_count = 0
-	reserved_qty_details = get_sre_reserved_qty_details_for_voucher("Sales Order", so.name)
+	reserved_qty_details = get_sre_reserved_qty_details_for_voucher("Sales Order", sales_order.name)
 
-	for item in items if items_details else so.get("items"):
+	for item in items if items_details else sales_order.get("items"):
 		# Skip if `Reserved Stock` is not checked for the item.
 		if not item.get("reserve_stock"):
 			continue
 
 		# Stock should be reserved from the Pick List if has Picked Qty.
-		if not against_pick_list and flt(item.picked_qty) > 0:
+		if not from_voucher_type == "Pick List" and flt(item.picked_qty) > 0:
 			frappe.throw(
-				_(
-					"Row #{0}: Item {1} has been picked, please create a Stock Reservation from the Pick List."
-				).format(item.idx, frappe.bold(item.item_code))
+				_("Row #{0}: Item {1} has been picked, please reserve stock from the Pick List.").format(
+					item.idx, frappe.bold(item.item_code)
+				)
 			)
 
 		is_stock_item, has_serial_no, has_batch_no = frappe.get_cached_value(
@@ -828,13 +833,15 @@
 
 		# Skip if Non-Stock Item.
 		if not is_stock_item:
-			frappe.msgprint(
-				_("Row #{0}: Stock cannot be reserved for a non-stock Item {1}").format(
-					item.idx, frappe.bold(item.item_code)
-				),
-				title=_("Stock Reservation"),
-				indicator="yellow",
-			)
+			if not from_voucher_type:
+				frappe.msgprint(
+					_("Row #{0}: Stock cannot be reserved for a non-stock Item {1}").format(
+						item.idx, frappe.bold(item.item_code)
+					),
+					title=_("Stock Reservation"),
+					indicator="yellow",
+				)
+
 			item.db_set("reserve_stock", 0)
 			continue
 
@@ -853,13 +860,15 @@
 
 		# Stock is already reserved for the item, notify the user and skip the item.
 		if unreserved_qty <= 0:
-			frappe.msgprint(
-				_("Row #{0}: Stock is already reserved for the Item {1}.").format(
-					item.idx, frappe.bold(item.item_code)
-				),
-				title=_("Stock Reservation"),
-				indicator="yellow",
-			)
+			if not from_voucher_type:
+				frappe.msgprint(
+					_("Row #{0}: Stock is already reserved for the Item {1}.").format(
+						item.idx, frappe.bold(item.item_code)
+					),
+					title=_("Stock Reservation"),
+					indicator="yellow",
+				)
+
 			continue
 
 		available_qty_to_reserve = get_available_qty_to_reserve(item.item_code, item.warehouse)
@@ -867,7 +876,7 @@
 		# No stock available to reserve, notify the user and skip the item.
 		if available_qty_to_reserve <= 0:
 			frappe.msgprint(
-				_("Row #{0}: No available stock to reserve for the Item {1} in Warehouse {2}.").format(
+				_("Row #{0}: Stock not available to reserve for the Item {1} in Warehouse {2}.").format(
 					item.idx, frappe.bold(item.item_code), frappe.bold(item.warehouse)
 				),
 				title=_("Stock Reservation"),
@@ -893,7 +902,9 @@
 
 		# Partial Reservation
 		if qty_to_be_reserved < unreserved_qty:
-			if not item.get("qty_to_reserve") or qty_to_be_reserved < flt(item.get("qty_to_reserve")):
+			if not from_voucher_type and (
+				not item.get("qty_to_reserve") or qty_to_be_reserved < flt(item.get("qty_to_reserve"))
+			):
 				msg = _("Row #{0}: Only {1} available to reserve for the Item {2}").format(
 					item.idx,
 					frappe.bold(str(qty_to_be_reserved / item.conversion_factor) + " " + item.uom),
@@ -915,33 +926,42 @@
 		sre.warehouse = item.warehouse
 		sre.has_serial_no = has_serial_no
 		sre.has_batch_no = has_batch_no
-		sre.voucher_type = so.doctype
-		sre.voucher_no = so.name
+		sre.voucher_type = sales_order.doctype
+		sre.voucher_no = sales_order.name
 		sre.voucher_detail_no = item.name
 		sre.available_qty = available_qty_to_reserve
 		sre.voucher_qty = item.stock_qty
 		sre.reserved_qty = qty_to_be_reserved
-		sre.company = so.company
+		sre.company = sales_order.company
 		sre.stock_uom = item.stock_uom
-		sre.project = so.project
+		sre.project = sales_order.project
 
-		if against_pick_list:
-			sre.against_pick_list = item.pick_list
-			sre.against_pick_list_item = item.pick_list_item
+		if from_voucher_type:
+			sre.from_voucher_type = from_voucher_type
+			sre.from_voucher_no = item.from_voucher_no
+			sre.from_voucher_detail_no = item.from_voucher_detail_no
 
-			if item.pick_list_sbb:
-				sbb = frappe.get_doc("Serial and Batch Bundle", item.pick_list_sbb)
-				sre.reservation_based_on = "Serial and Batch"
-				for entry in sbb.entries:
-					sre.append(
-						"sb_entries",
-						{
-							"serial_no": entry.serial_no,
-							"batch_no": entry.batch_no,
-							"qty": 1 if has_serial_no else abs(entry.qty),
-							"warehouse": entry.warehouse,
-						},
-					)
+		if item.get("serial_and_batch_bundle"):
+			sbb = frappe.get_doc("Serial and Batch Bundle", item.serial_and_batch_bundle)
+			sre.reservation_based_on = "Serial and Batch"
+
+			index, picked_qty = 0, 0
+			while index < len(sbb.entries) and picked_qty < qty_to_be_reserved:
+				entry = sbb.entries[index]
+				qty = 1 if has_serial_no else min(abs(entry.qty), qty_to_be_reserved - picked_qty)
+
+				sre.append(
+					"sb_entries",
+					{
+						"serial_no": entry.serial_no,
+						"batch_no": entry.batch_no,
+						"qty": qty,
+						"warehouse": entry.warehouse,
+					},
+				)
+
+				index += 1
+				picked_qty += qty
 
 		sre.save()
 		sre.submit()
@@ -956,29 +976,37 @@
 	voucher_type: str = None,
 	voucher_no: str = None,
 	voucher_detail_no: str = None,
-	against_pick_list: str = None,
+	from_voucher_type: Literal["Pick List", "Purchase Receipt"] = None,
+	from_voucher_no: str = None,
+	from_voucher_detail_no: str = None,
 	sre_list: list[dict] = None,
 	notify: bool = True,
 ) -> None:
 	"""Cancel Stock Reservation Entries."""
 
-	if not sre_list and against_pick_list:
-		sre = frappe.qb.DocType("Stock Reservation Entry")
-		sre_list = (
-			frappe.qb.from_(sre)
-			.select(sre.name)
-			.where(
-				(sre.docstatus == 1)
-				& (sre.against_pick_list == against_pick_list)
-				& (sre.status.notin(["Delivered", "Cancelled"]))
+	if not sre_list:
+		if voucher_type and voucher_no:
+			sre_list = get_stock_reservation_entries_for_voucher(
+				voucher_type, voucher_no, voucher_detail_no, fields=["name"]
 			)
-			.orderby(sre.creation)
-		).run(as_dict=True)
+		elif from_voucher_type and from_voucher_no:
+			sre = frappe.qb.DocType("Stock Reservation Entry")
+			query = (
+				frappe.qb.from_(sre)
+				.select(sre.name)
+				.where(
+					(sre.docstatus == 1)
+					& (sre.from_voucher_type == from_voucher_type)
+					& (sre.from_voucher_no == from_voucher_no)
+					& (sre.status.notin(["Delivered", "Cancelled"]))
+				)
+				.orderby(sre.creation)
+			)
 
-	elif not sre_list and (voucher_type and voucher_no):
-		sre_list = get_stock_reservation_entries_for_voucher(
-			voucher_type, voucher_no, voucher_detail_no, fields=["name"]
-		)
+			if from_voucher_detail_no:
+				query = query.where(sre.from_voucher_detail_no == from_voucher_detail_no)
+
+			sre_list = query.run(as_dict=True)
 
 	if sre_list:
 		for sre in sre_list:
diff --git a/erpnext/stock/doctype/stock_reservation_entry/test_stock_reservation_entry.py b/erpnext/stock/doctype/stock_reservation_entry/test_stock_reservation_entry.py
index 1168a4e..f4c74a8 100644
--- a/erpnext/stock/doctype/stock_reservation_entry/test_stock_reservation_entry.py
+++ b/erpnext/stock/doctype/stock_reservation_entry/test_stock_reservation_entry.py
@@ -5,6 +5,7 @@
 
 import frappe
 from frappe.tests.utils import FrappeTestCase, change_settings
+from frappe.utils import today
 
 from erpnext.selling.doctype.sales_order.sales_order import create_pick_list, make_delivery_note
 from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
@@ -28,10 +29,6 @@
 			items={self.sr_item.name: self.sr_item}, warehouse=self.warehouse, qty=100
 		)
 
-	def tearDown(self) -> None:
-		cancel_all_stock_reservation_entries()
-		return super().tearDown()
-
 	@change_settings("Stock Settings", {"allow_negative_stock": 0})
 	def test_validate_stock_reservation_settings(self) -> None:
 		from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
@@ -555,8 +552,9 @@
 						(sre.voucher_type == "Sales Order")
 						& (sre.voucher_no == location.sales_order)
 						& (sre.voucher_detail_no == location.sales_order_item)
-						& (sre.against_pick_list == pl.name)
-						& (sre.against_pick_list_item == location.name)
+						& (sre.from_voucher_type == "Pick List")
+						& (sre.from_voucher_no == pl.name)
+						& (sre.from_voucher_detail_no == location.name)
 					)
 				).run(as_dict=True)
 				reserved_sb_details: set[tuple] = {
@@ -567,6 +565,90 @@
 				# Test - 3: Reserved Serial/Batch Nos should be equal to Picked Serial/Batch Nos.
 				self.assertSetEqual(picked_sb_details, reserved_sb_details)
 
+	@change_settings(
+		"Stock Settings",
+		{
+			"allow_negative_stock": 0,
+			"enable_stock_reservation": 1,
+			"auto_reserve_serial_and_batch": 1,
+			"pick_serial_and_batch_based_on": "FIFO",
+			"auto_reserve_stock_for_sales_order_on_purchase": 1,
+		},
+	)
+	def test_stock_reservation_from_purchase_receipt(self):
+		from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
+		from erpnext.selling.doctype.sales_order.sales_order import make_material_request
+		from erpnext.stock.doctype.material_request.material_request import make_purchase_order
+
+		items_details = create_items()
+		create_material_receipt(items_details, self.warehouse, qty=10)
+
+		item_list = []
+		for item_code, properties in items_details.items():
+			item_list.append(
+				{
+					"item_code": item_code,
+					"warehouse": self.warehouse,
+					"qty": randint(11, 100),
+					"uom": properties.stock_uom,
+					"rate": randint(10, 400),
+				}
+			)
+
+		so = make_sales_order(
+			item_list=item_list,
+			warehouse=self.warehouse,
+		)
+
+		mr = make_material_request(so.name)
+		mr.schedule_date = today()
+		mr.save().submit()
+
+		po = make_purchase_order(mr.name)
+		po.supplier = "_Test Supplier"
+		po.save().submit()
+
+		pr = make_purchase_receipt(po.name)
+		pr.save().submit()
+
+		for item in pr.items:
+			sre, status, reserved_qty = frappe.db.get_value(
+				"Stock Reservation Entry",
+				{
+					"from_voucher_type": "Purchase Receipt",
+					"from_voucher_no": pr.name,
+					"from_voucher_detail_no": item.name,
+				},
+				["name", "status", "reserved_qty"],
+			)
+
+			# Test - 1: SRE status should be `Reserved`.
+			self.assertEqual(status, "Reserved")
+
+			# Test - 2: SRE Reserved Qty should be equal to PR Item Qty.
+			self.assertEqual(reserved_qty, item.qty)
+
+			if item.serial_and_batch_bundle:
+				sb_details = frappe.db.get_all(
+					"Serial and Batch Entry",
+					filters={"parent": item.serial_and_batch_bundle},
+					fields=["serial_no", "batch_no", "qty"],
+					as_list=True,
+				)
+				reserved_sb_details = frappe.db.get_all(
+					"Serial and Batch Entry",
+					filters={"parent": sre},
+					fields=["serial_no", "batch_no", "qty"],
+					as_list=True,
+				)
+
+				# Test - 3: Reserved Serial/Batch Nos should be equal to PR Item Serial/Batch Nos.
+				self.assertEqual(set(sb_details), set(reserved_sb_details))
+
+	def tearDown(self) -> None:
+		cancel_all_stock_reservation_entries()
+		return super().tearDown()
+
 
 def create_items() -> dict:
 	items_properties = [
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.json b/erpnext/stock/doctype/stock_settings/stock_settings.json
index 2052daa..1228290 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.json
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.json
@@ -38,8 +38,8 @@
   "stock_reservation_tab",
   "enable_stock_reservation",
   "column_break_rx3e",
-  "auto_reserve_stock_for_sales_order",
   "allow_partial_reservation",
+  "auto_reserve_stock_for_sales_order_on_purchase",
   "serial_and_batch_reservation_section",
   "auto_reserve_serial_and_batch",
   "serial_and_batch_item_settings_tab",
@@ -65,8 +65,7 @@
   "stock_frozen_upto_days",
   "column_break_26",
   "role_allowed_to_create_edit_back_dated_transactions",
-  "stock_auth_role",
-  "section_break_plhx"
+  "stock_auth_role"
  ],
  "fields": [
   {
@@ -356,7 +355,7 @@
   {
    "default": "1",
    "depends_on": "eval: doc.enable_stock_reservation",
-   "description": "If enabled, <b>Partial Stock Reservation Entries</b> can be created. For example, If you have a Sales Order of 100 units and the Available Stock is 90 units then a Stock Reservation Entry will be created for 90 units. ",
+   "description": "Partial stock can be reserved. For example, If you have a Sales Order of 100 units and the Available Stock is 90 units then a Stock Reservation Entry will be created for 90 units. ",
    "fieldname": "allow_partial_reservation",
    "fieldtype": "Check",
    "label": "Allow Partial Reservation"
@@ -383,7 +382,7 @@
   {
    "default": "1",
    "depends_on": "eval: doc.enable_stock_reservation",
-   "description": "If enabled, Serial and Batch Nos will be auto-reserved based on <b>Pick Serial / Batch Based On</b>",
+   "description": "Serial and Batch Nos will be auto-reserved based on <b>Pick Serial / Batch Based On</b>",
    "fieldname": "auto_reserve_serial_and_batch",
    "fieldtype": "Check",
    "label": "Auto Reserve Serial and Batch Nos"
@@ -394,14 +393,6 @@
    "label": "Serial and Batch Reservation"
   },
   {
-   "default": "0",
-   "depends_on": "eval: doc.enable_stock_reservation",
-   "description": "If enabled, <b>Stock Reservation Entries</b> will be created on submission of <b>Sales Order</b>",
-   "fieldname": "auto_reserve_stock_for_sales_order",
-   "fieldtype": "Check",
-   "label": "Auto Reserve Stock for Sales Order"
-  },
-  {
    "fieldname": "conversion_factor_section",
    "fieldtype": "Section Break",
    "label": "Stock UOM Quantity"
@@ -421,6 +412,14 @@
    "fieldname": "allow_to_edit_stock_uom_qty_for_purchase",
    "fieldtype": "Check",
    "label": "Allow to Edit Stock UOM Qty for Purchase Documents"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval: doc.enable_stock_reservation",
+   "description": "Stock will be reserved on submission of <b>Purchase Receipt</b> created against Material Receipt for Sales Order.",
+   "fieldname": "auto_reserve_stock_for_sales_order_on_purchase",
+   "fieldtype": "Check",
+   "label": "Auto Reserve Stock for Sales Order on Purchase"
   }
  ],
  "icon": "icon-cog",
@@ -428,7 +427,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2023-10-01 14:22:36.136111",
+ "modified": "2023-10-18 12:35:30.068799",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Settings",
@@ -453,4 +452,4 @@
  "sort_order": "ASC",
  "states": [],
  "track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 8c6fd84..e29fc88 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -268,7 +268,7 @@
 	if not item:
 		item = frappe.get_doc("Item", args.get("item_code"))
 
-	if item.variant_of:
+	if item.variant_of and not item.taxes:
 		item.update_template_tables()
 
 	item_defaults = get_item_defaults(item.name, args.company)
@@ -330,8 +330,12 @@
 			),
 			"expense_account": expense_account
 			or get_default_expense_account(args, item_defaults, item_group_defaults, brand_defaults),
-			"discount_account": get_default_discount_account(args, item_defaults),
-			"provisional_expense_account": get_provisional_account(args, item_defaults),
+			"discount_account": get_default_discount_account(
+				args, item_defaults, item_group_defaults, brand_defaults
+			),
+			"provisional_expense_account": get_provisional_account(
+				args, item_defaults, item_group_defaults, brand_defaults
+			),
 			"cost_center": get_default_cost_center(
 				args, item_defaults, item_group_defaults, brand_defaults
 			),
@@ -686,12 +690,22 @@
 	)
 
 
-def get_provisional_account(args, item):
-	return item.get("default_provisional_account") or args.default_provisional_account
+def get_provisional_account(args, item, item_group, brand):
+	return (
+		item.get("default_provisional_account")
+		or item_group.get("default_provisional_account")
+		or brand.get("default_provisional_account")
+		or args.default_provisional_account
+	)
 
 
-def get_default_discount_account(args, item):
-	return item.get("default_discount_account") or args.discount_account
+def get_default_discount_account(args, item, item_group, brand):
+	return (
+		item.get("default_discount_account")
+		or item_group.get("default_discount_account")
+		or brand.get("default_discount_account")
+		or args.discount_account
+	)
 
 
 def get_default_deferred_account(args, item, fieldname=None):
diff --git a/erpnext/stock/report/reserved_stock/reserved_stock.js b/erpnext/stock/report/reserved_stock/reserved_stock.js
index 2199f52..6872741 100644
--- a/erpnext/stock/report/reserved_stock/reserved_stock.js
+++ b/erpnext/stock/report/reserved_stock/reserved_stock.js
@@ -91,16 +91,30 @@
 			},
 		},
 		{
-			fieldname: "against_pick_list",
-			label: __("Against Pick List"),
+			fieldname: "from_voucher_type",
+			label: __("From Voucher Type"),
 			fieldtype: "Link",
-			options: "Pick List",
+			options: "DocType",
+			get_query: () => ({
+				filters: {
+					name: ["in", ["Pick List", "Purchase Receipt"]],
+				}
+			}),
+		},
+		{
+			fieldname: "from_voucher_no",
+			label: __("From Voucher No"),
+			fieldtype: "Dynamic Link",
+			options: "from_voucher_type",
 			get_query: () => ({
 				filters: {
 					docstatus: 1,
 					company: frappe.query_report.get_filter_value("company"),
 				},
 			}),
+			get_options: function () {
+				return frappe.query_report.get_filter_value("from_voucher_type");
+			},
 		},
 		{
 			fieldname: "reservation_based_on",
diff --git a/erpnext/stock/report/reserved_stock/reserved_stock.py b/erpnext/stock/report/reserved_stock/reserved_stock.py
index d93ee1c..21ce203 100644
--- a/erpnext/stock/report/reserved_stock/reserved_stock.py
+++ b/erpnext/stock/report/reserved_stock/reserved_stock.py
@@ -44,7 +44,8 @@
 			(sre.available_qty - sre.reserved_qty).as_("available_qty"),
 			sre.voucher_type,
 			sre.voucher_no,
-			sre.against_pick_list,
+			sre.from_voucher_type,
+			sre.from_voucher_no,
 			sre.name.as_("stock_reservation_entry"),
 			sre.status,
 			sre.project,
@@ -65,7 +66,8 @@
 		"warehouse",
 		"voucher_type",
 		"voucher_no",
-		"against_pick_list",
+		"from_voucher_type",
+		"from_voucher_no",
 		"reservation_based_on",
 		"status",
 		"project",
@@ -142,7 +144,6 @@
 			"fieldname": "voucher_type",
 			"label": _("Voucher Type"),
 			"fieldtype": "Data",
-			"options": "Warehouse",
 			"width": 110,
 		},
 		{
@@ -153,11 +154,17 @@
 			"width": 120,
 		},
 		{
-			"fieldname": "against_pick_list",
-			"label": _("Against Pick List"),
-			"fieldtype": "Link",
-			"options": "Pick List",
-			"width": 130,
+			"fieldname": "from_voucher_type",
+			"label": _("From Voucher Type"),
+			"fieldtype": "Data",
+			"width": 110,
+		},
+		{
+			"fieldname": "from_voucher_no",
+			"label": _("From Voucher No"),
+			"fieldtype": "Dynamic Link",
+			"options": "from_voucher_type",
+			"width": 120,
 		},
 		{
 			"fieldname": "stock_reservation_entry",
diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js
index f2b395a..587a3b4 100644
--- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js
+++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js
@@ -107,7 +107,7 @@
 	get_materials_from_supplier: function (frm) {
 		let sco_rm_details = [];
 
-		if (frm.doc.status != "Closed" && frm.doc.supplied_items && frm.doc.per_received > 0) {
+		if (frm.doc.status != "Closed" && frm.doc.supplied_items) {
 			frm.doc.supplied_items.forEach(d => {
 				if (d.total_supplied_qty > 0 && d.total_supplied_qty != d.consumed_qty) {
 					sco_rm_details.push(d.name);
@@ -193,7 +193,7 @@
 	}
 
 	has_unsupplied_items() {
-		return this.frm.doc['supplied_items'].some(item => item.required_qty > item.supplied_qty);
+		return this.frm.doc['supplied_items'].some(item => item.required_qty > (item.supplied_qty - item.returned_qty));
 	}
 
 	make_subcontracting_receipt() {
diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js
index d4daacd..f96823b 100644
--- a/erpnext/support/doctype/issue/issue.js
+++ b/erpnext/support/doctype/issue/issue.js
@@ -1,13 +1,6 @@
 frappe.ui.form.on("Issue", {
 	onload: function(frm) {
 		frm.email_field = "raised_by";
-		frm.set_query("customer", function () {
-			return {
-				filters: {
-					"disabled": 0
-				}
-			};
-		});
 
 		frappe.db.get_value("Support Settings", {name: "Support Settings"},
 			["allow_resetting_service_level_agreement", "track_service_level_agreement"], (r) => {
diff --git a/erpnext/templates/pages/projects.html b/erpnext/templates/pages/projects.html
index 9fe4338..3b8698f 100644
--- a/erpnext/templates/pages/projects.html
+++ b/erpnext/templates/pages/projects.html
@@ -14,18 +14,16 @@
 
 {% block style %}
   <style>
-    {
-      % include "templates/includes/projects.css"%
-    }
+    {% include "templates/includes/projects.css" %}
   </style>
 {% endblock %}
 
 {% block page_content %}
   <div class="web-list-item transaction-list-item">
     <div class="row align-items-center">
-      <div class="col-sm-4 "><b>Status: {{ doc.status }}</b></div>
-      <div class="col-sm-4 "><b>Progress: {{ doc.percent_complete }}%</b></div>
-      <div class="col-sm-4 "><b>Hours Spent: {{ doc.actual_time | round }}</b></div>
+      <div class="col-sm-4 "><b>{{ _("Status") }}: {{ _(doc.status) }}</b></div>
+      <div class="col-sm-4 "><b>{{ _("Progress") }}: {{ doc.get_formatted("percent_complete") }}</b></div>
+      <div class="col-sm-4 "><b>{{ _("Hours Spent") }}: {{ doc.get_formatted("actual_time") }}</b></div>
     </div>
   </div>
 
@@ -34,7 +32,7 @@
   <hr>
 
   <div class="row align-items-center">
-    <div class="col-sm-6 my-account-header"> <h4>Tasks</h4></div>
+    <div class="col-sm-6 my-account-header"> <h4>{{ _("Tasks") }}</h4></div>
     <div class="col-sm-6 text-right">
       <a class="btn btn-secondary btn-light btn-sm" href='/tasks/new?project={{ doc.project_name }}'>{{ _("New task") }}</a>
     </div>
@@ -44,39 +42,39 @@
     <div class="result">
       <div class="web-list-item transaction-list-item">
         <div class="row align-items-center">
-          <div class="col-sm-4"><b>Tasks</b></div>
-          <div class="col-sm-2"><b>Status</b></div>
-          <div class="col-sm-2"><b>End Date</b></div>
-          <div class="col-sm-2"><b>Assignment</b></div>
-          <div class="col-sm-2"><b>Modified On</b></div>
+          <div class="col-sm-4"><b>{{ _("Tasks") }}</b></div>
+          <div class="col-sm-2"><b>{{ _("Status") }}</b></div>
+          <div class="col-sm-2"><b>{{ _("End Date") }}</b></div>
+          <div class="col-sm-2"><b>{{ _("Assignment") }}</b></div>
+          <div class="col-sm-2"><b>{{ _("Modified On") }}</b></div>
         </div>
       </div>
       {% include "erpnext/templates/includes/projects/project_tasks.html" %}
     </div>
   </div>
   {% else %}
-    {{ empty_state('Task')}}
+    {{ empty_state(_("Task")) }}
   {% endif %}
 
-  <h4 class="my-account-header">Timesheets</h4>
+  <h4 class="my-account-header">{{ _("Timesheets") }}</h4>
   {% if doc.timesheets %}
     <div class="website-list">
       <div class="result">
         <div class="web-list-item transaction-list-item">
           <div class="row align-items-center">
-            <div class="col-xs-2"><b>Timesheet</b></div>
-            <div class="col-xs-2"><b>Status</b></div>
-            <div class="col-xs-2"><b>From</b></div>
-            <div class="col-xs-2"><b>To</b></div>
-            <div class="col-xs-2"><b>Modified By</b></div>
-            <div class="col-xs-2"><b>Modified On</b></div>
+            <div class="col-xs-2"><b>{{ _("Timesheet") }}</b></div>
+            <div class="col-xs-2"><b>{{ _("Status") }}</b></div>
+            <div class="col-xs-2"><b>{{ _("From") }}</b></div>
+            <div class="col-xs-2"><b>{{ _("To") }}</b></div>
+            <div class="col-xs-2"><b>{{ _("Modified By") }}</b></div>
+            <div class="col-xs-2"><b>{{ _("Modified On") }}</b></div>
           </div>
         </div>
       {% include "erpnext/templates/includes/projects/project_timesheets.html" %}
       </div>
     </div>
   {% else %}
-    {{ empty_state('Timesheet')}}
+    {{ empty_state(_("Timesheet")) }}
   {% endif %}
 
   {% if doc.attachments %}
@@ -113,7 +111,7 @@
 
 {% macro progress_bar(percent_complete) %}
 {% if percent_complete %}
-  <span class="small py-2">Project Progress:</span>
+  <span class="small py-2">{{ _("Project Progress:") }}</span>
   <div class="progress progress-hg" style="height: 15px;">
     <div
       class="progress-bar progress-bar-{{ 'warning' if percent_complete|round < 100 else 'success' }} active"\
@@ -133,7 +131,7 @@
         <div>
           <img src="/assets/frappe/images/ui-states/list-empty-state.svg" alt="Generic Empty State" class="null-state">
         </div>
-        <p>You haven't created a {{ section_name }} yet</p>
+        <p>{{ _("You haven't created a {0} yet").format(section_name) }}</p>
       </div>
     </div>
   </div>