Set billing hours to 0 in timesheet #9535 (#10139)

* `update_billing_hours` to use flt not cint

* if not billable, reset billable hours

* if not billable, reset time rates

* test
diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py
index 1db0610..955a2b0 100644
--- a/erpnext/projects/doctype/timesheet/test_timesheet.py
+++ b/erpnext/projects/doctype/timesheet/test_timesheet.py
@@ -14,8 +14,8 @@
 
 class TestTimesheet(unittest.TestCase):
 	def test_timesheet_billing_amount(self):
-		salary_structure = make_salary_structure("_T-Employee-0001")
-		timesheet = make_timesheet("_T-Employee-0001", simulate = True, billable=1)
+		make_salary_structure("_T-Employee-0001")
+		timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=1)
 
 		self.assertEquals(timesheet.total_hours, 2)
 		self.assertEquals(timesheet.total_billable_hours, 2)
@@ -23,6 +23,16 @@
 		self.assertEquals(timesheet.time_logs[0].billing_amount, 100)
 		self.assertEquals(timesheet.total_billable_amount, 100)
 
+	def test_timesheet_billing_amount_not_billable(self):
+		make_salary_structure("_T-Employee-0001")
+		timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=0)
+
+		self.assertEquals(timesheet.total_hours, 2)
+		self.assertEquals(timesheet.total_billable_hours, 0)
+		self.assertEquals(timesheet.time_logs[0].billing_rate, 0)
+		self.assertEquals(timesheet.time_logs[0].billing_amount, 0)
+		self.assertEquals(timesheet.total_billable_amount, 0)
+
 	def test_salary_slip_from_timesheet(self):
 		salary_structure = make_salary_structure("_T-Employee-0001")
 		timesheet = make_timesheet("_T-Employee-0001", simulate = True, billable=1)
@@ -43,7 +53,7 @@
 		self.assertEquals(timesheet.status, 'Submitted')
 
 	def test_sales_invoice_from_timesheet(self):
-		timesheet = make_timesheet("_T-Employee-0001", simulate = True, billable = 1)
+		timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=1)
 		sales_invoice = make_sales_invoice(timesheet.name)
 		sales_invoice.customer = "_Test Customer"
 		sales_invoice.due_date = nowdate()
diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js
index 441ab1a..9b330e7 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.js
+++ b/erpnext/projects/doctype/timesheet/timesheet.js
@@ -105,7 +105,9 @@
 	},
 
 	billable: function(frm, cdt, cdn) {
-		calculate_billing_costing_amount(frm, cdt, cdn)
+		update_billing_hours(frm, cdt, cdn);
+		update_time_rates(frm, cdt, cdn);
+		calculate_billing_costing_amount(frm, cdt, cdn);
 	},
 
 	activity_type: function(frm, cdt, cdn) {
@@ -148,8 +150,21 @@
 	}
 }
 
+var update_billing_hours = function(frm, cdt, cdn){
+	var child = locals[cdt][cdn];
+	if(!child.billable) frappe.model.set_value(cdt, cdn, 'billing_hours', 0.0);
+}
+
+var update_time_rates = function(frm, cdt, cdn){
+	var child = locals[cdt][cdn];
+	if(!child.billable){
+		frappe.model.set_value(cdt, cdn, 'billing_rate', 0.0);
+		frappe.model.set_value(cdt, cdn, 'costing_rate', 0.0);
+	}
+}
+
 var calculate_billing_costing_amount = function(frm, cdt, cdn){
-	var child = locals[cdt][cdn]
+	var child = locals[cdt][cdn];
 	var billing_amount = 0.0;
 	var costing_amount = 0.0;
 
@@ -160,7 +175,7 @@
 
 	frappe.model.set_value(cdt, cdn, 'billing_amount', billing_amount);
 	frappe.model.set_value(cdt, cdn, 'costing_amount', costing_amount);
-	calculate_time_and_amount(frm)
+	calculate_time_and_amount(frm);
 }
 
 var calculate_time_and_amount = function(frm) {
diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py
index 6416176..bb3d902 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.py
+++ b/erpnext/projects/doctype/timesheet/timesheet.py
@@ -46,6 +46,7 @@
 
 		for d in self.get("time_logs"):
 			self.update_billing_hours(d)
+			self.update_time_rates(d)
 
 			self.total_hours += flt(d.hours)
 			if d.billable:
@@ -61,8 +62,11 @@
 			self.per_billed = (self.total_billed_amount * 100) / self.total_billable_amount
 
 	def update_billing_hours(self, args):
-		if cint(args.billing_hours) == 0:
-			args.billing_hours = args.hours
+		if args.billable:
+			if flt(args.billing_hours) == 0.0:
+				args.billing_hours = args.hours
+		else:
+			args.billing_hours = 0
 
 	def set_status(self):
 		self.status = {
@@ -263,13 +267,19 @@
 		for data in self.time_logs:
 			if data.activity_type and data.billable:
 				rate = get_activity_cost(self.employee, data.activity_type)
-				hours =  data.billing_hours or 0
+				hours = data.billing_hours or 0
 				if rate:
 					data.billing_rate = flt(rate.get('billing_rate')) if flt(data.billing_rate) == 0 else data.billing_rate
 					data.costing_rate = flt(rate.get('costing_rate')) if flt(data.costing_rate) == 0 else data.costing_rate
 					data.billing_amount = data.billing_rate * hours
 					data.costing_amount = data.costing_rate * hours
 
+	def update_time_rates(self, ts_detail):
+		if not ts_detail.billable:
+			ts_detail.billing_rate = 0.0
+			ts_detail.costing_rate = 0.0
+
+
 @frappe.whitelist()
 def get_projectwise_timesheet_data(project, parent=None):
 	cond = ''