fix: validate job card
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.js b/erpnext/manufacturing/doctype/job_card/job_card.js
index 35be388..df35028 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.js
+++ b/erpnext/manufacturing/doctype/job_card/job_card.js
@@ -28,6 +28,11 @@
 		frappe.flags.resume_job = 0;
 		let has_items = frm.doc.items && frm.doc.items.length;
 
+		if (frm.doc.__onload.work_order_stopped) {
+			frm.disable_save();
+			return
+		}
+
 		if (!frm.doc.__islocal && has_items && frm.doc.docstatus < 2) {
 			let to_request = frm.doc.for_quantity > frm.doc.transferred_qty;
 			let excess_transfer_allowed = frm.doc.__onload.job_card_excess_transfer;
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py
index e1d79be..dd1df20 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/job_card.py
@@ -37,6 +37,7 @@
 	def onload(self):
 		excess_transfer = frappe.db.get_single_value("Manufacturing Settings", "job_card_excess_transfer")
 		self.set_onload("job_card_excess_transfer", excess_transfer)
+		self.set_onload("work_order_stopped", self.is_work_order_stopped())
 
 	def validate(self):
 		self.validate_time_logs()
@@ -45,6 +46,7 @@
 		self.validate_sequence_id()
 		self.set_sub_operations()
 		self.update_sub_operation_status()
+		self.validate_work_order()
 
 	def set_sub_operations(self):
 		if self.operation:
@@ -549,6 +551,18 @@
 				frappe.throw(_("{0}, complete the operation {1} before the operation {2}.")
 					.format(message, bold(row.operation), bold(self.operation)), OperationSequenceError)
 
+	def validate_work_order(self):
+		if self.is_work_order_stopped():
+			frappe.throw(_("You can't make any changes to Job Card since Work Order is stopped."))
+
+	def is_work_order_stopped(self):
+		if self.work_order:
+			status = frappe.get_value('Work Order', self.work_order)
+
+			if status == "Closed":
+				return True
+
+		return False
 
 @frappe.whitelist()
 def make_time_log(args):
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index b6a8700..3dbbf31 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -802,8 +802,43 @@
 				self.assertEqual(row.qty, 1)
 
 	def test_close_work_order(self):
-		close_work_order(self.wo_order.name, "Closed")
-		self.assertEqual(self.wo_order.status, "Closed")
+		items = ['Test FG Item for Closed WO', 'Test RM Item 1 for Closed WO',
+			'Test RM Item 2 for Closed WO']
+
+		company = '_Test Company with perpetual inventory'
+		for item_code in items:
+			create_item(item_code = item_code, is_stock_item = 1,
+				is_purchase_item=1, opening_stock=100, valuation_rate=10, company=company, warehouse='Stores - TCP1')
+
+		item = 'Test FG Item for Closed WO'
+		raw_materials = ['Test RM Item 1 for Closed WO', 'Test RM Item 2 for Closed WO']
+		if not frappe.db.get_value('BOM', {'item': item}):
+			bom = make_bom(item=item, source_warehouse='Stores - TCP1', raw_materials=raw_materials, do_not_save=True)
+			bom.with_operations = 1
+			bom.append('operations', {
+				'operation': '_Test Operation 1',
+				'workstation': '_Test Workstation 1',
+				'hour_rate': 20,
+				'time_in_mins': 60
+			})
+
+			bom.submit()
+
+		wo_order = make_wo_order_test_record(item=item, company=company, planned_start_date=now(), qty=20, skip_transfer=1)
+		job_cards = frappe.db.get_value('Job Card', {'work_order': wo_order.name}, 'name')
+		
+		for jc in job_cards:
+			job_card_doc = frappe.get_doc('Job Card', jc)
+			job_card_doc.append('time_logs', {
+				'from_time': now(),
+				'time_in_mins': 60,
+				'completed_qty': job_card_doc.for_quantity
+			})
+
+			job_card_doc.submit()
+
+		close_work_order(wo_order, "Closed")
+		self.assertEqual(wo_order.get('status'), "Closed")
 
 def update_job_card(job_card):
 	job_card_doc = frappe.get_doc('Job Card', job_card)