[#4420] Hook up Retainer's total_spent and profit_left for periods.

This commit is contained in:
Eric Davis
2010-09-09 14:22:25 -07:00
parent 91d8c1818e
commit 0a1bb9169d
4 changed files with 168 additions and 7 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ class FixedDeliverable < Deliverable
end
# Fixed deliverables are always 100% spent
def total_spent
def total_spent(date=nil)
total
end
+3 -3
View File
@@ -24,7 +24,7 @@ class HourlyDeliverable < Deliverable
# Total amount to be billed on the deliverable, using the total time logged
# and the contract rate
def total_spent
def total_spent(date=nil)
return 0 if contract.nil?
return 0 if contract.billable_rate.blank?
return 0 unless self.issues.count > 0
@@ -56,7 +56,7 @@ class HourlyDeliverable < Deliverable
# The amount of money remaining after expenses have been taken out
# Profit left = Total - Labor spent - Overhead spent
def profit_left
total_spent - labor_budget_spent - overhead_spent
def profit_left(date=nil)
total_spent(date) - labor_budget_spent(date) - overhead_spent(date)
end
end
+34
View File
@@ -111,6 +111,40 @@ class RetainerDeliverable < HourlyDeliverable
end
end
def total_spent(date=nil)
if date
if within_date_range?(date)
# TODO: duplicated on HourlyDeliverable#total_spent
return 0 if contract.nil?
return 0 if contract.billable_rate.blank?
return 0 unless self.issues.count > 0
issue_ids = self.issues.collect(&:id)
if issue_ids.present?
time_logs = TimeEntry.all(:conditions => ["#{Issue.table_name}.id IN (:issue_ids) AND tyear = (:year) AND tmonth = (:month)",
{:issue_ids => issue_ids,
:year => date.year,
:month => date.month}
],
:include => :issue)
end
time_logs ||= []
hours = time_logs.inject(0) {|total, time_entry|
total += time_entry.hours if time_entry.billable?
total
}
return hours * contract.billable_rate
else
0 # outside of range
end
else
super
end
end
# TODO: stolen directly from redmine_overhead but with a block option
def labor_budget_spent_with_filter(&block)
return 0.0 unless self.issues.size > 0
+130 -3
View File
@@ -271,7 +271,71 @@ class RetainerDeliverableTest < ActiveSupport::TestCase
end
end
# context "#profit_left"
# (Labor used * contract rate) - (labor used * time rate) - (overhead used * time rate)
context "#profit_left" do
setup do
@project = Project.generate!
@contract = Contract.generate!(:billable_rate => 200, :project => @project)
@deliverable = RetainerDeliverable.generate!(:start_date => '2010-01-01', :end_date => '2010-03-31', :contract => @contract)
@deliverable.labor_budgets << LaborBudget.spawn(:budget => 100, :hours => 10)
@deliverable.overhead_budgets << OverheadBudget.spawn(:budget => 100, :hours => 10)
@deliverable.save!
@manager = User.generate!
@role = Role.generate!
User.add_to_project(@manager, @project, @role)
configure_overhead_plugin
@issue1 = Issue.generate_for_project!(@project)
@time_entry1 = TimeEntry.generate!(:issue => @issue1,
:project => @project,
:activity => @billable_activity,
:spent_on => Date.new(2010,1,2),
:hours => 10,
:user => @manager)
@time_entry2 = TimeEntry.generate!(:issue => @issue1,
:project => @project,
:activity => @non_billable_activity,
:spent_on => Date.new(2010,2,1),
:hours => 20,
:user => @manager)
@rate = Rate.generate!(:project => @project,
:user => @manager,
:date_in_effect => Date.new(2010,1,1),
:amount => 100)
@deliverable.issues << @issue1
end
context "with a empty period" do
should "use all periods" do
assert_equal (10 * 200) - (10 * 100) - (20 * 100), @deliverable.profit_left(nil)
end
end
context "with a period out of the retainer range" do
should "filter the records periods" do
assert_equal 0, @deliverable.profit_left(Date.new(2011,1,1))
end
end
context "with an invalid period" do
should "return 0" do
assert_equal 0, @deliverable.profit_left('1')
end
end
context "with a period in the retainer range" do
should "filter the records" do
assert_equal (0 * 200) - (0 * 100) - (20 * 100), @deliverable.profit_left(Date.new(2010,2,1))
end
end
end
context "#profit_budget" do
setup do
@@ -311,8 +375,71 @@ class RetainerDeliverableTest < ActiveSupport::TestCase
end
# context "#total_spent"
context "#total_spent" do
setup do
@project = Project.generate!
@contract = Contract.generate!(:billable_rate => 200, :project => @project)
@deliverable = RetainerDeliverable.generate!(:start_date => '2010-01-01', :end_date => '2010-03-31', :contract => @contract)
@deliverable.labor_budgets << LaborBudget.spawn(:budget => 100, :hours => 10)
@deliverable.overhead_budgets << OverheadBudget.spawn(:budget => 100, :hours => 10)
@deliverable.save!
@manager = User.generate!
@role = Role.generate!
User.add_to_project(@manager, @project, @role)
configure_overhead_plugin
@issue1 = Issue.generate_for_project!(@project)
@time_entry1 = TimeEntry.generate!(:issue => @issue1,
:project => @project,
:activity => @billable_activity,
:spent_on => Date.new(2010,1,2),
:hours => 10,
:user => @manager)
@time_entry2 = TimeEntry.generate!(:issue => @issue1,
:project => @project,
:activity => @billable_activity,
:spent_on => Date.new(2010,2,1),
:hours => 20,
:user => @manager)
@rate = Rate.generate!(:project => @project,
:user => @manager,
:date_in_effect => Date.new(2010,1,1),
:amount => 100)
@deliverable.issues << @issue1
end
context "with a empty period" do
should "use all periods" do
# Labor used * contract rate
assert_equal (10+20) * 200, @deliverable.total_spent(nil)
end
end
context "with a period out of the retainer range" do
should "filter the records periods" do
assert_equal 0, @deliverable.total_spent(Date.new(2011,1,1))
end
end
context "with an invalid period" do
should "return 0" do
assert_equal 0, @deliverable.total_spent('1')
end
end
context "with a period in the retainer range" do
should "filter the records" do
assert_equal 20 * 200, @deliverable.total_spent(Date.new(2010,2,1))
end
end
end
context "#total" do
setup do
@contract = Contract.generate!(:billable_rate => 100)