Merge branch 'develop' into product-bundle-fixes
diff --git a/erpnext/selling/doctype/quotation/test_quotation.py b/erpnext/selling/doctype/quotation/test_quotation.py
index 769e066..aa83726 100644
--- a/erpnext/selling/doctype/quotation/test_quotation.py
+++ b/erpnext/selling/doctype/quotation/test_quotation.py
@@ -302,6 +302,109 @@
 
 		enable_calculate_bundle_price(enable=0)
 
+	def test_product_bundle_price_calculation_for_multiple_product_bundles_when_calculate_bundle_price_is_checked(self):
+		from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle
+		from erpnext.stock.doctype.item.test_item import make_item
+
+		make_item("_Test Product Bundle 1", {"is_stock_item": 0})
+		make_item("_Test Product Bundle 2", {"is_stock_item": 0})
+		make_item("_Test Bundle Item 1", {"is_stock_item": 1})
+		make_item("_Test Bundle Item 2", {"is_stock_item": 1})
+		make_item("_Test Bundle Item 3", {"is_stock_item": 1})
+
+		make_product_bundle("_Test Product Bundle 1",
+			["_Test Bundle Item 1", "_Test Bundle Item 2"])
+		make_product_bundle("_Test Product Bundle 2",
+			["_Test Bundle Item 2", "_Test Bundle Item 3"])
+
+		enable_calculate_bundle_price()
+
+		item_list = [
+			{
+				"item_code": "_Test Product Bundle 1",
+				"warehouse": "",
+				"qty": 1,
+				"rate": 400,
+				"delivered_by_supplier": 1,
+				"supplier": '_Test Supplier'
+			},
+			{
+				"item_code": "_Test Product Bundle 2",
+				"warehouse": "",
+				"qty": 1,
+				"rate": 400,
+				"delivered_by_supplier": 1,
+				"supplier": '_Test Supplier'
+			}
+		]
+
+		quotation = make_quotation(item_list=item_list, do_not_submit=1)
+		quotation.packed_items[0].rate = 100
+		quotation.packed_items[1].rate = 200
+		quotation.packed_items[2].rate = 200
+		quotation.packed_items[3].rate = 300
+		quotation.save()
+
+		expected_values = [300, 500]
+
+		for item in quotation.items:
+			self.assertEqual(item.amount, expected_values[item.idx-1])
+
+		enable_calculate_bundle_price(enable=0)
+
+	def test_packed_items_indices_are_reset_when_product_bundle_is_deleted_from_items_table(self):
+		from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle
+		from erpnext.stock.doctype.item.test_item import make_item
+
+		make_item("_Test Product Bundle 1", {"is_stock_item": 0})
+		make_item("_Test Product Bundle 2", {"is_stock_item": 0})
+		make_item("_Test Product Bundle 3", {"is_stock_item": 0})
+		make_item("_Test Bundle Item 1", {"is_stock_item": 1})
+		make_item("_Test Bundle Item 2", {"is_stock_item": 1})
+		make_item("_Test Bundle Item 3", {"is_stock_item": 1})
+
+		make_product_bundle("_Test Product Bundle 1",
+			["_Test Bundle Item 1", "_Test Bundle Item 2"])
+		make_product_bundle("_Test Product Bundle 2",
+			["_Test Bundle Item 2", "_Test Bundle Item 3"])
+		make_product_bundle("_Test Product Bundle 3",
+			["_Test Bundle Item 3", "_Test Bundle Item 1"])
+
+		item_list = [
+			{
+				"item_code": "_Test Product Bundle 1",
+				"warehouse": "",
+				"qty": 1,
+				"rate": 400,
+				"delivered_by_supplier": 1,
+				"supplier": '_Test Supplier'
+			},
+			{
+				"item_code": "_Test Product Bundle 2",
+				"warehouse": "",
+				"qty": 1,
+				"rate": 400,
+				"delivered_by_supplier": 1,
+				"supplier": '_Test Supplier'
+			},
+			{
+				"item_code": "_Test Product Bundle 3",
+				"warehouse": "",
+				"qty": 1,
+				"rate": 400,
+				"delivered_by_supplier": 1,
+				"supplier": '_Test Supplier'
+			}
+		]
+
+		quotation = make_quotation(item_list=item_list, do_not_submit=1)
+		del quotation.items[1]
+		quotation.save()
+
+		for id, item in enumerate(quotation.packed_items):
+			expected_index = id + 1
+			self.assertEqual(item.idx, expected_index)
+
 test_records = frappe.get_test_records('Quotation')
 
 def enable_calculate_bundle_price(enable=1):
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 47b8ebd..1c24825 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -925,6 +925,7 @@
 				"supplier",
 				"pricing_rules"
 			],
+			"condition": lambda doc: doc.parent_item in items_to_map
 		}
 	}, target_doc, set_missing_values)
 
diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py
index 3f73093..0ce8ee4 100644
--- a/erpnext/stock/doctype/packed_item/packed_item.py
+++ b/erpnext/stock/doctype/packed_item/packed_item.py
@@ -106,11 +106,15 @@
 	if not delete_list:
 		return doc
 
+	index = 1
 	packed_items = doc.get("packed_items")
 	doc.set("packed_items", [])
+
 	for d in packed_items:
 		if d not in delete_list:
+			d.idx = index
 			doc.append("packed_items", d)
+			index += 1
 
 def update_product_bundle_price(doc, parent_items):
 	"""Updates the prices of Product Bundles based on the rates of the Items in the bundle."""
@@ -128,7 +132,8 @@
 		else:
 			update_parent_item_price(doc, parent_items[parent_items_index][0], bundle_price)
 
-			bundle_price = 0
+			bundle_item_rate = bundle_item.rate if bundle_item.rate else 0
+			bundle_price = bundle_item.qty * bundle_item_rate
 			parent_items_index += 1
 
 	# for the last product bundle