Merge pull request #27028 from noahjacob/prompt_warehouse_fix

fix: incorrect mandatory error message for warehouse
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 068672a..566323a 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -15,4 +15,4 @@
 5f473611bd6ed57703716244a054d3fb5ba9cd23
 
 # Whitespace fix throughout codebase
-0ef5247e2f6e9562fe837394243b71642d1d98d6
+4551d7d6029b6f587f6c99d4f8df5519241c6a86
diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js
index 3f50b41..e72c8eb 100644
--- a/erpnext/manufacturing/doctype/bom/bom.js
+++ b/erpnext/manufacturing/doctype/bom/bom.js
@@ -235,7 +235,7 @@
 						reqd: 1,
 					},
 					{
-						fieldname: "varint_item_code",
+						fieldname: "variant_item_code",
 						options: "Item",
 						label: __("Variant Item"),
 						fieldtype: "Link",
@@ -287,7 +287,7 @@
 			let variant_items = data.items || [];
 
 			variant_items.forEach(d => {
-				if (!d.varint_item_code) {
+				if (!d.variant_item_code) {
 					frappe.throw(__("Select variant item code for the template item {0}", [d.item_code]));
 				}
 			})
@@ -299,7 +299,7 @@
 		has_template_rm.forEach(d => {
 			dialog.fields_dict.items.df.data.push({
 				"item_code": d.item_code,
-				"varint_item_code": "",
+				"variant_item_code": "",
 				"qty": d.qty,
 				"source_warehouse": d.source_warehouse,
 				"operation": d.operation
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 8c27d6c..b4c6635 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -297,7 +297,7 @@
 
 		if self.total_produced_qty > 0:
 			self.status = "In Process"
-			if self.total_produced_qty == self.total_planned_qty:
+			if self.total_produced_qty >= self.total_planned_qty:
 				self.status = "Completed"
 
 		if self.status != 'Completed':
@@ -346,6 +346,7 @@
 				"production_plan"       : self.name,
 				"production_plan_item"  : d.name,
 				"product_bundle_item"	: d.product_bundle_item,
+				"planned_start_date"    : d.planned_start_date,
 				"make_work_order_for_sub_assembly_items": d.get("make_work_order_for_sub_assembly_items", 0)
 			}
 
diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
index af8de8e..a5b9ff8 100644
--- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
@@ -5,7 +5,7 @@
 
 import frappe
 import unittest
-from frappe.utils import nowdate, now_datetime, flt
+from frappe.utils import nowdate, now_datetime, flt, add_to_date
 from erpnext.stock.doctype.item.test_item import create_item
 from erpnext.manufacturing.doctype.production_plan.production_plan import get_sales_orders
 from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation
@@ -61,6 +61,21 @@
 		pln = frappe.get_doc('Production Plan', pln.name)
 		pln.cancel()
 
+	def test_production_plan_start_date(self):
+		planned_date = add_to_date(date=None, days=3)
+		plan = create_production_plan(item_code='Test Production Item 1', planned_start_date=planned_date)
+		plan.make_work_order()
+
+		work_orders = frappe.get_all('Work Order', fields = ['name', 'planned_start_date'],
+			filters = {'production_plan': plan.name})
+
+		self.assertEqual(work_orders[0].planned_start_date, planned_date)
+
+		for wo in work_orders:
+			frappe.delete_doc('Work Order', wo.name)
+
+		frappe.get_doc('Production Plan', plan.name).cancel()
+
 	def test_production_plan_for_existing_ordered_qty(self):
 		sr1 = create_stock_reconciliation(item_code="Raw Material Item 1",
 			target="_Test Warehouse - _TC", qty=1, rate=110)
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index 282b5d0..69a4b95 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -838,7 +838,7 @@
 
 	for item in variant_items:
 		args = frappe._dict({
-			"item_code": item.get("varint_item_code"),
+			"item_code": item.get("variant_item_code"),
 			"required_qty": item.get("qty"),
 			"qty": item.get("qty"), # for bom
 			"source_warehouse": item.get("source_warehouse"),
@@ -859,7 +859,7 @@
 		}, bom_doc)
 
 		if not args.source_warehouse:
-			args["source_warehouse"] = get_item_defaults(item.get("varint_item_code"),
+			args["source_warehouse"] = get_item_defaults(item.get("variant_item_code"),
 				wo_doc.company).default_warehouse
 
 		args["amount"] = flt(args.get("required_qty")) * flt(args.get("rate"))
diff --git a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py
index 89cfa16..24ca666 100644
--- a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py
+++ b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py
@@ -44,6 +44,18 @@
 		if d.item_group not in item_groups:
 			item_groups.append(d.item_group)
 
+	if item_groups:
+		child_items = []
+		for item_group in item_groups:
+			if frappe.db.get_value("Item Group", {"name":item_group}, "is_group"):
+				for child_item_group in frappe.get_all("Item Group", {"parent_item_group":item_group}):
+					if child_item_group['name'] not in child_items:
+						child_items.append(child_item_group['name'])
+
+		for item in child_items:
+			if item not in item_groups:
+				item_groups.append(item)
+
 	date_field = ("transaction_date"
 		if filters.get('doctype') == "Sales Order" else "posting_date")
 
diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py
index 56afe95..e9f4bd5 100644
--- a/erpnext/shopping_cart/cart.py
+++ b/erpnext/shopping_cart/cart.py
@@ -308,7 +308,7 @@
 	party = get_party()
 
 	party.customer_name = company_name or fullname
-	party.customer_type == "Company" if company_name else "Individual"
+	party.customer_type = "Company" if company_name else "Individual"
 
 	contact_name = frappe.db.get_value("Contact", {"email_id": frappe.session.user})
 	contact = frappe.get_doc("Contact", contact_name)