feat: Provision to fetch items from BOM in Stock Entry

Items are populated in child table and amounts are calculated
Warehouse Fields in popup toggle based on Stock Entry Type
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 225ae29..d02dd59 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -599,6 +599,7 @@
 				item.image,
 				bom.project,
 				item.stock_uom,
+				item.item_group,
 				item.allow_alternative_item,
 				item_default.default_warehouse,
 				item_default.expense_account as expense_account,
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 0b02302..cee09e7 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -181,6 +181,12 @@
 			}
 		}
 
+		if (frm.doc.docstatus === 0) {
+			frm.add_custom_button(__('Bill of Materials'), function(){
+				frm.events.get_items_from_bom(frm);
+			}, __("Get items from"));
+		}
+
 		if (frm.doc.docstatus===0) {
 			frm.add_custom_button(__('Purchase Invoice'), function() {
 				erpnext.utils.map_current_doc({
@@ -387,6 +393,73 @@
 		}
 	},
 
+	get_items_from_bom: function(frm) {
+		let filters = function(){
+			return {filters: { docstatus:1 }};
+		}
+
+		let fields = [
+			{"fieldname":"bom", "fieldtype":"Link", "label":__("BOM"),
+			options:"BOM", reqd: 1, get_query: filters()},
+			{"fieldname":"source_warehouse", "fieldtype":"Link", "label":__("Source Warehouse"),
+			options:"Warehouse"},
+			{"fieldname":"target_warehouse", "fieldtype":"Link", "label":__("Target Warehouse"),
+			options:"Warehouse"},
+			{"fieldname":"qty", "fieldtype":"Float", "label":__("Quantity"),
+			reqd: 1, "default": 1},
+			{"fieldname":"fetch_exploded", "fieldtype":"Check",
+			"label":__("Fetch exploded BOM (including sub-assemblies)"), "default":1},
+			{"fieldname":"fetch", "label":__("Get Items from BOM"), "fieldtype":"Button"}
+		]
+		if (frm.doc.stock_entry_type == 'Material Issue'){
+			fields.splice(2,1);
+		}
+		else if(frm.doc.stock_entry_type == 'Material Receipt'){
+			fields.splice(1,1);
+		}
+
+		let d = new frappe.ui.Dialog({
+			title: __("Get Items from BOM"),
+			fields: fields
+		});
+		d.get_input("fetch").on("click", function() {
+			let values = d.get_values();
+			if(!values) return;
+			values["company"] = frm.doc.company;
+			if(!frm.doc.company) frappe.throw(__("Company field is required"));
+			frappe.call({
+				method: "erpnext.manufacturing.doctype.bom.bom.get_bom_items",
+				args: values,
+				callback: function(r) {
+					if (!r.message) {
+						frappe.throw(__("BOM does not contain any stock item"));
+					} else {
+						erpnext.utils.remove_empty_first_row(frm, "items");
+						$.each(r.message, function(i, item) {
+							let d = frappe.model.add_child(cur_frm.doc, "Stock Entry Detail", "items");
+							d.item_code = item.item_code;
+							d.item_name = item.item_name;
+							d.item_group = item.item_group;
+							d.s_warehouse = values.source_warehouse;
+							d.t_warehouse = values.target_warehouse;
+							d.uom = item.stock_uom;
+							d.stock_uom = item.stock_uom;
+							d.conversion_factor = 1;
+							d.qty = item.qty;
+							d.expense_account = item.expense_account;
+							d.project = item.project;
+							frm.events.set_basic_rate(frm, d.doctype, d.name);
+						});
+					}
+					d.hide();
+					refresh_field("items");
+				}
+			});
+
+		});
+		d.show();
+	},
+
 	calculate_basic_amount: function(frm, item) {
 		item.basic_amount = flt(flt(item.transfer_qty) * flt(item.basic_rate),
 			precision("basic_amount", item));