Merge pull request #19853 from rohitwaghchaure/fixed_production_plan_items_required_to_pull_mr

fix: 'NoneType' object is not iterable
diff --git a/erpnext/projects/doctype/project/project.js b/erpnext/projects/doctype/project/project.js
index 25c97d1..3570a0f 100644
--- a/erpnext/projects/doctype/project/project.js
+++ b/erpnext/projects/doctype/project/project.js
@@ -4,20 +4,16 @@
 	setup(frm) {
 		frm.make_methods = {
 			'Timesheet': () => {
-				let doctype = 'Timesheet';
-				frappe.model.with_doctype(doctype, () => {
-					let new_doc = frappe.model.get_new_doc(doctype);
-
-					// add a new row and set the project
-					let time_log = frappe.model.get_new_doc('Timesheet Detail');
-					time_log.project = frm.doc.name;
-					time_log.parent = new_doc.name;
-					time_log.parentfield = 'time_logs';
-					time_log.parenttype = 'Timesheet';
-					new_doc.time_logs = [time_log];
-
-					frappe.ui.form.make_quick_entry(doctype, null, null, new_doc);
-				});
+				open_form(frm, "Timesheet", "Timesheet Detail", "time_logs");
+			},
+			'Purchase Order': () => {
+				open_form(frm, "Purchase Order", "Purchase Order Item", "items");
+			},
+			'Purchase Receipt': () => {
+				open_form(frm, "Purchase Receipt", "Purchase Receipt Item", "items");
+			},
+			'Purchase Invoice': () => {
+				open_form(frm, "Purchase Invoice", "Purchase Invoice Item", "items");
 			},
 		};
 	},
@@ -80,7 +76,7 @@
 				frm.events.set_status(frm, 'Cancelled');
 			}, __('Set Status'));
 		}
-		
+
 		if (frappe.model.can_read("Task")) {
 			frm.add_custom_button(__("Gantt Chart"), function () {
 				frappe.route_options = {
@@ -123,3 +119,20 @@
 	},
 
 });
+
+function open_form(frm, doctype, child_doctype, parentfield) {
+	frappe.model.with_doctype(doctype, () => {
+		let new_doc = frappe.model.get_new_doc(doctype);
+
+		// add a new row and set the project
+		let new_child_doc = frappe.model.get_new_doc(child_doctype);
+		new_child_doc.project = frm.doc.name;
+		new_child_doc.parent = new_doc.name;
+		new_child_doc.parentfield = parentfield;
+		new_child_doc.parenttype = doctype;
+		new_doc[parentfield] = [new_child_doc];
+
+		frappe.ui.form.make_quick_entry(doctype, null, null, new_doc);
+	});
+
+}
\ No newline at end of file
diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py
index c4481c9..e908216 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.py
+++ b/erpnext/projects/doctype/timesheet/timesheet.py
@@ -188,7 +188,8 @@
 			}, as_dict=True)
 		# check internal overlap
 		for time_log in self.time_logs:
-			if not (time_log.from_time or time_log.to_time): continue
+			if not (time_log.from_time and time_log.to_time
+				and args.from_time and args.to_time): continue
 
 			if (fieldname != 'workstation' or args.get(fieldname) == time_log.get(fieldname)) and \
 				args.idx != time_log.idx and ((args.from_time > time_log.from_time and args.from_time < time_log.to_time) or
diff --git a/erpnext/regional/report/gstr_1/gstr_1.js b/erpnext/regional/report/gstr_1/gstr_1.js
index ce55921..1a7ff2b 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.js
+++ b/erpnext/regional/report/gstr_1/gstr_1.js
@@ -55,14 +55,25 @@
 		report.page.add_inner_button(__("Download as JSON"), function () {
 			var filters = report.get_values();
 
-			const args = {
-				cmd: 'erpnext.regional.report.gstr_1.gstr_1.get_json',
-				data: report.data,
-				report_name: report.report_name,
-				filters: filters
-			};
-
-			open_url_post(frappe.request.url, args);
+			frappe.call({
+				method: 'erpnext.regional.report.gstr_1.gstr_1.get_json',
+				args: {
+					data: report.data,
+					report_name: report.report_name,
+					filters: filters
+				},
+				callback: function(r) {
+					if (r.message) {
+						const args = {
+							cmd: 'erpnext.regional.report.gstr_1.gstr_1.download_json_file',
+							data: r.message.data,
+							report_name: r.message.report_name,
+							report_type: r.message.report_type
+						};
+						open_url_post(frappe.request.url, args);
+					}
+				}
+			});
 		});
 	}
 }
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index 090616b..4f9cc7f 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -532,16 +532,9 @@
 		self.columns = self.invoice_columns + self.tax_columns + self.other_columns
 
 @frappe.whitelist()
-def get_json():
-	data = frappe._dict(frappe.local.form_dict)
-
-	del data["cmd"]
-	if "csrf_token" in data:
-		del data["csrf_token"]
-
-	filters = json.loads(data["filters"])
-	report_data = json.loads(data["data"])
-	report_name = data["report_name"]
+def get_json(filters, report_name, data):
+	filters = json.loads(filters)
+	report_data = json.loads(data)
 	gstin = get_company_gstin_number(filters["company"])
 
 	fp = "%02d%s" % (getdate(filters["to_date"]).month, getdate(filters["to_date"]).year)
@@ -575,7 +568,11 @@
 		out = get_export_json(res)
 		gst_json["exp"] = out
 
-	download_json_file(report_name, filters["type_of_business"], gst_json)
+	return {
+		'report_name': report_name,
+		'report_type': filters['type_of_business'],
+		'data': gst_json
+	}
 
 def get_b2b_json(res, gstin):
 	inv_type, out = {"Registered Regular": "R", "Deemed Export": "DE", "URD": "URD", "SEZ": "SEZ"}, []
@@ -722,11 +719,15 @@
 	if gstin:
 		return gstin[0]["gstin"]
 	else:
-		frappe.throw(_("Please set valid GSTIN No. in Company Address"))
+		frappe.throw(_("Please set valid GSTIN No. in Company Address for company {0}".format(
+			frappe.bold(company)
+		)))
 
-def download_json_file(filename, report_type, data):
+@frappe.whitelist()
+def download_json_file():
 	''' download json content in a file '''
-	frappe.response['filename'] = frappe.scrub("{0} {1}".format(filename, report_type)) + '.json'
-	frappe.response['filecontent'] = json.dumps(data)
+	data = frappe._dict(frappe.local.form_dict)
+	frappe.response['filename'] = frappe.scrub("{0} {1}".format(data['report_name'], data['report_type'])) + '.json'
+	frappe.response['filecontent'] = data['data']
 	frappe.response['content_type'] = 'application/json'
 	frappe.response['type'] = 'download'
diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py
index 831381c..5341f29 100644
--- a/erpnext/stock/doctype/packed_item/packed_item.py
+++ b/erpnext/stock/doctype/packed_item/packed_item.py
@@ -65,7 +65,7 @@
 	bin = get_bin_qty(packing_item_code, pi.warehouse)
 	pi.actual_qty = flt(bin.get("actual_qty"))
 	pi.projected_qty = flt(bin.get("projected_qty"))
-	if old_packed_items_map:
+	if old_packed_items_map and old_packed_items_map.get((packing_item_code, main_item_row.item_code)):
 		pi.batch_no = old_packed_items_map.get((packing_item_code, main_item_row.item_code))[0].batch_no
 		pi.serial_no = old_packed_items_map.get((packing_item_code, main_item_row.item_code))[0].serial_no
 		pi.warehouse = old_packed_items_map.get((packing_item_code, main_item_row.item_code))[0].warehouse