fix(timesheet): scoping whitelisted methods output to projects and timesheets that are acccessible to users (#58267)

This commit is contained in:
Diptanil Saha
2026-08-30 23:16:32 +05:30
committed by GitHub
parent 1cedd1421d
commit d5df40986d

View File

@@ -311,6 +311,12 @@ def get_projectwise_timesheet_data(
tsd = frappe.qb.DocType("Timesheet Detail") tsd = frappe.qb.DocType("Timesheet Detail")
ts = frappe.qb.DocType("Timesheet") ts = frappe.qb.DocType("Timesheet")
allowed_timesheets = frappe.get_list("Timesheet", pluck="name")
allowed_projects = frappe.get_list("Project", pluck="name")
if not allowed_timesheets:
return []
query = ( query = (
frappe.qb.from_(tsd) frappe.qb.from_(tsd)
.inner_join(ts) .inner_join(ts)
@@ -332,6 +338,8 @@ def get_projectwise_timesheet_data(
& (tsd.docstatus == 1) & (tsd.docstatus == 1)
& (tsd.is_billable == 1) & (tsd.is_billable == 1)
& tsd.sales_invoice.isnull() & tsd.sales_invoice.isnull()
& (tsd.parent.isin(allowed_timesheets))
& ((tsd.project.isin(allowed_projects)) | (tsd.project.isnull()))
) )
) )
@@ -347,6 +355,11 @@ def get_projectwise_timesheet_data(
@frappe.whitelist() @frappe.whitelist()
def get_timesheet_detail_rate(timelog: str, currency: str): def get_timesheet_detail_rate(timelog: str, currency: str):
allowed_timesheets = frappe.get_list("Timesheet", pluck="name")
if not allowed_timesheets:
return 0.0
ts = frappe.qb.DocType("Timesheet") ts = frappe.qb.DocType("Timesheet")
ts_detail = frappe.qb.DocType("Timesheet Detail") ts_detail = frappe.qb.DocType("Timesheet Detail")
@@ -354,10 +367,20 @@ def get_timesheet_detail_rate(timelog: str, currency: str):
frappe.qb.from_(ts_detail) frappe.qb.from_(ts_detail)
.inner_join(ts) .inner_join(ts)
.on(ts.name == ts_detail.parent) .on(ts.name == ts_detail.parent)
.select(ts_detail.billing_amount.as_("billing_amount"), ts.currency.as_("currency")) .select(
.where(ts_detail.name == timelog) ts_detail.billing_amount.as_("billing_amount"),
ts.currency.as_("currency"),
ts.name.as_("timesheet"),
)
.where((ts_detail.name == timelog) & ts_detail.parent.isin(allowed_timesheets))
.limit(1)
.run(as_dict=1) .run(as_dict=1)
)[0] )
if not timelog_detail:
return 0.0
timelog_detail = timelog_detail[0]
if timelog_detail.currency: if timelog_detail.currency:
exchange_rate = get_exchange_rate(timelog_detail.currency, currency) exchange_rate = get_exchange_rate(timelog_detail.currency, currency)
@@ -372,6 +395,11 @@ def get_timesheet(doctype: str, txt: str, searchfield: str, start: int, page_len
if not filters: if not filters:
filters = {} filters = {}
allowed_timesheets = frappe.get_list("Timesheet", pluck="name")
if not allowed_timesheets:
return []
tsd = frappe.qb.DocType("Timesheet Detail") tsd = frappe.qb.DocType("Timesheet Detail")
ts = frappe.qb.DocType("Timesheet") ts = frappe.qb.DocType("Timesheet")
@@ -386,6 +414,7 @@ def get_timesheet(doctype: str, txt: str, searchfield: str, start: int, page_len
& (tsd.docstatus == 1) & (tsd.docstatus == 1)
& (ts.total_billable_amount > 0) & (ts.total_billable_amount > 0)
& tsd.parent.like(f"%{txt}%") & tsd.parent.like(f"%{txt}%")
& tsd.parent.isin(allowed_timesheets)
) )
) )
@@ -396,12 +425,12 @@ def get_timesheet(doctype: str, txt: str, searchfield: str, start: int, page_len
@frappe.whitelist() @frappe.whitelist()
def get_timesheet_data(name: str, project: str): def get_timesheet_data(name: str, project: str | None = None):
data = None data = None
if project and project != "": if project:
data = get_projectwise_timesheet_data(project, name) data = get_projectwise_timesheet_data(project, name)
else: else:
data = frappe.get_all( data = frappe.get_list(
"Timesheet", "Timesheet",
fields=[ fields=[
{"SUB": ["total_billable_amount", "total_billed_amount"], "as": "billing_amt"}, {"SUB": ["total_billable_amount", "total_billed_amount"], "as": "billing_amt"},