[#2863] Override the deliverable rows from the budget plugin to show
labor budget spent. * Added FixedDeliverable#labor_budget_spent * Added HourlyDeliverable#labor_budget_spent * Added an _deliverable_summary_row.html.erb with the new method
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
<%= content_tag(:td, h(deliverable.subject), :class => 'subject') %>
|
<%= content_tag(:td, h(deliverable.subject), :class => 'subject') %>
|
||||||
<%= content_tag(:td, number_to_currency(deliverable.budget || 0.0, :precision => 0), :class => 'budget') if allowed_management? %>
|
<%= content_tag(:td, number_to_currency(deliverable.budget || 0.0, :precision => 0), :class => 'budget') if allowed_management? %>
|
||||||
<%= content_tag(:td, number_to_currency(deliverable.labor_budget || 0.0, :precision => 0), :class => 'budget') if allowed_management? %>
|
<%= content_tag(:td, number_to_currency(deliverable.labor_budget || 0.0, :precision => 0), :class => 'budget') if allowed_management? %>
|
||||||
<%= content_tag(:td, number_to_currency(deliverable.spent, :precision => 0), :class => 'spent') if allowed_management? %>
|
<%= content_tag(:td, number_to_currency(deliverable.labor_budget_spent, :precision => 0), :class => 'spent') if allowed_management? %>
|
||||||
<%= content_tag(:td, format_date(deliverable.due), :class => 'due_date') %>
|
<%= content_tag(:td, format_date(deliverable.due), :class => 'due_date') %>
|
||||||
<%= content_tag(:td, progress_bar(deliverable.progress, :width => '100%', :class => 'done_ratio')) %>
|
<%= content_tag(:td, progress_bar(deliverable.progress, :width => '100%', :class => 'done_ratio')) %>
|
||||||
<%= Redmine::Hook.call_hook(:plugin_budget_view_deliverable_summary_row, { :deliverable => deliverable }) %>
|
<%= Redmine::Hook.call_hook(:plugin_budget_view_deliverable_summary_row, { :deliverable => deliverable }) %>
|
||||||
|
|||||||
4
init.rb
4
init.rb
@@ -3,11 +3,15 @@ require 'redmine'
|
|||||||
# Patches to the Redmine core.
|
# Patches to the Redmine core.
|
||||||
require 'dispatcher'
|
require 'dispatcher'
|
||||||
require 'overhead_deliverable_patch'
|
require 'overhead_deliverable_patch'
|
||||||
|
require 'overhead_hourly_deliverable_patch'
|
||||||
|
require 'overhead_fixed_deliverable_patch'
|
||||||
require 'overhead_issue_patch'
|
require 'overhead_issue_patch'
|
||||||
require 'overhead_time_entry_patch'
|
require 'overhead_time_entry_patch'
|
||||||
require 'overhead_time_entry_activity_patch'
|
require 'overhead_time_entry_activity_patch'
|
||||||
Dispatcher.to_prepare do
|
Dispatcher.to_prepare do
|
||||||
Deliverable.send(:include, OverheadDeliverablePatch)
|
Deliverable.send(:include, OverheadDeliverablePatch)
|
||||||
|
HourlyDeliverable.send(:include, OverheadHourlyDeliverablePatch)
|
||||||
|
FixedDeliverable.send(:include, OverheadFixedDeliverablePatch)
|
||||||
Issue.send(:include, OverheadIssuePatch)
|
Issue.send(:include, OverheadIssuePatch)
|
||||||
TimeEntry.send(:include, OverheadTimeEntryPatch)
|
TimeEntry.send(:include, OverheadTimeEntryPatch)
|
||||||
TimeEntryActivity.send(:include, OverheadTimeEntryActivityPatch)
|
TimeEntryActivity.send(:include, OverheadTimeEntryActivityPatch)
|
||||||
|
|||||||
32
lib/overhead_fixed_deliverable_patch.rb
Normal file
32
lib/overhead_fixed_deliverable_patch.rb
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
require_dependency 'deliverable'
|
||||||
|
require_dependency 'fixed_deliverable'
|
||||||
|
|
||||||
|
module OverheadFixedDeliverablePatch
|
||||||
|
def self.included(base)
|
||||||
|
base.send(:include, InstanceMethods)
|
||||||
|
|
||||||
|
base.class_eval do
|
||||||
|
unloadable
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module InstanceMethods
|
||||||
|
# Amount of "billable" money spent on issues. Similar to +spent+
|
||||||
|
# but only billable time.
|
||||||
|
def labor_budget_spent
|
||||||
|
return 0.0 if self.fixed_cost.nil?
|
||||||
|
return self.fixed_cost unless self.issues.size > 0
|
||||||
|
|
||||||
|
# Get all timelogs assigned
|
||||||
|
time_logs = self.issues.collect(&:time_entries).flatten
|
||||||
|
|
||||||
|
return fixed_cost + time_logs.collect {|time_log|
|
||||||
|
if time_log.billable?
|
||||||
|
time_log.cost
|
||||||
|
else
|
||||||
|
0.0
|
||||||
|
end
|
||||||
|
}.sum
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
33
lib/overhead_hourly_deliverable_patch.rb
Normal file
33
lib/overhead_hourly_deliverable_patch.rb
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
require_dependency 'deliverable'
|
||||||
|
require_dependency 'hourly_deliverable'
|
||||||
|
|
||||||
|
module OverheadHourlyDeliverablePatch
|
||||||
|
def self.included(base)
|
||||||
|
base.send(:include, InstanceMethods)
|
||||||
|
|
||||||
|
base.class_eval do
|
||||||
|
unloadable
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module InstanceMethods
|
||||||
|
# Amount of "billable" money spent on issues. Similar to +spent+
|
||||||
|
# but only billable time.
|
||||||
|
def labor_budget_spent
|
||||||
|
return 0.0 unless self.issues.size > 0
|
||||||
|
total = 0.0
|
||||||
|
|
||||||
|
# Get all timelogs assigned
|
||||||
|
time_logs = self.issues.collect(&:time_entries).flatten
|
||||||
|
|
||||||
|
return time_logs.collect {|time_log|
|
||||||
|
if time_log.billable?
|
||||||
|
time_log.cost
|
||||||
|
else
|
||||||
|
0.0
|
||||||
|
end
|
||||||
|
}.sum
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
39
spec/lib/overhead_fixed_deliverable_patch_spec.rb
Normal file
39
spec/lib/overhead_fixed_deliverable_patch_spec.rb
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
require File.dirname(__FILE__) + '/../spec_helper'
|
||||||
|
|
||||||
|
describe FixedDeliverable, '#labor_budget_spent' do
|
||||||
|
def mock_issues_and_time_entries
|
||||||
|
@deliverable.should_receive(:issues).at_least(:once).and_return do
|
||||||
|
issue1 = mock_model(Issue, :time_entries => [
|
||||||
|
mock_model(TimeEntry, :cost => 100, :billable? => true),
|
||||||
|
mock_model(TimeEntry, :cost => 200, :billable? => false),
|
||||||
|
mock_model(TimeEntry, :cost => 50, :billable? => true)
|
||||||
|
])
|
||||||
|
issue2 = mock_model(Issue, :time_entries => [
|
||||||
|
mock_model(TimeEntry, :cost => 1000, :billable? => true),
|
||||||
|
mock_model(TimeEntry, :cost => 2000, :billable? => false),
|
||||||
|
mock_model(TimeEntry, :cost => 5000, :billable? => true)
|
||||||
|
])
|
||||||
|
[issue1, issue2]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
@deliverable = FixedDeliverable.new :fixed_cost => 0
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be 0 if there are no assigned issues' do
|
||||||
|
@deliverable.should_receive(:issues).and_return([])
|
||||||
|
@deliverable.labor_budget_spent.should eql(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should total all billable time entries' do
|
||||||
|
mock_issues_and_time_entries
|
||||||
|
@deliverable.labor_budget_spent.should eql(6150.0)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should total the billable time entries to the fixed_cost' do
|
||||||
|
mock_issues_and_time_entries
|
||||||
|
@deliverable.should_receive(:fixed_cost).at_least(:once).and_return(5000)
|
||||||
|
@deliverable.labor_budget_spent.should eql(11_150.0)
|
||||||
|
end
|
||||||
|
end
|
||||||
28
spec/lib/overhead_hourly_deliverable_patch_spec.rb
Normal file
28
spec/lib/overhead_hourly_deliverable_patch_spec.rb
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
require File.dirname(__FILE__) + '/../spec_helper'
|
||||||
|
|
||||||
|
describe HourlyDeliverable, '#labor_budget_spent' do
|
||||||
|
it 'should be 0 if there are no assigned issues' do
|
||||||
|
deliverable = HourlyDeliverable.new
|
||||||
|
deliverable.should_receive(:issues).and_return([])
|
||||||
|
deliverable.labor_budget_spent.should eql(0.0)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should total all billable time entries' do
|
||||||
|
deliverable = HourlyDeliverable.new
|
||||||
|
deliverable.should_receive(:issues).at_least(:once).and_return do
|
||||||
|
issue1 = mock_model(Issue, :time_entries => [
|
||||||
|
mock_model(TimeEntry, :cost => 100, :billable? => true),
|
||||||
|
mock_model(TimeEntry, :cost => 200, :billable? => false),
|
||||||
|
mock_model(TimeEntry, :cost => 50, :billable? => true)
|
||||||
|
])
|
||||||
|
issue2 = mock_model(Issue, :time_entries => [
|
||||||
|
mock_model(TimeEntry, :cost => 1000, :billable? => true),
|
||||||
|
mock_model(TimeEntry, :cost => 2000, :billable? => false),
|
||||||
|
mock_model(TimeEntry, :cost => 5000, :billable? => true)
|
||||||
|
])
|
||||||
|
[issue1, issue2]
|
||||||
|
end
|
||||||
|
|
||||||
|
deliverable.labor_budget_spent.should eql(6150.0)
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user