diff --git a/app/models/contract.rb b/app/models/contract.rb index 2db8ae4..8552893 100644 --- a/app/models/contract.rb +++ b/app/models/contract.rb @@ -36,8 +36,6 @@ class Contract < ActiveRecord::Base named_scope :by_name, {:order => "#{Contract.table_name}.name ASC"} [:status, :contract_type, - :fixed_spent, - :fixed_markup_spent, :discount_spent, :discount_budget ].each do |mthd| define_method(mthd) { "TODO in later release" } @@ -100,12 +98,22 @@ class Contract < ActiveRecord::Base def fixed_budget deliverables.inject(0) {|total, deliverable| total += deliverable.fixed_budget_total } end - + + # OPTIMIZE: N+1 + def fixed_spent + deliverables.inject(0) {|total, deliverable| total += deliverable.fixed_budget_total_spent } + end + # OPTIMIZE: N+1 def fixed_markup_budget deliverables.inject(0) {|total, deliverable| total += deliverable.fixed_markup_budget_total } end + # OPTIMIZE: N+1 + def fixed_markup_spent + deliverables.inject(0) {|total, deliverable| total += deliverable.fixed_markup_budget_total_spent } + end + def after_initialize self.executed = false unless self.executed.present? end diff --git a/app/models/deliverable.rb b/app/models/deliverable.rb index d9f356e..692ed8d 100644 --- a/app/models/deliverable.rb +++ b/app/models/deliverable.rb @@ -92,11 +92,20 @@ class Deliverable < ActiveRecord::Base fixed_budgets.sum(:budget) end + def fixed_budget_total_spent(date=nil) + fixed_budgets.paid.sum(:budget) + end + # OPTIMIZE: N+1 def fixed_markup_budget_total(date=nil) fixed_budgets.inject(0) {|total, fixed_budget| total += fixed_budget.markup_value } end + # OPTIMIZE: N+1 + def fixed_markup_budget_total_spent(date=nil) + fixed_budgets.paid.inject(0) {|total, fixed_budget| total += fixed_budget.markup_value } + end + def filter_by_date(date=nil, &block) block.call end diff --git a/app/models/fixed_budget.rb b/app/models/fixed_budget.rb index 982067a..9a43013 100644 --- a/app/models/fixed_budget.rb +++ b/app/models/fixed_budget.rb @@ -23,6 +23,8 @@ class FixedBudget < ActiveRecord::Base end } + named_scope :paid, {:conditions => {:paid => true}} + def markup_value return 0 if budget.blank? || markup.blank? @@ -38,6 +40,14 @@ class FixedBudget < ActiveRecord::Base end + def budget_spent + if paid? + budget + else + 0 + end + end + def percent_markup? markup && markup.match(/%/) end diff --git a/app/models/retainer_deliverable.rb b/app/models/retainer_deliverable.rb index 9831474..c77890e 100644 --- a/app/models/retainer_deliverable.rb +++ b/app/models/retainer_deliverable.rb @@ -133,6 +133,17 @@ class RetainerDeliverable < HourlyDeliverable end end + def fixed_budget_total_spent(date=nil) + case scope_date_status(date) + when :in + fixed_budgets.paid.sum(:budget, :conditions => {:year => date.year, :month => date.month}) + when :out + 0 + else + super + end + end + def fixed_markup_budget_total(date=nil) case scope_date_status(date) when :in @@ -145,6 +156,21 @@ class RetainerDeliverable < HourlyDeliverable super end end + + def fixed_markup_budget_total_spent(date=nil) + case scope_date_status(date) + when :in + fixed_budgets. + paid. + all(:conditions => {:year => date.year, :month => date.month}). + inject(0) {|total, fixed_budget| total += fixed_budget.markup_value } + when :out + 0 + else + super + end + end + def total_spent(date=nil) case scope_date_status(date) when :in diff --git a/app/views/contracts/show.html.erb b/app/views/contracts/show.html.erb index 864236d..2149e11 100644 --- a/app/views/contracts/show.html.erb +++ b/app/views/contracts/show.html.erb @@ -104,7 +104,7 @@ <%= h deliverable.manager.try(:name) %> <%= format_budget_for_deliverable(deliverable, deliverable.labor_budget_spent, deliverable.labor_budget_total, :class => 'labor') %> <%= format_budget_for_deliverable(deliverable, deliverable.overhead_spent, deliverable.overhead_budget_total, :class => 'overhead') %> - <%= format_budget_for_deliverable(deliverable, 0, deliverable.fixed_budget_total, :class => 'fixed') %> + <%= format_budget_for_deliverable(deliverable, deliverable.fixed_budget_total_spent, deliverable.fixed_budget_total, :class => 'fixed') %> <% end %> diff --git a/app/views/deliverables/_details_row.html.erb b/app/views/deliverables/_details_row.html.erb index 2713db5..ce52817 100644 --- a/app/views/deliverables/_details_row.html.erb +++ b/app/views/deliverables/_details_row.html.erb @@ -67,7 +67,7 @@ <% next if fixed_budget.blank_record? %> <%= h(fixed_budget.title) %> - 0 + <%= h(format_value_field_for_contracts(fixed_budget.budget_spent)) %> <%= h(format_value_field_for_contracts(fixed_budget.budget)) %> @@ -75,7 +75,7 @@ <%= l(:field_markup) %> - 0 + <%= h(format_value_field_for_contracts(deliverable.fixed_markup_budget_total_spent(period))) %> <%= h(format_value_field_for_contracts(deliverable.fixed_markup_budget_total(period))) %> diff --git a/test/integration/contracts_show_test.rb b/test/integration/contracts_show_test.rb index 3d57987..bb3dccd 100644 --- a/test/integration/contracts_show_test.rb +++ b/test/integration/contracts_show_test.rb @@ -225,14 +225,26 @@ class ContractsShowTest < ActionController::IntegrationTest end - should "QUESTION: show the total fixed budget spent for a Deliverable" + should "show the total fixed budget spent for a Deliverable" do + @manager = User.generate! + + @deliverable1 = FixedDeliverable.generate!(:contract => @contract, :manager => @manager) + + FixedBudget.generate!(:deliverable => @deliverable1, :budget => '$1,000', :markup => '$100', :paid => true) + FixedBudget.generate!(:deliverable => @deliverable1, :budget => '$2,000', :markup => '200%') + + visit_contract_page(@contract) + assert_select "table#deliverables" do + assert_select "td.fixed.spent-amount", :text => /1,000/ + end + end should "show each fixed budget item in the details for the Deliverable" do @manager = User.generate! @deliverable1 = FixedDeliverable.generate!(:contract => @contract, :manager => @manager) - @budget1 = FixedBudget.generate!(:deliverable => @deliverable1, :title => 'Item 1', :budget => '$1,000', :markup => '$100') + @budget1 = FixedBudget.generate!(:deliverable => @deliverable1, :title => 'Item 1', :budget => '$1,000', :markup => '$100', :paid => true) @budget2 = FixedBudget.generate!(:deliverable => @deliverable1, :title => 'Item 2', :budget => '$2,000', :markup => '200%') visit_contract_page(@contract) @@ -240,7 +252,7 @@ class ContractsShowTest < ActionController::IntegrationTest assert_select "#deliverable_details_#{@deliverable1.id}" do assert_select "tr#fixed_budget_#{@budget1.id}" do assert_select 'td.fixed_title', :text => /#{@budget1.title}/ - assert_select 'td.fixed_budget_spent', :text => '0' + assert_select 'td.fixed_budget_spent', :text => '1,000' assert_select 'td.fixed_budget_total', :text => '1,000' end @@ -259,13 +271,13 @@ class ContractsShowTest < ActionController::IntegrationTest @deliverable1 = FixedDeliverable.generate!(:contract => @contract, :manager => @manager) - @budget1 = FixedBudget.generate!(:deliverable => @deliverable1, :title => 'Item 1', :budget => '$1,000', :markup => '$100') + @budget1 = FixedBudget.generate!(:deliverable => @deliverable1, :title => 'Item 1', :budget => '$1,000', :markup => '$100', :paid => true) @budget2 = FixedBudget.generate!(:deliverable => @deliverable1, :title => 'Item 2', :budget => '$2,000', :markup => '200%') visit_contract_page(@contract) assert_select "table#deliverables" do assert_select "#deliverable_details_#{@deliverable1.id}" do - assert_select 'td.fixed_markup_budget_spent', :text => '0' + assert_select 'td.fixed_markup_budget_spent', :text => '100' assert_select 'td.fixed_markup_budget_total', :text => '4,100' end end diff --git a/test/unit/contract_test.rb b/test/unit/contract_test.rb index b993620..c3daeae 100644 --- a/test/unit/contract_test.rb +++ b/test/unit/contract_test.rb @@ -268,7 +268,15 @@ class ContractTest < ActiveSupport::TestCase end context "#fixed_spent" do - should "QUESTION: how to compute the amount spent" + should "sum all fixed budget amounts on the Deliverables which are paid" do + contract = Contract.generate! + contract.deliverables << @deliverable_1 = FixedDeliverable.generate! + FixedBudget.generate!(:deliverable => @deliverable_1, :budget => '$1,000', :paid => true) + contract.deliverables << @deliverable_2 = HourlyDeliverable.generate! + FixedBudget.generate!(:deliverable => @deliverable_2, :budget => '$2,000') + + assert_equal 1000, contract.fixed_spent + end end context "#fixed_markup_budget" do @@ -285,7 +293,15 @@ class ContractTest < ActiveSupport::TestCase end context "#fixed_markup_spent" do - should "QUESTION: how to compute the amount spent" + should "sum all fixed budget markup values on the Deliverables which are paid" do + contract = Contract.generate! + contract.deliverables << @deliverable_1 = FixedDeliverable.generate! + FixedBudget.generate!(:deliverable => @deliverable_1, :budget => '$1,000', :markup => '$100', :paid => true) + contract.deliverables << @deliverable_2 = HourlyDeliverable.generate! + FixedBudget.generate!(:deliverable => @deliverable_2, :budget => '$2,000', :markup => '200%') + + assert_equal (100) + (0), contract.fixed_markup_spent + end end end diff --git a/test/unit/retainer_deliverable_test.rb b/test/unit/retainer_deliverable_test.rb index ea67a46..4fe5e33 100644 --- a/test/unit/retainer_deliverable_test.rb +++ b/test/unit/retainer_deliverable_test.rb @@ -514,6 +514,43 @@ class RetainerDeliverableTest < ActiveSupport::TestCase end + context "#fixed_budget_total_spent" 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.fixed_budgets << FixedBudget.spawn(:budget => 1000, :paid => true) + @deliverable.fixed_budgets << FixedBudget.spawn(:budget => 2000) + @deliverable.save! + + assert_equal 1000 * 3, @deliverable.fixed_budget_total_spent + end + + context "with a empty period" do + should "use all periods" do + assert_equal 3000, @deliverable.fixed_budget_total_spent(nil) + end + end + + context "with a period out of the retainer range" do + should "filter the records" do + assert_equal 0, @deliverable.fixed_budget_total_spent(Date.new(2011,1,1)) + end + end + + context "with an invalid period" do + should "return 0" do + assert_equal 0, @deliverable.fixed_budget_total_spent('1') + end + end + + context "with a period in the retainer range" do + should "filter the records" do + assert_equal 1000, @deliverable.fixed_budget_total_spent(Date.new(2010,2,1)) + end + end + + end + context "#fixed_markup_budget_total" do setup do @contract = Contract.generate!(:billable_rate => 100) @@ -550,4 +587,41 @@ class RetainerDeliverableTest < ActiveSupport::TestCase end end + + context "#fixed_markup_budget_total_spent" 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.fixed_budgets << FixedBudget.spawn(:budget => 1000, :markup => '50%', :paid => true) + @deliverable.fixed_budgets << FixedBudget.spawn(:budget => 2000, :markup => '$1000') + @deliverable.save! + + assert_equal (500) * 3, @deliverable.fixed_markup_budget_total_spent + end + + context "with a empty period" do + should "use all periods" do + assert_equal 1500, @deliverable.fixed_markup_budget_total_spent(nil) + end + end + + context "with a period out of the retainer range" do + should "filter the records" do + assert_equal 0, @deliverable.fixed_markup_budget_total_spent(Date.new(2011,1,1)) + end + end + + context "with an invalid period" do + should "return 0" do + assert_equal 0, @deliverable.fixed_markup_budget_total_spent('1') + end + end + + context "with a period in the retainer range" do + should "filter the records" do + assert_equal 500, @deliverable.fixed_markup_budget_total_spent(Date.new(2010,2,1)) + end + end + + end end