From 82dec74eb758911f664d1a0c75d26d2d7c60383a Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Wed, 8 Sep 2010 15:39:34 -0700 Subject: [PATCH] [#4420] Changed the approach for Retainer calculations by using an optional parameter. --- app/models/deliverable.rb | 20 +++-- app/models/fixed_deliverable.rb | 8 +- app/models/hourly_deliverable.rb | 10 +-- app/models/retainer_deliverable.rb | 20 ++++- test/unit/deliverable_test.rb | 33 -------- test/unit/retainer_deliverable_test.rb | 106 +++++++++++++++++++++---- 6 files changed, 127 insertions(+), 70 deletions(-) diff --git a/app/models/deliverable.rb b/app/models/deliverable.rb index 6b89ba6..b668ff1 100644 --- a/app/models/deliverable.rb +++ b/app/models/deliverable.rb @@ -54,20 +54,20 @@ class Deliverable < ActiveRecord::Base end end - def labor_budget_total + def labor_budget_total(date=nil) labor_budgets.sum(:budget) end - def labor_budget_total_for_date(date=nil) #Used on subclasses - labor_budget_total - end - - def overhead_budget_total + def overhead_budget_total(date=nil) overhead_budgets.sum(:budget) end - def overhead_budget_total_for_date(date=nil) #Used on subclasses - overhead_budget_total + def profit_budget(date=nil) + nil + end + + def labor_budget_hours(date=nil) + labor_budgets.sum(:hours) end # Total number of hours estimated in the Deliverable's budgets @@ -81,6 +81,10 @@ class Deliverable < ActiveRecord::Base issues.inject(0) {|total, issue| total += issue.spent_hours } end + def filter_by_date(date=nil, &block) + block.call + end + def retainer? type == "RetainerDeliverable" end diff --git a/app/models/fixed_deliverable.rb b/app/models/fixed_deliverable.rb index c944114..f1c5034 100644 --- a/app/models/fixed_deliverable.rb +++ b/app/models/fixed_deliverable.rb @@ -11,7 +11,7 @@ class FixedDeliverable < Deliverable 'F' end - def total + def total(date=nil) read_attribute(:total) || 0.0 end @@ -22,9 +22,9 @@ class FixedDeliverable < Deliverable # The amount of profit that is budgeted for this deliverable. # Profit = Total - ( Labor + Overhead + Fixed + Markup ) - def profit_budget - budgets = labor_budget_total + overhead_budget_total - (total || 0.0) - budgets + def profit_budget(date=nil) + budgets = labor_budget_total(date) + overhead_budget_total(date) + (total(date) || 0.0) - budgets end # The amount of money remaining after expenses have been taken out diff --git a/app/models/hourly_deliverable.rb b/app/models/hourly_deliverable.rb index ddaa8c5..11601a6 100644 --- a/app/models/hourly_deliverable.rb +++ b/app/models/hourly_deliverable.rb @@ -14,12 +14,12 @@ class HourlyDeliverable < Deliverable 'H' end - def total + def total(date=nil) return 0 if contract.nil? return 0 if contract.billable_rate.blank? return 0 if labor_budgets.count == 0 && overhead_budgets.count == 0 - return contract.billable_rate * labor_budgets.sum(:hours) + return contract.billable_rate * labor_budget_hours(date) end # Total amount to be billed on the deliverable, using the total time logged @@ -49,9 +49,9 @@ class HourlyDeliverable < Deliverable # The amount of profit that is budgeted for this deliverable # Profit = Total - ( Labor + Overhead + Fixed + Markup ) - def profit_budget - budgets = labor_budget_total + overhead_budget_total - (total || 0.0) - budgets + def profit_budget(date=nil) + budgets = labor_budget_total(date) + overhead_budget_total(date) + (total(date) || 0.0) - budgets end # The amount of money remaining after expenses have been taken out diff --git a/app/models/retainer_deliverable.rb b/app/models/retainer_deliverable.rb index 42d832a..2898718 100644 --- a/app/models/retainer_deliverable.rb +++ b/app/models/retainer_deliverable.rb @@ -75,7 +75,7 @@ class RetainerDeliverable < HourlyDeliverable budgets end - def labor_budget_total_for_date(date=nil) + def labor_budget_total(date=nil) if date if within_date_range?(date) labor_budgets.sum(:budget, :conditions => {:year => date.year, :month => date.month}) @@ -83,11 +83,11 @@ class RetainerDeliverable < HourlyDeliverable 0 # outside of range end else - labor_budgets.sum(:budget) + super end end - def overhead_budget_total_for_date(date=nil) + def overhead_budget_total(date=nil) if date if within_date_range?(date) overhead_budgets.sum(:budget, :conditions => {:year => date.year, :month => date.month}) @@ -95,7 +95,19 @@ class RetainerDeliverable < HourlyDeliverable 0 # outside of range end else - overhead_budgets.sum(:budget) + super + end + end + + def labor_budget_hours(date=nil) + if date + if within_date_range?(date) + labor_budgets.sum(:hours, :conditions => {:year => date.year, :month => date.month}) + else + 0 # outside of range + end + else + super end end diff --git a/test/unit/deliverable_test.rb b/test/unit/deliverable_test.rb index cb937ee..6691318 100644 --- a/test/unit/deliverable_test.rb +++ b/test/unit/deliverable_test.rb @@ -34,37 +34,4 @@ class DeliverableTest < ActiveSupport::TestCase end end - context "#labor_budget_spent_for_period" do - should "use all periods" - end - - context "#labor_budget_total_for_period" do - should "use all periods" - end - - context "#overhead_spent_for_period" do - should "use all periods" - end - - context "#overhead_budget_total_for_period" do - should "use all periods" - end - - context "#profit_left_for_period" do - should "use all periods" - end - - context "#profit_budget_for_period" do - should "use all periods" - end - - context "#total_spent_for_period" do - should "use all periods" - end - - context "#total_for_period" do - should "use all periods" - end - - end diff --git a/test/unit/retainer_deliverable_test.rb b/test/unit/retainer_deliverable_test.rb index 06ed2dc..7f12696 100644 --- a/test/unit/retainer_deliverable_test.rb +++ b/test/unit/retainer_deliverable_test.rb @@ -80,7 +80,7 @@ class RetainerDeliverableTest < ActiveSupport::TestCase end end - context "#labor_budget_spent_for_date" do + context "#labor_budget_spent" do context "with a empty period" do should "use all periods" end @@ -94,7 +94,7 @@ class RetainerDeliverableTest < ActiveSupport::TestCase end end - context "#labor_budget_total_for_date" do + context "#labor_budget_total" do setup do @deliverable = RetainerDeliverable.generate!(:start_date => '2010-01-01', :end_date => '2010-03-31') @deliverable.labor_budgets << LaborBudget.spawn(:budget => 100, :hours => 10) @@ -103,32 +103,32 @@ class RetainerDeliverableTest < ActiveSupport::TestCase context "with a empty period" do should "use all periods" do - assert_equal 300.0, @deliverable.labor_budget_total_for_date(nil) + assert_equal 300.0, @deliverable.labor_budget_total(nil) end end context "with a period out of the retainer range" do should "filter the records" do - assert_equal 0, @deliverable.labor_budget_total_for_date(Date.new(2011,1,1)) + assert_equal 0, @deliverable.labor_budget_total(Date.new(2011,1,1)) end end context "with an invalid period" do should "return 0" do - assert_equal 0, @deliverable.labor_budget_total_for_date('1') + assert_equal 0, @deliverable.labor_budget_total('1') end end context "with a period in the retainer range" do should "filter the records" do - assert_equal 100.0, @deliverable.labor_budget_total_for_date(Date.new(2010,2,1)) + assert_equal 100.0, @deliverable.labor_budget_total(Date.new(2010,2,1)) end end end - # context "#overhead_spent_for_date" + # context "#overhead_spent" - context "#overhead_budget_total_for_date" do + context "#overhead_budget_total" do setup do @deliverable = RetainerDeliverable.generate!(:start_date => '2010-01-01', :end_date => '2010-03-31') @deliverable.overhead_budgets << OverheadBudget.spawn(:budget => 100, :hours => 10) @@ -137,31 +137,105 @@ class RetainerDeliverableTest < ActiveSupport::TestCase context "with a empty period" do should "use all periods" do - assert_equal 300.0, @deliverable.overhead_budget_total_for_date(nil) + assert_equal 300.0, @deliverable.overhead_budget_total(nil) end end context "with a period out of the retainer range" do should "filter the records" do - assert_equal 0, @deliverable.overhead_budget_total_for_date(Date.new(2011,1,1)) + assert_equal 0, @deliverable.overhead_budget_total(Date.new(2011,1,1)) end end context "with an invalid period" do should "return 0" do - assert_equal 0, @deliverable.overhead_budget_total_for_date('1') + assert_equal 0, @deliverable.overhead_budget_total('1') end end context "with a period in the retainer range" do should "filter the records" do - assert_equal 100.0, @deliverable.overhead_budget_total_for_date(Date.new(2010,2,1)) + assert_equal 100.0, @deliverable.overhead_budget_total(Date.new(2010,2,1)) end end end - # context "#profit_left_for_date" - # context "#profit_budget_for_date" - # context "#total_spent_for_date" - # context "#total_for_date" + # context "#profit_left" + + context "#profit_budget" do + setup do + @contract = Contract.generate!(:billable_rate => 100) + @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! + + assert_equal 100 * 30, @deliverable.total + assert_equal 2400, @deliverable.profit_budget # 3000 - 300 - 300 + end + + context "with a empty period" do + should "use all periods" do + assert_equal 2400, @deliverable.profit_budget(nil) + end + end + + context "with a period out of the retainer range" do + should "filter the records" do + assert_equal 0, @deliverable.profit_budget(Date.new(2011,1,1)) + end + end + + context "with an invalid period" do + should "return 0" do + assert_equal 0, @deliverable.profit_budget('1') + end + end + + context "with a period in the retainer range" do + should "filter the records" do + assert_equal 1000 - 200, @deliverable.profit_budget(Date.new(2010,2,1)) + end + end + + end + + # context "#total_spent" + + context "#total" do + setup do + @contract = Contract.generate!(:billable_rate => 100) + @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! + + assert_equal 100 * 30, @deliverable.total + end + + context "with a empty period" do + should "use all periods" do + assert_equal 3000, @deliverable.total(nil) + end + end + + context "with a period out of the retainer range" do + should "filter the records" do + assert_equal 0, @deliverable.total(Date.new(2011,1,1)) + end + end + + context "with an invalid period" do + should "return 0" do + assert_equal 0, @deliverable.total('1') + end + end + + context "with a period in the retainer range" do + should "filter the records" do + assert_equal 1000, @deliverable.total(Date.new(2010,2,1)) + end + end + + end end