test: test bundle - picklist behaviour
diff --git a/erpnext/stock/doctype/packed_item/test_packed_item.py b/erpnext/stock/doctype/packed_item/test_packed_item.py
index c928b57..ad7fd9a 100644
--- a/erpnext/stock/doctype/packed_item/test_packed_item.py
+++ b/erpnext/stock/doctype/packed_item/test_packed_item.py
@@ -14,8 +14,13 @@
 from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
 
 
-def create_product_bundle(quantities: Optional[List[int]] = None) -> Tuple[str, List[str]]:
-	"""Get a new product_bundle for use in tests"""
+def create_product_bundle(
+	quantities: Optional[List[int]] = None, warehouse: Optional[str] = None
+) -> Tuple[str, List[str]]:
+	"""Get a new product_bundle for use in tests.
+
+	Create 10x required stock if warehouse is specified.
+	"""
 	if not quantities:
 		quantities = [2, 2]
 
@@ -28,8 +33,11 @@
 		compoenent = make_item().name
 		components.append(compoenent)
 		bundle_doc.append("items", {"item_code": compoenent, "qty": qty})
+		if warehouse:
+			make_stock_entry(item=compoenent, to_warehouse=warehouse, qty=10 * qty, rate=100)
 
 	bundle_doc.insert()
+
 	return bundle, components
 
 
@@ -41,12 +49,10 @@
 		super().setUpClass()
 		cls.warehouse = "_Test Warehouse - _TC"
 
-		cls.bundle, cls.bundle_items = create_product_bundle()
-		cls.bundle2, cls.bundle2_items = create_product_bundle()
+		cls.bundle, cls.bundle_items = create_product_bundle(warehouse=cls.warehouse)
+		cls.bundle2, cls.bundle2_items = create_product_bundle(warehouse=cls.warehouse)
 
 		cls.normal_item = make_item().name
-		for item in cls.bundle_items + cls.bundle2_items:
-			make_stock_entry(item_code=item, to_warehouse=cls.warehouse, qty=100, rate=100)
 
 	def test_adding_bundle_item(self):
 		"Test impact on packed items if bundle item row is added."
diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py
index 94e9e53..53584f5 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.py
+++ b/erpnext/stock/doctype/pick_list/pick_list.py
@@ -618,7 +618,6 @@
 	for so_row, item_code in product_bundles.items():
 		sales_order_item = frappe.get_doc("Sales Order Item", so_row)
 		dn_bundle_item = map_child_doc(sales_order_item, delivery_note, item_mapper)
-		# TODO: post process packed items and update stock details
 		dn_bundle_item.qty = pick_list._compute_picked_qty_for_bundle(
 			so_row, product_bundle_qty_map[item_code]
 		)
diff --git a/erpnext/stock/doctype/pick_list/test_pick_list.py b/erpnext/stock/doctype/pick_list/test_pick_list.py
index d1a9472..8ce05f1 100644
--- a/erpnext/stock/doctype/pick_list/test_pick_list.py
+++ b/erpnext/stock/doctype/pick_list/test_pick_list.py
@@ -8,6 +8,7 @@
 from erpnext.selling.doctype.sales_order.sales_order import create_pick_list
 from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
 from erpnext.stock.doctype.item.test_item import create_item, make_item
+from erpnext.stock.doctype.packed_item.test_packed_item import create_product_bundle
 from erpnext.stock.doctype.pick_list.pick_list import create_delivery_note
 from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
 from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
@@ -584,12 +585,12 @@
 	def test_picklist_with_bundles(self):
 		# from test_records.json
 		warehouse = "_Test Warehouse - _TC"
-		bundle = "_Test Product Bundle Item"
-		bundle_items = {"_Test Item": 5, "_Test Item Home Desktop 100": 2}
-		for item in bundle_items:
-			make_stock_entry(item=item, to_warehouse=warehouse, qty=10, rate=10)
 
-		so = make_sales_order(item_code=bundle, qty=3)
+		quantities = [5, 2]
+		bundle, components = create_product_bundle(quantities, warehouse=warehouse)
+		bundle_items = dict(zip(components, quantities))
+
+		so = make_sales_order(item_code=bundle, qty=3, rate=42)
 
 		pl = create_pick_list(so.name)
 		pl.save()
@@ -597,14 +598,48 @@
 		for item in pl.locations:
 			self.assertEqual(item.stock_qty, bundle_items[item.item_code] * 3)
 
-	# def test_pick_list_skips_items_in_expired_batch(self):
-	# 	pass
+		# check picking status on sales order
+		pl.submit()
+		so.reload()
+		self.assertEqual(so.per_picked, 100)
 
-	# def test_pick_list_from_sales_order(self):
-	# 	pass
+		# deliver
+		dn = create_delivery_note(pl.name).submit()
+		self.assertEqual(dn.items[0].rate, 42)
+		self.assertEqual(dn.packed_items[0].warehouse, warehouse)
+		so.reload()
+		self.assertEqual(so.per_delivered, 100)
 
-	# def test_pick_list_from_work_order(self):
-	# 	pass
+	def test_picklist_with_partial_bundles(self):
+		# from test_records.json
+		warehouse = "_Test Warehouse - _TC"
 
-	# def test_pick_list_from_material_request(self):
-	# 	pass
+		quantities = [5, 2]
+		bundle, components = create_product_bundle(quantities, warehouse=warehouse)
+
+		so = make_sales_order(item_code=bundle, qty=4, rate=42)
+
+		pl = create_pick_list(so.name)
+		for loc in pl.locations:
+			loc.picked_qty = loc.qty / 2
+
+		pl.save().submit()
+		so.reload()
+		self.assertEqual(so.per_picked, 50)
+
+		# deliver half qty
+		dn = create_delivery_note(pl.name).submit()
+		self.assertEqual(dn.items[0].rate, 42)
+		so.reload()
+		self.assertEqual(so.per_delivered, 50)
+
+		pl = create_pick_list(so.name)
+		pl.save().submit()
+		so.reload()
+		self.assertEqual(so.per_picked, 100)
+
+		# deliver remaining
+		dn = create_delivery_note(pl.name).submit()
+		self.assertEqual(dn.items[0].rate, 42)
+		so.reload()
+		self.assertEqual(so.per_delivered, 100)