feat: provistion to pull timesheet in sales invoice
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index d3e8a44..b361c0c 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -695,6 +695,7 @@
 				refresh_field(['timesheets'])
 			}
 		})
+		frm.refresh();
 	},
 
 	onload: function(frm) {
@@ -810,6 +811,65 @@
 	},
 
 	refresh: function(frm) {
+		if (frm.doc.project) {
+			frm.add_custom_button(__('Fetch Timesheet'), function() {
+				let d = new frappe.ui.Dialog({
+					title: __('Fetch Timesheet'),
+					fields: [
+						{
+							"label" : "From",
+							"fieldname": "from_time",
+							"fieldtype": "Date",
+							"reqd": 1,
+						},
+						{
+							fieldtype: 'Column Break',
+							fieldname: 'col_break_1',
+						},
+						{
+							"label" : "To",
+							"fieldname": "to_time",
+							"fieldtype": "Date",
+							"reqd": 1,
+						}
+					],
+					primary_action: function() {
+						let data = d.get_values();
+						frappe.call({
+							method: "erpnext.projects.doctype.timesheet.timesheet.get_projectwise_timesheet_data",
+							args: {
+								from_time: data.from_time,
+								to_time: data.to_time,
+								project: frm.doc.project
+							},
+							callback: function(r) {
+								if(!r.exc) {
+									if(r.message.length > 0) {
+										frm.clear_table('timesheets')
+										r.message.forEach((d) => {
+											frm.add_child('timesheets',{
+												'time_sheet': d.parent,
+												'billing_hours': d.billing_hours,
+												'billing_amount': d.billing_amt,
+												'timesheet_detail': d.name
+											});
+										});
+										frm.refresh_field('timesheets')
+									}
+									else {
+										frappe.msgprint(__('No Timesheet Found.'))
+									}
+									d.hide();
+								}
+							}
+						});
+					},
+					primary_action_label: __('Get Timesheets')
+				});
+				d.show();
+			})
+		}
+
 		if (frappe.boot.active_domains.includes("Healthcare")) {
 			frm.set_df_property("patient", "hidden", 0);
 			frm.set_df_property("patient_name", "hidden", 0);
diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py
index ea81b3e..ed02f79 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.py
+++ b/erpnext/projects/doctype/timesheet/timesheet.py
@@ -204,14 +204,16 @@
 			ts_detail.billing_rate = 0.0
 
 @frappe.whitelist()
-def get_projectwise_timesheet_data(project, parent=None):
-	cond = ''
+def get_projectwise_timesheet_data(project, parent=None, from_time=None, to_time=None):
+	condition = ''
 	if parent:
-		cond = "and parent = %(parent)s"
+		condition = "AND parent = %(parent)s"
+	if from_time and to_time:
+		condition += "AND from_time BETWEEN %(from_time)s AND %(to_time)s"
 
 	return frappe.db.sql("""select name, parent, billing_hours, billing_amount as billing_amt
 			from `tabTimesheet Detail` where parenttype = 'Timesheet' and docstatus=1 and project = %(project)s {0} and billable = 1
-			and sales_invoice is null""".format(cond), {'project': project, 'parent': parent}, as_dict=1)
+			and sales_invoice is null""".format(condition), {'project': project, 'parent': parent, 'from_time': from_time, 'to_time': to_time}, as_dict=1)
 
 @frappe.whitelist()
 @frappe.validate_and_sanitize_search_inputs