From 4d475042f0ff19dc44baca396a4d2a2c03c0e028 Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Tue, 13 Jul 2010 10:28:45 -0700 Subject: [PATCH] [#4183] Implemented Contract#profit_budget and Deliverable#profit_budget. --- app/models/contract.rb | 7 ++++++- app/models/fixed_deliverable.rb | 7 +++++++ app/models/hourly_deliverable.rb | 7 +++++++ test/unit/contract_test.rb | 19 +++++++++++++++++++ test/unit/fixed_deliverable_test.rb | 24 ++++++++++++++++++++++++ test/unit/hourly_deliverable_test.rb | 22 ++++++++++++++++++++++ 6 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 test/unit/fixed_deliverable_test.rb diff --git a/app/models/contract.rb b/app/models/contract.rb index 403ba74..f892cc0 100644 --- a/app/models/contract.rb +++ b/app/models/contract.rb @@ -31,7 +31,7 @@ class Contract < ActiveRecord::Base [:status, :contract_type, :labor_spent, :overhead_spent, :fixed_spent, :fixed_budget, :total_spent, - :markup_spent, :markup_budget, :profit_spent, :profit_budget, + :markup_spent, :markup_budget, :profit_spent, :discount_spent, :discount_budget, :client_point_of_contact, :estimated_hour_spent ].each do |mthd| @@ -58,6 +58,11 @@ class Contract < ActiveRecord::Base deliverables.inject(0) {|total, deliverable| total += deliverable.total } end + # OPTIMIZE: N+1 + def profit_budget + deliverables.inject(0) {|total, deliverable| total += deliverable.profit_budget } + end + PaymentTerms = { :net_0 => :text_payment_terms_net_0, :net_15 => :text_payment_terms_net_15, diff --git a/app/models/fixed_deliverable.rb b/app/models/fixed_deliverable.rb index c91a64d..a856bc0 100644 --- a/app/models/fixed_deliverable.rb +++ b/app/models/fixed_deliverable.rb @@ -15,6 +15,13 @@ class FixedDeliverable < Deliverable read_attribute(:total) || 0.0 end + # 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 + end + # Hardcoded value used as a wrapper for the old Budget plugin API. # # The Overhead plugin uses this in it's calcuations. diff --git a/app/models/hourly_deliverable.rb b/app/models/hourly_deliverable.rb index c534508..f32d372 100644 --- a/app/models/hourly_deliverable.rb +++ b/app/models/hourly_deliverable.rb @@ -31,4 +31,11 @@ class HourlyDeliverable < Deliverable def clear_total write_attribute(:total, nil) end + + # 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 + end end diff --git a/test/unit/contract_test.rb b/test/unit/contract_test.rb index 4a2ec60..9d5a982 100644 --- a/test/unit/contract_test.rb +++ b/test/unit/contract_test.rb @@ -80,4 +80,23 @@ class ContractTest < ActiveSupport::TestCase assert_equal 10_000 + (30 * 100), contract.total_budget end end + + context "#profit_budget" do + should "sum all of the profit budgets of the Deliverables" do + contract = Contract.generate!(:billable_rate => 100.0) + + contract.deliverables << @deliverable_1 = FixedDeliverable.generate!(:total => 10_000) + LaborBudget.generate!(:deliverable => @deliverable_1, :budget => 2000) + OverheadBudget.generate!(:deliverable => @deliverable_1, :budget => 2000) + + contract.deliverables << @deliverable_2 = HourlyDeliverable.generate! + LaborBudget.generate!(:deliverable => @deliverable_2, :hours => 10) + OverheadBudget.generate!(:deliverable => @deliverable_2, :hours => 20) + + assert_equal 10_000 - 4000, @deliverable_1.profit_budget + assert_equal (30 * 100.0) - 0, @deliverable_2.profit_budget + assert_equal 9000, contract.profit_budget + + end + end end diff --git a/test/unit/fixed_deliverable_test.rb b/test/unit/fixed_deliverable_test.rb new file mode 100644 index 0000000..f46cc01 --- /dev/null +++ b/test/unit/fixed_deliverable_test.rb @@ -0,0 +1,24 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class FixedDeliverableTest < ActiveSupport::TestCase + context "#profit_budget" do + context "with no labor budget, no overhead budget" do + should "equal the total" do + assert_equal 1000, FixedDeliverable.generate(:total => 1_000).profit_budget + end + end + + should "be the total minus the sum of all of the budgets" do + deliverable = FixedDeliverable.generate(:total => 1_000) + LaborBudget.generate!(:deliverable => deliverable, :budget => 200) + LaborBudget.generate!(:deliverable => deliverable, :budget => 200) + OverheadBudget.generate!(:deliverable => deliverable, :budget => 200) + + assert_equal 400, deliverable.profit_budget + end + + should "be 0 if there is no total" do + assert_equal 0, FixedDeliverable.generate(:total => nil).profit_budget + end + end +end diff --git a/test/unit/hourly_deliverable_test.rb b/test/unit/hourly_deliverable_test.rb index 0d6208c..63856d1 100644 --- a/test/unit/hourly_deliverable_test.rb +++ b/test/unit/hourly_deliverable_test.rb @@ -49,4 +49,26 @@ class HourlyDeliverableTest < ActiveSupport::TestCase end end + + context "#profit_budget" do + setup do + @contract = Contract.generate!(:billable_rate => 100.0) + @deliverable = HourlyDeliverable.generate!(:contract => @contract) + end + + context "with no labor budget, no overhead budget" do + should "be 0 (no hours available to bill)" do + assert_equal 0, @deliverable.profit_budget + end + end + + should "be the total minus the sum of all of the budgets' amounts" do + LaborBudget.generate!(:deliverable => @deliverable, :hours => 10, :budget => 2000) + LaborBudget.generate!(:deliverable => @deliverable, :hours => 5, :budget => 1000) + OverheadBudget.generate!(:deliverable => @deliverable, :hours => 15, :budget => 2000) + + assert_equal 30 * 100, @deliverable.total + assert_equal 3000 - (2000 + 1000 + 2000), @deliverable.profit_budget + end + end end