fix: update production plan status #27567

fix: update production plan status
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 7e6fc3c..2424ef9 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -311,7 +311,7 @@
 
 		if self.total_produced_qty > 0:
 			self.status = "In Process"
-			if self.total_produced_qty >= self.total_planned_qty:
+			if self.check_have_work_orders_completed():
 				self.status = "Completed"
 
 		if self.status != 'Completed':
@@ -575,6 +575,15 @@
 
 			self.append("sub_assembly_items", data)
 
+	def check_have_work_orders_completed(self):
+		wo_status = frappe.db.get_list(
+			"Work Order",
+			filters={"production_plan": self.name},
+			fields="status",
+			pluck="status"
+		)
+		return all(s == "Completed" for s in wo_status)
+
 @frappe.whitelist()
 def download_raw_materials(doc, warehouses=None):
 	if isinstance(doc, str):
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 20e54e0..1dac50c 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -308,6 +308,7 @@
 erpnext.patches.v13_0.add_default_interview_notification_templates
 erpnext.patches.v13_0.enable_scheduler_job_for_item_reposting
 erpnext.patches.v13_0.requeue_failed_reposts
+erpnext.patches.v12_0.update_production_plan_status
 erpnext.patches.v13_0.healthcare_deprecation_warning
 erpnext.patches.v14_0.delete_healthcare_doctypes
 erpnext.patches.v13_0.create_pan_field_for_india #2
diff --git a/erpnext/patches/v12_0/update_production_plan_status.py b/erpnext/patches/v12_0/update_production_plan_status.py
new file mode 100644
index 0000000..06fc503
--- /dev/null
+++ b/erpnext/patches/v12_0/update_production_plan_status.py
@@ -0,0 +1,31 @@
+# Copyright (c) 2021, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+import frappe
+
+
+def execute():
+	frappe.reload_doc("manufacturing", "doctype", "production_plan")
+	frappe.db.sql("""
+		UPDATE `tabProduction Plan` ppl
+		SET status = "Completed"
+		WHERE ppl.name IN (
+			SELECT ss.name FROM (
+				SELECT
+					(
+						count(wo.status = "Completed") =
+						count(pp.name)
+					) =
+					(
+						pp.status != "Completed"
+						AND pp.total_produced_qty >= pp.total_planned_qty
+					) AS should_set,
+					pp.name AS name
+				FROM
+					`tabWork Order` wo INNER JOIN`tabProduction Plan` pp
+					ON wo.production_plan = pp.name
+				GROUP BY pp.name
+				HAVING should_set = 1
+			) ss
+		)
+	""")