From ea1c4661341a1a000107ce989ba6e01c3632f8c6 Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Tue, 4 Aug 2009 15:28:50 -0700 Subject: [PATCH] [#2844] Added an API to get the total number of billable and overhead hours. * Added Issue#billable_time_spent * Added Issue#overhead_time_spent * Added specs --- init.rb | 2 + lib/overhead_issue_patch.rb | 38 +++++++++++++ spec/lib/overhead_issue_patch_spec.rb | 80 +++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 lib/overhead_issue_patch.rb create mode 100644 spec/lib/overhead_issue_patch_spec.rb diff --git a/init.rb b/init.rb index 2d2a84d..ed1fe90 100644 --- a/init.rb +++ b/init.rb @@ -2,9 +2,11 @@ require 'redmine' # Patches to the Redmine core. require 'dispatcher' +require 'overhead_issue_patch' require 'overhead_time_entry_patch' require 'overhead_time_entry_activity_patch' Dispatcher.to_prepare do + Issue.send(:include, OverheadIssuePatch) TimeEntry.send(:include, OverheadTimeEntryPatch) TimeEntryActivity.send(:include, OverheadTimeEntryActivityPatch) end diff --git a/lib/overhead_issue_patch.rb b/lib/overhead_issue_patch.rb new file mode 100644 index 0000000..04705de --- /dev/null +++ b/lib/overhead_issue_patch.rb @@ -0,0 +1,38 @@ +require_dependency 'issue' + +module OverheadIssuePatch + def self.included(base) + base.send(:include, InstanceMethods) + + base.class_eval do + unloadable + end + end + + module InstanceMethods + def billable_time_spent + time_entry_hours_based_on_billable_flag(true) + end + + def overhead_time_spent + time_entry_hours_based_on_billable_flag(false) + end + + private + # Totals time_entries that are billable (true) or overhead (false) + # and returns the rounded value + def time_entry_hours_based_on_billable_flag(billable_flag=true) + time = time_entries.inject(0.0) {|sum, time_entry| + sum += time_entry.hours if time_entry.billable? == billable_flag + sum + } + if time > 0 + return time.round(1) + else + return 0 + end + + end + end +end + diff --git a/spec/lib/overhead_issue_patch_spec.rb b/spec/lib/overhead_issue_patch_spec.rb new file mode 100644 index 0000000..ecede72 --- /dev/null +++ b/spec/lib/overhead_issue_patch_spec.rb @@ -0,0 +1,80 @@ +require File.dirname(__FILE__) + '/../spec_helper' + +def mock_time_entry(hours, billable) + mock_model(TimeEntry, :hours => hours.to_f, :billable? => billable) +end + +describe Issue, '#billable_time_spent' do + it 'should total the billable time entries' do + time_entries = [mock_time_entry(12, true), + mock_time_entry(13, true)] + + issue = Issue.new + issue.should_receive(:time_entries).and_return(time_entries) + issue.billable_time_spent.should eql(25.0) + end + + it 'should not include overhead time entries' do + time_entries = [mock_time_entry(12, true), + mock_time_entry(13, true), + mock_time_entry(20, false), + mock_time_entry(40, false)] + + issue = Issue.new + issue.should_receive(:time_entries).and_return(time_entries) + issue.billable_time_spent.should eql(25.0) + end + + it 'should round to the tenths place' do + time_entries = [mock_time_entry(20, true), + mock_time_entry(13.333333, true)] + + issue = Issue.new + issue.should_receive(:time_entries).and_return(time_entries) + issue.billable_time_spent.should eql(33.3) + + end + + it 'should return 0 if there are no time entries' do + issue = Issue.new + issue.billable_time_spent.should eql(0) + end +end + +describe Issue, '#overhead_time_spent' do + it 'should total the overhead time entries' do + time_entries = [mock_time_entry(12, false), + mock_time_entry(13, false)] + + issue = Issue.new + issue.should_receive(:time_entries).and_return(time_entries) + issue.overhead_time_spent.should eql(25.0) + end + + it 'should not include billable time entries' do + time_entries = [mock_time_entry(12, true), + mock_time_entry(13, true), + mock_time_entry(20, false), + mock_time_entry(40, false)] + + issue = Issue.new + issue.should_receive(:time_entries).and_return(time_entries) + issue.overhead_time_spent.should eql(60.0) + end + + it 'should round to the tenths place' do + time_entries = [mock_time_entry(20, false), + mock_time_entry(13.333333, false)] + + issue = Issue.new + issue.should_receive(:time_entries).and_return(time_entries) + issue.overhead_time_spent.should eql(33.3) + + end + + it 'should return 0 if there are no time entries' do + issue = Issue.new + issue.overhead_time_spent.should eql(0) + end +end +