fix: set per_billed based on hours when amounts are zero (#33984)

* fix: set per_billed based on hours when amounts are zero

* test: calculate_percentage_billed
diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py
index e098c3e..828a55e 100644
--- a/erpnext/projects/doctype/timesheet/test_timesheet.py
+++ b/erpnext/projects/doctype/timesheet/test_timesheet.py
@@ -161,6 +161,37 @@
 		to_time = timesheet.time_logs[0].to_time
 		self.assertEqual(to_time, add_to_date(from_time, hours=2, as_datetime=True))
 
+	def test_per_billed_hours(self):
+		"""If amounts are 0, per_billed should be calculated based on hours."""
+		ts = frappe.new_doc("Timesheet")
+		ts.total_billable_amount = 0
+		ts.total_billed_amount = 0
+		ts.total_billable_hours = 2
+
+		ts.total_billed_hours = 0.5
+		ts.calculate_percentage_billed()
+		self.assertEqual(ts.per_billed, 25)
+
+		ts.total_billed_hours = 2
+		ts.calculate_percentage_billed()
+		self.assertEqual(ts.per_billed, 100)
+
+	def test_per_billed_amount(self):
+		"""If amounts are > 0, per_billed should be calculated based on amounts, regardless of hours."""
+		ts = frappe.new_doc("Timesheet")
+		ts.total_billable_hours = 2
+		ts.total_billed_hours = 1
+		ts.total_billable_amount = 200
+		ts.total_billed_amount = 50
+		ts.calculate_percentage_billed()
+		self.assertEqual(ts.per_billed, 25)
+
+		ts.total_billed_hours = 3
+		ts.total_billable_amount = 200
+		ts.total_billed_amount = 200
+		ts.calculate_percentage_billed()
+		self.assertEqual(ts.per_billed, 100)
+
 
 def make_timesheet(
 	employee,
diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py
index f3bd09a..d482a46 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.py
+++ b/erpnext/projects/doctype/timesheet/timesheet.py
@@ -64,6 +64,8 @@
 		self.per_billed = 0
 		if self.total_billed_amount > 0 and self.total_billable_amount > 0:
 			self.per_billed = (self.total_billed_amount * 100) / self.total_billable_amount
+		elif self.total_billed_hours > 0 and self.total_billable_hours > 0:
+			self.per_billed = (self.total_billed_hours * 100) / self.total_billable_hours
 
 	def update_billing_hours(self, args):
 		if args.is_billable: