Merge pull request #39835 from s-aga-r/FIX-9623

fix: create SBB for `transfer_qty` in SE
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/br_planilha_de_contas.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/br_planilha_de_contas.json
index a1dbddc..45be1e3 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/br_planilha_de_contas.json
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/br_planilha_de_contas.json
@@ -56,7 +56,9 @@
                     "Constru\u00e7\u00f5es em Andamento de Im\u00f3veis Destinados \u00e0 Venda": {}, 
                     "Estoques Destinados \u00e0 Doa\u00e7\u00e3o": {}, 
                     "Im\u00f3veis Destinados \u00e0 Venda": {}, 
-                    "Insumos (materiais diretos)": {}, 
+                    "Insumos (materiais diretos)": {
+                        "account_type": "Stock"
+                    }, 
                     "Insumos Agropecu\u00e1rios": {}, 
                     "Mercadorias para Revenda": {}, 
                     "Outras 11": {}, 
@@ -146,6 +148,65 @@
             "root_type": "Asset"
         }, 
         "CUSTOS DE PRODU\u00c7\u00c3O": {
+            "CUSTO DOS PRODUTOS E SERVI\u00c7OS VENDIDOS": {
+                "CUSTO DOS PRODUTOS VENDIDOS": {
+                    "CUSTO DOS PRODUTOS VENDIDOS PARA AS DEMAIS ATIVIDADES": {
+                        "Custos dos Produtos Vendidos em Geral": {
+                            "account_type": "Cost of Goods Sold"
+                        }, 
+                        "Outros Custos 4": {}, 
+                        "account_type": "Cost of Goods Sold"
+                    }, 
+                    "CUSTO DOS PRODUTOS VENDIDOS PARA ASSIST\u00caNCIA SOCIAL": {
+                        "Custos dos Produtos para Assist\u00eancia Social - Gratuidades": {}, 
+                        "Custos dos Produtos para Assist\u00eancia Social - Vendidos": {}, 
+                        "Outras": {}
+                    }, 
+                    "CUSTO DOS PRODUTOS VENDIDOS PARA EDUCA\u00c7\u00c3O": {
+                        "Custos dos Produtos para Educa\u00e7\u00e3o - Gratuidades": {}, 
+                        "Custos dos Produtos para Educa\u00e7\u00e3o - Vendidos": {}, 
+                        "Outros Custos 6": {}
+                    }, 
+                    "CUSTO DOS PRODUTOS VENDIDOS PARA SA\u00daDE": {
+                        "Custos dos Produtos para Sa\u00fade - Gratuidades": {}, 
+                        "Custos dos Produtos para Sa\u00fade \u2013 Vendidos": {}, 
+                        "Outros Custos 5": {}
+                    }, 
+                    "account_type": "Cost of Goods Sold"
+                }, 
+                "CUSTO DOS SERVI\u00c7OS PRESTADOS": {
+                    "CUSTO DOS SERVI\u00c7OS PRESTADOS PARA AS DEMAIS ATIVIDADES": {
+                        "Custo dos Servi\u00e7os Prestados em Geral": {}, 
+                        "Outros Custos": {}
+                    }, 
+                    "CUSTO DOS SERVI\u00c7OS PRESTADOS PARA ASSIST\u00caNCIA SOCIAL": {
+                        "Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias": {}, 
+                        "Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es 1": {}, 
+                        "Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas 1": {}, 
+                        "Custo dos Servi\u00e7os Prestados a Gratuidade 1": {}, 
+                        "Custo dos Servi\u00e7os Prestados a Pacientes Particulares": {}, 
+                        "Outros Custos 2": {}
+                    }, 
+                    "CUSTO DOS SERVI\u00c7OS PRESTADOS PARA EDUCA\u00c7\u00c3O": {
+                        "Custo dos Servi\u00e7os Prestados a Alunos N\u00e3o Bolsistas": {}, 
+                        "Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias (Exceto PROUNI)": {}, 
+                        "Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es": {}, 
+                        "Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas": {}, 
+                        "Custo dos Servi\u00e7os Prestados a Gratuidade": {}, 
+                        "Custo dos Servi\u00e7os Prestados ao PROUNI": {}, 
+                        "Outros Custos 1": {}
+                    }, 
+                    "CUSTO DOS SERVI\u00c7OS PRESTADOS PARA SA\u00daDE": {
+                        "Custo dos Servi\u00e7os Prestados a Conv\u00eanios SUS": {}, 
+                        "Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias 1": {}, 
+                        "Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es 2": {}, 
+                        "Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas 2": {}, 
+                        "Custo dos Servi\u00e7os Prestados a Gratuidade 2": {}, 
+                        "Custo dos Servi\u00e7os Prestados a Pacientes Particulares 1": {}, 
+                        "Outros Custos 3": {}
+                    }
+                }
+            }, 
             "CUSTO DOS BENS E SERVI\u00c7OS PRODUZIDOS": {
                 "CUSTO DOS PRODUTOS DE FABRICA\u00c7\u00c3O PR\u00d3PRIA PRODUZIDOS": {
                     "Alimenta\u00e7\u00e3o do Trabalhador": {}, 
@@ -621,7 +682,9 @@
                             "Receita das Unidades Imobili\u00e1rias Vendidas": {}, 
                             "Receita de Exporta\u00e7\u00e3o Direta de Mercadorias e Produtos": {}, 
                             "Receita de Exporta\u00e7\u00e3o de Servi\u00e7os": {}, 
-                            "Receita de Loca\u00e7\u00e3o de Bens M\u00f3veis e Im\u00f3veis": {}, 
+                            "Receita de Loca\u00e7\u00e3o de Bens M\u00f3veis e Im\u00f3veis": {
+                                "account_type": "Income Account"
+                            }, 
                             "Receita de Vendas de Mercadorias e Produtos a Comercial Exportadora com Fim Espec\u00edfico de Exporta\u00e7\u00e3o": {}
                         }
                     }
@@ -645,65 +708,6 @@
                 }
             }, 
             "RESULTADO OPERACIONAL": {
-                "CUSTO DOS PRODUTOS E SERVI\u00c7OS VENDIDOS": {
-                    "CUSTO DOS PRODUTOS VENDIDOS": {
-                        "CUSTO DOS PRODUTOS VENDIDOS PARA AS DEMAIS ATIVIDADES": {
-                            "Custos dos Produtos Vendidos em Geral": {
-                                "account_type": "Cost of Goods Sold"
-                            }, 
-                            "Outros Custos 4": {}, 
-                            "account_type": "Cost of Goods Sold"
-                        }, 
-                        "CUSTO DOS PRODUTOS VENDIDOS PARA ASSIST\u00caNCIA SOCIAL": {
-                            "Custos dos Produtos para Assist\u00eancia Social - Gratuidades": {}, 
-                            "Custos dos Produtos para Assist\u00eancia Social - Vendidos": {}, 
-                            "Outras": {}
-                        }, 
-                        "CUSTO DOS PRODUTOS VENDIDOS PARA EDUCA\u00c7\u00c3O": {
-                            "Custos dos Produtos para Educa\u00e7\u00e3o - Gratuidades": {}, 
-                            "Custos dos Produtos para Educa\u00e7\u00e3o - Vendidos": {}, 
-                            "Outros Custos 6": {}
-                        }, 
-                        "CUSTO DOS PRODUTOS VENDIDOS PARA SA\u00daDE": {
-                            "Custos dos Produtos para Sa\u00fade - Gratuidades": {}, 
-                            "Custos dos Produtos para Sa\u00fade \u2013 Vendidos": {}, 
-                            "Outros Custos 5": {}
-                        }, 
-                        "account_type": "Cost of Goods Sold"
-                    }, 
-                    "CUSTO DOS SERVI\u00c7OS PRESTADOS": {
-                        "CUSTO DOS SERVI\u00c7OS PRESTADOS PARA AS DEMAIS ATIVIDADES": {
-                            "Custo dos Servi\u00e7os Prestados em Geral": {}, 
-                            "Outros Custos": {}
-                        }, 
-                        "CUSTO DOS SERVI\u00c7OS PRESTADOS PARA ASSIST\u00caNCIA SOCIAL": {
-                            "Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias": {}, 
-                            "Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es 1": {}, 
-                            "Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas 1": {}, 
-                            "Custo dos Servi\u00e7os Prestados a Gratuidade 1": {}, 
-                            "Custo dos Servi\u00e7os Prestados a Pacientes Particulares": {}, 
-                            "Outros Custos 2": {}
-                        }, 
-                        "CUSTO DOS SERVI\u00c7OS PRESTADOS PARA EDUCA\u00c7\u00c3O": {
-                            "Custo dos Servi\u00e7os Prestados a Alunos N\u00e3o Bolsistas": {}, 
-                            "Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias (Exceto PROUNI)": {}, 
-                            "Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es": {}, 
-                            "Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas": {}, 
-                            "Custo dos Servi\u00e7os Prestados a Gratuidade": {}, 
-                            "Custo dos Servi\u00e7os Prestados ao PROUNI": {}, 
-                            "Outros Custos 1": {}
-                        }, 
-                        "CUSTO DOS SERVI\u00c7OS PRESTADOS PARA SA\u00daDE": {
-                            "Custo dos Servi\u00e7os Prestados a Conv\u00eanios SUS": {}, 
-                            "Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias 1": {}, 
-                            "Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es 2": {}, 
-                            "Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas 2": {}, 
-                            "Custo dos Servi\u00e7os Prestados a Gratuidade 2": {}, 
-                            "Custo dos Servi\u00e7os Prestados a Pacientes Particulares 1": {}, 
-                            "Outros Custos 3": {}
-                        }
-                    }
-                }, 
                 "DESPESAS OPERACIONAIS": {
                     "DESPESAS OPERACIONAIS 1": {
                         "DESPESAS OPERACIONAIS 2": {
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index c61c332..e3897bf 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -85,7 +85,14 @@
 				frappe.throw(
 					_(
 						"The currency of invoice {} ({}) is different from the currency of this dunning ({})."
-					).format(row.sales_invoice, invoice_currency, self.currency)
+					).format(
+						frappe.get_desk_link(
+							"Sales Invoice",
+							row.sales_invoice,
+						),
+						invoice_currency,
+						self.currency,
+					)
 				)
 
 	def validate_overdue_payments(self):
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 74c835c..8ffbaa1 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -156,14 +156,18 @@
 				if self.doctype == "Stock Reconciliation":
 					qty = row.qty
 					type_of_transaction = "Inward"
+					warehouse = row.warehouse
 				else:
-					qty = row.stock_qty
+					qty = row.stock_qty if self.doctype != "Stock Entry" else row.transfer_qty
 					type_of_transaction = get_type_of_transaction(self, row)
+					warehouse = (
+						row.warehouse if self.doctype != "Stock Entry" else row.s_warehouse or row.t_warehouse
+					)
 
 				sn_doc = SerialBatchCreation(
 					{
 						"item_code": row.item_code,
-						"warehouse": row.warehouse,
+						"warehouse": warehouse,
 						"posting_date": self.posting_date,
 						"posting_time": self.posting_time,
 						"voucher_type": self.doctype,
@@ -938,6 +942,9 @@
 			"Stock Reconciliation",
 		)
 
+		if not frappe.get_all("Putaway Rule", limit=1):
+			return
+
 		if self.doctype == "Purchase Invoice" and self.get("update_stock") == 0:
 			valid_doctype = False
 
diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json
index d3ad51f..63e3fa3 100644
--- a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json
+++ b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json
@@ -7,6 +7,7 @@
  "field_order": [
   "raw_materials_consumption_section",
   "material_consumption",
+  "get_rm_cost_from_consumption_entry",
   "column_break_3",
   "backflush_raw_materials_based_on",
   "capacity_planning",
@@ -202,13 +203,20 @@
    "fieldname": "set_op_cost_and_scrape_from_sub_assemblies",
    "fieldtype": "Check",
    "label": "Set Operating Cost / Scrape Items From Sub-assemblies"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval: doc.material_consumption",
+   "fieldname": "get_rm_cost_from_consumption_entry",
+   "fieldtype": "Check",
+   "label": "Get Raw Materials Cost from Consumption Entry"
   }
  ],
  "icon": "icon-wrench",
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2023-12-28 16:37:44.874096",
+ "modified": "2024-02-08 19:00:37.561244",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "Manufacturing Settings",
diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py
index 463ba9f..9a50111 100644
--- a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py
+++ b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py
@@ -26,6 +26,7 @@
 		default_scrap_warehouse: DF.Link | None
 		default_wip_warehouse: DF.Link | None
 		disable_capacity_planning: DF.Check
+		get_rm_cost_from_consumption_entry: DF.Check
 		job_card_excess_transfer: DF.Check
 		make_serial_no_batch_from_work_order: DF.Check
 		material_consumption: DF.Check
diff --git a/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.json b/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.json
index d07bf0f..06c1b49 100644
--- a/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.json
+++ b/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.json
@@ -38,7 +38,8 @@
    "in_list_view": 1,
    "label": "Item Code",
    "options": "Item",
-   "reqd": 1
+   "reqd": 1,
+   "search_index": 1
   },
   {
    "fieldname": "item_name",
@@ -53,7 +54,8 @@
    "in_standard_filter": 1,
    "label": "For Warehouse",
    "options": "Warehouse",
-   "reqd": 1
+   "reqd": 1,
+   "search_index": 1
   },
   {
    "columns": 1,
@@ -141,7 +143,8 @@
    "fieldname": "from_warehouse",
    "fieldtype": "Link",
    "label": "From Warehouse",
-   "options": "Warehouse"
+   "options": "Warehouse",
+   "search_index": 1
   },
   {
    "fetch_from": "item_code.safety_stock",
@@ -199,7 +202,7 @@
  ],
  "istable": 1,
  "links": [],
- "modified": "2023-09-12 12:09:08.358326",
+ "modified": "2024-02-11 16:21:11.977018",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "Material Request Plan Item",
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.json b/erpnext/manufacturing/doctype/production_plan/production_plan.json
index 257b60c..54c3893 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.json
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.json
@@ -298,7 +298,8 @@
    "no_copy": 1,
    "options": "\nDraft\nSubmitted\nNot Started\nIn Process\nCompleted\nClosed\nCancelled\nMaterial Requested",
    "print_hide": 1,
-   "read_only": 1
+   "read_only": 1,
+   "search_index": 1
   },
   {
    "fieldname": "amended_from",
@@ -436,7 +437,7 @@
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2023-12-26 16:31:13.740777",
+ "modified": "2024-02-11 15:42:47.642481",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "Production Plan",
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 6e9d1fc..b942842 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -1768,23 +1768,23 @@
 	return reserved_qty_for_production_plan - reserved_qty_for_production
 
 
+@frappe.request_cache
 def get_non_completed_production_plans():
 	table = frappe.qb.DocType("Production Plan")
 	child = frappe.qb.DocType("Production Plan Item")
 
-	query = (
+	return (
 		frappe.qb.from_(table)
 		.inner_join(child)
 		.on(table.name == child.parent)
 		.select(table.name)
+		.distinct()
 		.where(
 			(table.docstatus == 1)
 			& (table.status.notin(["Completed", "Closed"]))
 			& (child.planned_qty > child.ordered_qty)
 		)
-	).run(as_dict=True)
-
-	return list(set([d.name for d in query]))
+	).run(pluck="name")
 
 
 def get_raw_materials_of_sub_assembly_items(
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index f6e9a07..efe9f53 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -1776,6 +1776,52 @@
 			"Manufacturing Settings", "set_op_cost_and_scrape_from_sub_assemblies", 0
 		)
 
+	@change_settings(
+		"Manufacturing Settings", {"material_consumption": 1, "get_rm_cost_from_consumption_entry": 1}
+	)
+	def test_get_rm_cost_from_consumption_entry(self):
+		from erpnext.stock.doctype.stock_entry.test_stock_entry import (
+			make_stock_entry as make_stock_entry_test_record,
+		)
+
+		rm = make_item(properties={"is_stock_item": 1}).name
+		fg = make_item(properties={"is_stock_item": 1}).name
+
+		make_stock_entry_test_record(
+			purpose="Material Receipt",
+			item_code=rm,
+			target="Stores - _TC",
+			qty=10,
+			basic_rate=100,
+		)
+		make_stock_entry_test_record(
+			purpose="Material Receipt",
+			item_code=rm,
+			target="Stores - _TC",
+			qty=10,
+			basic_rate=200,
+		)
+
+		bom = make_bom(item=fg, raw_materials=[rm], rate=150).name
+		wo = make_wo_order_test_record(
+			production_item=fg,
+			bom_no=bom,
+			qty=10,
+		)
+
+		mte = frappe.get_doc(make_stock_entry(wo.name, "Material Transfer for Manufacture", 10))
+		mte.items[0].s_warehouse = "Stores - _TC"
+		mte.insert().submit()
+
+		mce = frappe.get_doc(make_stock_entry(wo.name, "Material Consumption for Manufacture", 10))
+		mce.insert().submit()
+
+		me = frappe.get_doc(make_stock_entry(wo.name, "Manufacture", 10))
+		me.insert().submit()
+
+		valuation_rate = sum([item.valuation_rate * item.transfer_qty for item in mce.items]) / 10
+		self.assertEqual(me.items[0].valuation_rate, valuation_rate)
+
 
 def prepare_boms_for_sub_assembly_test():
 	if not frappe.db.exists("BOM", {"item": "Test Final SF Item 1"}):
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.json b/erpnext/manufacturing/doctype/work_order/work_order.json
index 1996e19..63c74b6 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.json
+++ b/erpnext/manufacturing/doctype/work_order/work_order.json
@@ -447,7 +447,8 @@
    "no_copy": 1,
    "options": "Production Plan",
    "print_hide": 1,
-   "read_only": 1
+   "read_only": 1,
+   "search_index": 1
   },
   {
    "fieldname": "production_plan_item",
@@ -592,7 +593,7 @@
  "image_field": "image",
  "is_submittable": 1,
  "links": [],
- "modified": "2023-08-11 18:35:49.852069",
+ "modified": "2024-02-11 15:47:13.454422",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "Work Order",
diff --git a/erpnext/manufacturing/doctype/work_order_item/work_order_item.json b/erpnext/manufacturing/doctype/work_order_item/work_order_item.json
index f354d45..0f4d693 100644
--- a/erpnext/manufacturing/doctype/work_order_item/work_order_item.json
+++ b/erpnext/manufacturing/doctype/work_order_item/work_order_item.json
@@ -36,7 +36,8 @@
    "fieldtype": "Link",
    "in_list_view": 1,
    "label": "Item Code",
-   "options": "Item"
+   "options": "Item",
+   "search_index": 1
   },
   {
    "fieldname": "source_warehouse",
@@ -141,7 +142,7 @@
  ],
  "istable": 1,
  "links": [],
- "modified": "2022-09-28 10:50:43.512562",
+ "modified": "2024-02-11 15:45:32.318374",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "Work Order Item",
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index 5ae48ee..b5189b8 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -20,6 +20,7 @@
 from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle
 from erpnext.selling.doctype.sales_order.sales_order import (
 	WarehouseRequired,
+	create_pick_list,
 	make_delivery_note,
 	make_material_request,
 	make_raw_material_request,
@@ -2023,6 +2024,83 @@
 			frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Not Requested"
 		)
 
+	def test_pick_list_without_rejected_materials(self):
+		serial_and_batch_item = make_item(
+			"_Test Serial and Batch Item for Rejected Materials",
+			properties={
+				"has_serial_no": 1,
+				"has_batch_no": 1,
+				"create_new_batch": 1,
+				"batch_number_series": "BAT-TSBIFRM-.#####",
+				"serial_no_series": "SN-TSBIFRM-.#####",
+			},
+		).name
+
+		serial_item = make_item(
+			"_Test Serial Item for Rejected Materials",
+			properties={
+				"has_serial_no": 1,
+				"serial_no_series": "SN-TSIFRM-.#####",
+			},
+		).name
+
+		batch_item = make_item(
+			"_Test Batch Item for Rejected Materials",
+			properties={
+				"has_batch_no": 1,
+				"create_new_batch": 1,
+				"batch_number_series": "BAT-TBIFRM-.#####",
+			},
+		).name
+
+		normal_item = make_item("_Test Normal Item for Rejected Materials").name
+
+		warehouse = "_Test Warehouse - _TC"
+		rejected_warehouse = "_Test Dummy Rejected Warehouse - _TC"
+
+		if not frappe.db.exists("Warehouse", rejected_warehouse):
+			frappe.get_doc(
+				{
+					"doctype": "Warehouse",
+					"warehouse_name": rejected_warehouse,
+					"company": "_Test Company",
+					"warehouse_group": "_Test Warehouse Group",
+					"is_rejected_warehouse": 1,
+				}
+			).insert()
+
+		se = make_stock_entry(item_code=normal_item, qty=1, to_warehouse=warehouse, do_not_submit=True)
+		for item in [serial_and_batch_item, serial_item, batch_item]:
+			se.append("items", {"item_code": item, "qty": 1, "t_warehouse": warehouse})
+
+		se.save()
+		se.submit()
+
+		se = make_stock_entry(
+			item_code=normal_item, qty=1, to_warehouse=rejected_warehouse, do_not_submit=True
+		)
+		for item in [serial_and_batch_item, serial_item, batch_item]:
+			se.append("items", {"item_code": item, "qty": 1, "t_warehouse": rejected_warehouse})
+
+		se.save()
+		se.submit()
+
+		so = make_sales_order(item_code=normal_item, qty=2, do_not_submit=True)
+
+		for item in [serial_and_batch_item, serial_item, batch_item]:
+			so.append("items", {"item_code": item, "qty": 2, "warehouse": warehouse})
+
+		so.save()
+		so.submit()
+
+		pick_list = create_pick_list(so.name)
+
+		pick_list.save()
+		for row in pick_list.locations:
+			self.assertEqual(row.qty, 1.0)
+			self.assertFalse(row.warehouse == rejected_warehouse)
+			self.assertTrue(row.warehouse == warehouse)
+
 
 def automatically_fetch_payment_terms(enable=1):
 	accounts_settings = frappe.get_doc("Accounts Settings")
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index feb4583..949c109 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -1122,6 +1122,7 @@
 		frappe.throw(_("Item {0} is cancelled").format(item_code))
 
 
+@frappe.request_cache
 def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0):
 	"""returns last purchase details in stock uom"""
 	# get last purchase order item details
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index e80218a..77a3d6d 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -228,9 +228,17 @@
 				const qty_fields = ['actual_qty', 'projected_qty', 'min_order_qty'];
 
 				if(!r.exc) {
-					$.each(r.message, function(k, v) {
-						if(!d[k] || in_list(qty_fields, k)) d[k] = v;
+					$.each(r.message, function(key, value) {
+						if(!d[key] || qty_fields.includes(key)) {
+							d[key] = value;
+						}
 					});
+
+					if (d.price_list_rate != r.message.price_list_rate) {
+						d.price_list_rate = r.message.price_list_rate;
+
+						frappe.model.set_value(d.doctype, d.name, "rate", d.price_list_rate);
+					}
 				}
 			}
 		});
@@ -432,7 +440,6 @@
 		item.amount = flt(item.qty) * flt(item.rate);
 		frappe.model.set_value(doctype, name, "amount", item.amount);
 		refresh_field("amount", item.name, item.parentfield);
-		frm.events.get_item_data(frm, item, false);
 	},
 
 	item_code: function(frm, doctype, name) {
@@ -452,7 +459,12 @@
 				set_schedule_date(frm);
 			}
 		}
-	}
+	},
+
+	conversion_factor: function(frm, doctype, name) {
+		const item = locals[doctype][name];
+		frm.events.get_item_data(frm, item, false);
+	},
 });
 
 erpnext.buying.MaterialRequestController = class MaterialRequestController extends erpnext.buying.BuyingController {
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 5dc07c9..c7239b5 100644
--- a/erpnext/stock/doctype/material_request_item/material_request_item.json
+++ b/erpnext/stock/doctype/material_request_item/material_request_item.json
@@ -35,6 +35,7 @@
   "received_qty",
   "rate_and_amount_section_break",
   "rate",
+  "price_list_rate",
   "col_break3",
   "amount",
   "accounting_details_section",
@@ -473,13 +474,22 @@
    "fieldtype": "Link",
    "label": "WIP Composite Asset",
    "options": "Asset"
+  },
+  {
+   "fieldname": "price_list_rate",
+   "fieldtype": "Currency",
+   "hidden": 1,
+   "label": "Price List Rate",
+   "options": "currency",
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "idx": 1,
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2023-11-14 18:37:59.599115",
+ "modified": "2024-02-08 16:30:56.137858",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Material Request Item",
diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.py b/erpnext/stock/doctype/material_request_item/material_request_item.py
index 2bed596..d23d041 100644
--- a/erpnext/stock/doctype/material_request_item/material_request_item.py
+++ b/erpnext/stock/doctype/material_request_item/material_request_item.py
@@ -41,6 +41,7 @@
 		parent: DF.Data
 		parentfield: DF.Data
 		parenttype: DF.Data
+		price_list_rate: DF.Currency
 		production_plan: DF.Link | None
 		project: DF.Link | None
 		projected_qty: DF.Float
diff --git a/erpnext/stock/doctype/pick_list/pick_list.js b/erpnext/stock/doctype/pick_list/pick_list.js
index aa0e125..3cc2956 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.js
+++ b/erpnext/stock/doctype/pick_list/pick_list.js
@@ -77,6 +77,9 @@
 				},
 				freeze: 1,
 				freeze_message: __("Setting Item Locations..."),
+				callback(r) {
+					refresh_field("locations");
+				}
 			});
 		}
 	},
diff --git a/erpnext/stock/doctype/pick_list/pick_list.json b/erpnext/stock/doctype/pick_list/pick_list.json
index bd84aad..0c47434 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.json
+++ b/erpnext/stock/doctype/pick_list/pick_list.json
@@ -16,6 +16,7 @@
   "for_qty",
   "column_break_4",
   "parent_warehouse",
+  "consider_rejected_warehouses",
   "get_item_locations",
   "section_break_6",
   "scan_barcode",
@@ -184,11 +185,18 @@
    "report_hide": 1,
    "reqd": 1,
    "search_index": 1
+  },
+  {
+   "default": "0",
+   "description": "Enable it if users want to consider rejected materials to dispatch.",
+   "fieldname": "consider_rejected_warehouses",
+   "fieldtype": "Check",
+   "label": "Consider Rejected Warehouses"
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2024-02-01 16:17:44.877426",
+ "modified": "2024-02-02 16:17:44.877426",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Pick List",
@@ -260,4 +268,4 @@
  "sort_order": "DESC",
  "states": [],
  "track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py
index e2edb20..0e1f8d7 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.py
+++ b/erpnext/stock/doctype/pick_list/pick_list.py
@@ -348,9 +348,9 @@
 		picked_items_details = self.get_picked_items_details(items)
 		self.item_location_map = frappe._dict()
 
-		from_warehouses = None
+		from_warehouses = [self.parent_warehouse] if self.parent_warehouse else []
 		if self.parent_warehouse:
-			from_warehouses = get_descendants_of("Warehouse", self.parent_warehouse)
+			from_warehouses.extend(get_descendants_of("Warehouse", self.parent_warehouse))
 
 		# Create replica before resetting, to handle empty table on update after submit.
 		locations_replica = self.get("locations")
@@ -369,6 +369,7 @@
 					self.item_count_map.get(item_code),
 					self.company,
 					picked_item_details=picked_items_details.get(item_code),
+					consider_rejected_warehouses=self.consider_rejected_warehouses,
 				),
 			)
 
@@ -710,6 +711,7 @@
 	company,
 	ignore_validation=False,
 	picked_item_details=None,
+	consider_rejected_warehouses=False,
 ):
 	locations = []
 	total_picked_qty = (
@@ -725,18 +727,34 @@
 			required_qty,
 			company,
 			total_picked_qty,
+			consider_rejected_warehouses=consider_rejected_warehouses,
 		)
 	elif has_serial_no:
 		locations = get_available_item_locations_for_serialized_item(
-			item_code, from_warehouses, required_qty, company, total_picked_qty
+			item_code,
+			from_warehouses,
+			required_qty,
+			company,
+			total_picked_qty,
+			consider_rejected_warehouses=consider_rejected_warehouses,
 		)
 	elif has_batch_no:
 		locations = get_available_item_locations_for_batched_item(
-			item_code, from_warehouses, required_qty, company, total_picked_qty
+			item_code,
+			from_warehouses,
+			required_qty,
+			company,
+			total_picked_qty,
+			consider_rejected_warehouses=consider_rejected_warehouses,
 		)
 	else:
 		locations = get_available_item_locations_for_other_item(
-			item_code, from_warehouses, required_qty, company, total_picked_qty
+			item_code,
+			from_warehouses,
+			required_qty,
+			company,
+			total_picked_qty,
+			consider_rejected_warehouses=consider_rejected_warehouses,
 		)
 
 	total_qty_available = sum(location.get("qty") for location in locations)
@@ -775,6 +793,7 @@
 	required_qty,
 	company,
 	total_picked_qty=0,
+	consider_rejected_warehouses=False,
 ):
 	# Get batch nos by FIFO
 	locations = get_available_item_locations_for_batched_item(
@@ -782,6 +801,7 @@
 		from_warehouses,
 		required_qty,
 		company,
+		consider_rejected_warehouses=consider_rejected_warehouses,
 	)
 
 	if locations:
@@ -811,7 +831,12 @@
 
 
 def get_available_item_locations_for_serialized_item(
-	item_code, from_warehouses, required_qty, company, total_picked_qty=0
+	item_code,
+	from_warehouses,
+	required_qty,
+	company,
+	total_picked_qty=0,
+	consider_rejected_warehouses=False,
 ):
 	picked_serial_nos = get_picked_serial_nos(item_code, from_warehouses)
 
@@ -828,6 +853,10 @@
 	else:
 		query = query.where(Coalesce(sn.warehouse, "") != "")
 
+	if not consider_rejected_warehouses:
+		if rejected_warehouses := get_rejected_warehouses():
+			query = query.where(sn.warehouse.notin(rejected_warehouses))
+
 	serial_nos = query.run(as_list=True)
 
 	warehouse_serial_nos_map = frappe._dict()
@@ -860,7 +889,12 @@
 
 
 def get_available_item_locations_for_batched_item(
-	item_code, from_warehouses, required_qty, company, total_picked_qty=0
+	item_code,
+	from_warehouses,
+	required_qty,
+	company,
+	total_picked_qty=0,
+	consider_rejected_warehouses=False,
 ):
 	locations = []
 	data = get_auto_batch_nos(
@@ -875,7 +909,14 @@
 	)
 
 	warehouse_wise_batches = frappe._dict()
+	rejected_warehouses = get_rejected_warehouses()
+
 	for d in data:
+		if (
+			not consider_rejected_warehouses and rejected_warehouses and d.warehouse in rejected_warehouses
+		):
+			continue
+
 		if d.warehouse not in warehouse_wise_batches:
 			warehouse_wise_batches.setdefault(d.warehouse, defaultdict(float))
 
@@ -898,7 +939,12 @@
 
 
 def get_available_item_locations_for_other_item(
-	item_code, from_warehouses, required_qty, company, total_picked_qty=0
+	item_code,
+	from_warehouses,
+	required_qty,
+	company,
+	total_picked_qty=0,
+	consider_rejected_warehouses=False,
 ):
 	bin = frappe.qb.DocType("Bin")
 	query = (
@@ -915,6 +961,10 @@
 		wh = frappe.qb.DocType("Warehouse")
 		query = query.from_(wh).where((bin.warehouse == wh.name) & (wh.company == company))
 
+	if not consider_rejected_warehouses:
+		if rejected_warehouses := get_rejected_warehouses():
+			query = query.where(bin.warehouse.notin(rejected_warehouses))
+
 	item_locations = query.run(as_dict=True)
 
 	return item_locations
@@ -1236,3 +1286,15 @@
 	item.serial_no = location.serial_no
 	item.batch_no = location.batch_no
 	item.material_request_item = location.material_request_item
+
+
+def get_rejected_warehouses():
+	if not hasattr(frappe.local, "rejected_warehouses"):
+		frappe.local.rejected_warehouses = []
+
+	if not frappe.local.rejected_warehouses:
+		frappe.local.rejected_warehouses = frappe.get_all(
+			"Warehouse", filters={"is_rejected_warehouse": 1}, pluck="name"
+		)
+
+	return frappe.local.rejected_warehouses
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 4c1de72..276b2f4 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -904,14 +904,62 @@
 				return flt(outgoing_items_cost / total_fg_qty)
 
 	def get_basic_rate_for_manufactured_item(self, finished_item_qty, outgoing_items_cost=0) -> float:
+		settings = frappe.get_single("Manufacturing Settings")
 		scrap_items_cost = sum([flt(d.basic_amount) for d in self.get("items") if d.is_scrap_item])
 
-		# Get raw materials cost from BOM if multiple material consumption entries
-		if not outgoing_items_cost and frappe.db.get_single_value(
-			"Manufacturing Settings", "material_consumption", cache=True
-		):
-			bom_items = self.get_bom_raw_materials(finished_item_qty)
-			outgoing_items_cost = sum([flt(row.qty) * flt(row.rate) for row in bom_items.values()])
+		if settings.material_consumption:
+			if settings.get_rm_cost_from_consumption_entry and self.work_order:
+
+				# Validate only if Material Consumption Entry exists for the Work Order.
+				if frappe.db.exists(
+					"Stock Entry",
+					{
+						"docstatus": 1,
+						"work_order": self.work_order,
+						"purpose": "Material Consumption for Manufacture",
+					},
+				):
+					for item in self.items:
+						if not item.is_finished_item and not item.is_scrap_item:
+							label = frappe.get_meta(settings.doctype).get_label("get_rm_cost_from_consumption_entry")
+							frappe.throw(
+								_(
+									"Row {0}: As {1} is enabled, raw materials cannot be added to {2} entry. Use {3} entry to consume raw materials."
+								).format(
+									item.idx,
+									frappe.bold(label),
+									frappe.bold("Manufacture"),
+									frappe.bold("Material Consumption for Manufacture"),
+								)
+							)
+
+					if frappe.db.exists(
+						"Stock Entry", {"docstatus": 1, "work_order": self.work_order, "purpose": "Manufacture"}
+					):
+						frappe.throw(
+							_("Only one {0} entry can be created against the Work Order {1}").format(
+								frappe.bold("Manufacture"), frappe.bold(self.work_order)
+							)
+						)
+
+					SE = frappe.qb.DocType("Stock Entry")
+					SE_ITEM = frappe.qb.DocType("Stock Entry Detail")
+
+					outgoing_items_cost = (
+						frappe.qb.from_(SE)
+						.left_join(SE_ITEM)
+						.on(SE.name == SE_ITEM.parent)
+						.select(Sum(SE_ITEM.valuation_rate * SE_ITEM.transfer_qty))
+						.where(
+							(SE.docstatus == 1)
+							& (SE.work_order == self.work_order)
+							& (SE.purpose == "Material Consumption for Manufacture")
+						)
+					).run()[0][0] or 0
+
+			elif not outgoing_items_cost:
+				bom_items = self.get_bom_raw_materials(finished_item_qty)
+				outgoing_items_cost = sum([flt(row.qty) * flt(row.rate) for row in bom_items.values()])
 
 		return flt((outgoing_items_cost - scrap_items_cost) / finished_item_qty)
 
@@ -982,6 +1030,9 @@
 		already_picked_serial_nos = []
 
 		for row in self.items:
+			if row.use_serial_batch_fields and (row.serial_no or row.batch_no):
+				continue
+
 			if not row.s_warehouse:
 				continue
 
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py
index 0f67e47..271cbbc 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py
@@ -92,9 +92,6 @@
 		else:
 			args.qty = cint(args.qty)
 
-	if args.serial_no or args.batch_no:
-		args.use_serial_batch_fields = True
-
 	# purpose
 	if not args.purpose:
 		if args.source and args.target:
@@ -136,7 +133,7 @@
 	serial_number = args.serial_no
 
 	bundle_id = None
-	if args.serial_no or args.batch_no or args.batches:
+	if not args.use_serial_batch_fields and (args.serial_no or args.batch_no or args.batches):
 		batches = frappe._dict({})
 		if args.batch_no:
 			batches = frappe._dict({args.batch_no: args.qty})
@@ -164,7 +161,11 @@
 			.name
 		)
 
-	args.serial_no = serial_number
+		args["serial_no"] = ""
+		args["batch_no"] = ""
+
+	else:
+		args.serial_no = serial_number
 
 	s.append(
 		"items",
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index af91536..6c3faa6 100644
--- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
@@ -1596,6 +1596,7 @@
 			qty=4,
 			to_warehouse="_Test Warehouse - _TC",
 			batch_no=batch.name,
+			use_serial_batch_fields=1,
 			do_not_save=True,
 		)
 
@@ -1754,6 +1755,51 @@
 			mr.cancel()
 			mr.delete()
 
+	def test_use_serial_and_batch_fields(self):
+		item = make_item(
+			"Test Use Serial and Batch Item SN Item",
+			{"has_serial_no": 1, "is_stock_item": 1},
+		)
+
+		serial_nos = [
+			"Test Use Serial and Batch Item SN Item - SN 001",
+			"Test Use Serial and Batch Item SN Item - SN 002",
+		]
+
+		se = make_stock_entry(
+			item_code=item.name,
+			qty=2,
+			to_warehouse="_Test Warehouse - _TC",
+			use_serial_batch_fields=1,
+			serial_no="\n".join(serial_nos),
+		)
+
+		self.assertTrue(se.items[0].use_serial_batch_fields)
+		self.assertFalse(se.items[0].serial_no)
+		self.assertTrue(se.items[0].serial_and_batch_bundle)
+
+		for serial_no in serial_nos:
+			self.assertTrue(frappe.db.exists("Serial No", serial_no))
+			self.assertEqual(frappe.db.get_value("Serial No", serial_no, "status"), "Active")
+
+		se1 = make_stock_entry(
+			item_code=item.name,
+			qty=2,
+			from_warehouse="_Test Warehouse - _TC",
+			use_serial_batch_fields=1,
+			serial_no="\n".join(serial_nos),
+		)
+
+		se1.reload()
+
+		self.assertTrue(se1.items[0].use_serial_batch_fields)
+		self.assertFalse(se1.items[0].serial_no)
+		self.assertTrue(se1.items[0].serial_and_batch_bundle)
+
+		for serial_no in serial_nos:
+			self.assertTrue(frappe.db.exists("Serial No", serial_no))
+			self.assertEqual(frappe.db.get_value("Serial No", serial_no, "status"), "Delivered")
+
 
 def make_serialized_item(**args):
 	args = frappe._dict(args)
diff --git a/erpnext/stock/doctype/warehouse/warehouse.json b/erpnext/stock/doctype/warehouse/warehouse.json
index 43b2ad2..7b0cade 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.json
+++ b/erpnext/stock/doctype/warehouse/warehouse.json
@@ -13,6 +13,7 @@
   "column_break_3",
   "is_group",
   "parent_warehouse",
+  "is_rejected_warehouse",
   "column_break_4",
   "account",
   "company",
@@ -249,13 +250,20 @@
   {
    "fieldname": "column_break_qajx",
    "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "description": "If yes, then this warehouse will be used to store rejected materials",
+   "fieldname": "is_rejected_warehouse",
+   "fieldtype": "Check",
+   "label": "Is Rejected Warehouse"
   }
  ],
  "icon": "fa fa-building",
  "idx": 1,
  "is_tree": 1,
  "links": [],
- "modified": "2023-05-29 13:10:43.333160",
+ "modified": "2024-01-24 16:27:28.299520",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Warehouse",