From f5d199bcb60b833346d46f717be4d4fbd4414822 Mon Sep 17 00:00:00 2001 From: Patrick Eissler <77415730+PatrickDEissler@users.noreply.github.com> Date: Fri, 19 Jun 2026 08:19:23 +0200 Subject: [PATCH] feat(Working Time): consider whole day billing in billable time --- .../doctype/working_time/test_working_time.py | 24 +++++++++++++++++++ .../doctype/working_time/working_time.py | 10 +++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/working_time/working_time/doctype/working_time/test_working_time.py b/working_time/working_time/doctype/working_time/test_working_time.py index 5b1be10..9aca062 100644 --- a/working_time/working_time/doctype/working_time/test_working_time.py +++ b/working_time/working_time/doctype/working_time/test_working_time.py @@ -106,6 +106,30 @@ def test_paid_break_totals(self): self.assertEqual(working_time.break_time, 60 * 60) self.assertEqual(working_time.working_time, 7.5 * 60 * 60) + def test_whole_day_project_billable_time(self): + working_time = self.get_working_time( + [ + { + "from_time": "09:00:00", + "to_time": "12:00:00", + "project": "Whole Day Project", + "billable": "100%", + }, + { + "from_time": "13:00:00", + "to_time": "15:00:00", + "project": "Other Project", + "billable": "50%", + }, + ] + ) + working_time.whole_day_project = "Whole Day Project" + working_time.before_validate() + + self.assertEqual(working_time.project_time, 5 * 60 * 60) + self.assertEqual(working_time.billable_time, (8 * 60 * 60) + (2 * 60 * 60 * 0.5)) + self.assertEqual(working_time.billable_pct, 180) + def test_non_break_clears_paid_break_flag(self): working_time = self.get_working_time( [ diff --git a/working_time/working_time/doctype/working_time/working_time.py b/working_time/working_time/doctype/working_time/working_time.py index f243eb6..deb2fac 100644 --- a/working_time/working_time/doctype/working_time/working_time.py +++ b/working_time/working_time/doctype/working_time/working_time.py @@ -27,6 +27,7 @@ def before_validate(self): self.project_time = self.billable_time = 0 self.project_pct = self.billable_pct = 0 + has_whole_day_logs = False last_idx = len(self.time_logs) - 1 for idx, log in enumerate(self.time_logs): log.to_time = self.time_logs[idx + 1].from_time if idx < last_idx else log.to_time @@ -44,7 +45,14 @@ def before_validate(self): self.working_time += log.duration if log.project: self.project_time += log.duration - self.billable_time += get_billable_duration(log) + if self.whole_day_project and log.project == self.whole_day_project: + has_whole_day_logs = True + else: + self.billable_time += get_billable_duration(log) + + if has_whole_day_logs: + ratio = 1 # TODO: Discuss this ratio with the team + self.billable_time += WHOLE_DAY_HOURS * ONE_HOUR * ratio if self.working_time: self.project_pct = round(self.project_time / self.working_time * 100, 0)