fix: handle for product bundle (#18420)

* fix: handle for product bundle

* fix: Requested changes and some general fixes
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index c9aaab4..67fa0d4 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -518,7 +518,7 @@
 			"doctype": "Material Request Item",
 			"field_map": {
 				"parent": "sales_order",
-				"stock_uom": "uom"
+				"uom": "stock_uom"
 			},
 			"postprocess": update_item
 		},
diff --git a/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py b/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py
index 670b4e9..14d8031 100644
--- a/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py
+++ b/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py
@@ -4,7 +4,7 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _
-from frappe.utils import cint,cstr
+from frappe.utils import flt
 
 def execute(filters=None):
 	columns = get_columns()
@@ -100,7 +100,7 @@
 			so.transaction_date,
 			so.customer,
 			so.territory,
-			sum(so_item.qty) as net_qty,
+			sum(so_item.qty) as total_qty,
 			so.company
 		FROM `tabSales Order` so, `tabSales Order Item` so_item
 		WHERE
@@ -111,10 +111,15 @@
 			so.name,so_item.item_code
 		""", as_dict = 1)
 
+	sales_orders = [row.name for row in sales_order_entry]
 	mr_records = frappe.get_all("Material Request Item",
-		{"sales_order_item": ("!=",""), "docstatus": 1},
+		{"sales_order": ("in", sales_orders), "docstatus": 1},
 		["parent", "qty", "sales_order", "item_code"])
 
+	bundled_item_map = get_packed_items(sales_orders)
+
+	item_with_product_bundle = get_items_with_product_bundle([row.item_code for row in sales_order_entry])
+
 	materials_request_dict = {}
 
 	for record in mr_records:
@@ -131,27 +136,64 @@
 		if record.parent not in details.get('material_requests'):
 			details['material_requests'].append(record.parent)
 
-	pending_so=[]
+	pending_so = []
 	for so in sales_order_entry:
-		# fetch all the material request records for a sales order item
-		key = (so.name, so.item_code)
-		materials_request = materials_request_dict.get(key) or {}
+		if so.item_code not in item_with_product_bundle:
+			material_requests_against_so = materials_request_dict.get((so.name, so.item_code)) or {}
+			# check for pending sales order
+			if flt(so.total_qty) > flt(material_requests_against_so.get('qty')):
+				so_record = {
+					"item_code": so.item_code,
+					"item_name": so.item_name,
+					"description": so.description,
+					"sales_order_no": so.name,
+					"date": so.transaction_date,
+					"material_request": ','.join(material_requests_against_so.get('material_requests', [])),
+					"customer": so.customer,
+					"territory": so.territory,
+					"so_qty": so.total_qty,
+					"requested_qty": material_requests_against_so.get('qty'),
+					"pending_qty": so.total_qty - flt(material_requests_against_so.get('qty')),
+					"company": so.company
+				}
+				pending_so.append(so_record)
+		else:
+			for item in bundled_item_map.get((so.name, so.item_code)):
+				material_requests_against_so = materials_request_dict.get((so.name, item.item_code)) or {}
+				if flt(item.qty) > flt(material_requests_against_so.get('qty')):
+					so_record = {
+						"item_code": item.item_code,
+						"item_name": item.item_name,
+						"description": item.description,
+						"sales_order_no": so.name,
+						"date": so.transaction_date,
+						"material_request": ','.join(material_requests_against_so.get('material_requests', [])),
+						"customer": so.customer,
+						"territory": so.territory,
+						"so_qty": item.qty,
+						"requested_qty": material_requests_against_so.get('qty', 0),
+						"pending_qty": item.qty - flt(material_requests_against_so.get('qty', 0)),
+						"company": so.company
+					}
+					pending_so.append(so_record)
 
-		# check for pending sales order
-		if cint(so.net_qty) > cint(materials_request.get('qty')):
-			so_record = {
-				"item_code": so.item_code,
-				"item_name": so.item_name,
-				"description": so.description,
-				"sales_order_no": so.name,
-				"date": so.transaction_date,
-				"material_request": ','.join(materials_request.get('material_requests', [])),
-				"customer": so.customer,
-				"territory": so.territory,
-				"so_qty": so.net_qty,
-				"requested_qty": cint(materials_request.get('qty')),
-				"pending_qty": so.net_qty - cint(materials_request.get('qty')),
-				"company": so.company
-			}
-			pending_so.append(so_record)
-	return pending_so
\ No newline at end of file
+
+	return pending_so
+
+def get_items_with_product_bundle(item_list):
+	bundled_items = frappe.get_all("Product Bundle", filters = [
+		("new_item_code", "IN", item_list)
+	], fields = ["new_item_code"])
+
+	return [d.new_item_code for d in bundled_items]
+
+def get_packed_items(sales_order_list):
+	packed_items = frappe.get_all("Packed Item", filters = [
+		("parent", "IN", sales_order_list)
+	], fields = ["parent_item", "item_code", "qty", "item_name", "description", "parent"])
+
+	bundled_item_map = frappe._dict()
+	for d in packed_items:
+		bundled_item_map.setdefault((d.parent, d.parent_item), []).append(d)
+
+	return bundled_item_map
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index bf5a818..35c0bb6 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -639,7 +639,7 @@
 		if not frappe.db.get_value("Price List",
 			{"name": args.price_list, args.transaction_type: 1, "enabled": 1}):
 			throw(_("Price List {0} is disabled or does not exist").format(args.price_list))
-	elif not args.get("supplier"):
+	elif args.get("customer"):
 		throw(_("Price List not selected"))
 
 def validate_conversion_rate(args, meta):