From 738024659456a9bc349d8a204bc44e0a2175cc24 Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Wed, 12 Oct 2011 15:43:06 -0700 Subject: [PATCH] [#6636] Add Deliverable calculation methods based on activity --- app/models/deliverable.rb | 39 ++++++++++++++ test/unit/deliverable_test.rb | 97 +++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) diff --git a/app/models/deliverable.rb b/app/models/deliverable.rb index 9a74526..0a117da 100644 --- a/app/models/deliverable.rb +++ b/app/models/deliverable.rb @@ -270,6 +270,45 @@ class Deliverable < ActiveRecord::Base type == "RetainerDeliverable" end + def billable_time_entry_activities + project.activities.select {|activity| activity.billable? } + end + + # Total amount spent ($) for a given activity + def spent_for_activity(activity) + issues.all.inject(0.0) do |all_issues_total, issue| + all_issues_total += issue.time_entries.all(:conditions => {:activity_id => activity.id}).sum(&:cost) + all_issues_total + end + end + + # Total hours spent for a given activity + def hours_spent_for_activity(activity) + issue_ids = issues.collect(&:id) + TimeEntry.sum(:hours, + :conditions => ["#{TimeEntry.table_name}.issue_id IN (?) AND activity_id IN (?)", issue_ids, activity.id]) + end + + # Total budget ($) for a given activity + def budget_for_activity(activity) + labor = labor_budgets.sum(:budget, + :conditions => ["#{LaborBudget.table_name}.time_entry_activity_id IN (?)", activity.id]) + overhead = overhead_budgets.sum(:budget, + :conditions => ["#{OverheadBudget.table_name}.time_entry_activity_id IN (?)", activity.id]) + + labor.to_f + overhead.to_f + end + + # Total budget (hours) a given activity + def hours_budget_for_activity(activity) + labor = labor_budgets.sum(:hours, + :conditions => ["#{LaborBudget.table_name}.time_entry_activity_id IN (?)", activity.id]) + overhead = overhead_budgets.sum(:hours, + :conditions => ["#{OverheadBudget.table_name}.time_entry_activity_id IN (?)", activity.id]) + + labor.to_f + overhead.to_f + end + def self.valid_types ['FixedDeliverable','HourlyDeliverable','RetainerDeliverable'] end diff --git a/test/unit/deliverable_test.rb b/test/unit/deliverable_test.rb index fa32573..02b3433 100644 --- a/test/unit/deliverable_test.rb +++ b/test/unit/deliverable_test.rb @@ -83,4 +83,101 @@ class DeliverableTest < ActiveSupport::TestCase end end + + context "#billable_time_entry_activities" do + setup do + configure_overhead_plugin + @project = Project.generate!(:identifier => 'main').reload + @contract = Contract.generate!(:project => @project, :billable_rate => 10) + @manager = User.generate! + @deliverable = RetainerDeliverable.spawn(:contract => @contract, :manager => @manager, :title => "Retainer Title", :start_date => '2010-01-01', :end_date => '2010-03-31') + + end + + should "include all billable activities" do + @billable_activity2 = TimeEntryActivity.generate!.reload + @billable_activity2.custom_field_values = { @custom_field.id => 'true' } + assert @billable_activity2.save + + assert @deliverable.billable_time_entry_activities.include?(@billable_activity), "Activity not included" + assert @deliverable.billable_time_entry_activities.include?(@billable_activity2), "Activity not included" + + end + + should "not include nonbillable activities" do + assert !@deliverable.billable_time_entry_activities.include?(@non_billable_activity3), "Non billable Activity included" + end + + end + + context "#spent_for_activity" do + should "return the total amount spent for an activity" do + configure_overhead_plugin + @project = Project.generate!(:identifier => 'main').reload + @contract = Contract.generate!(:project => @project, :billable_rate => 10) + @manager = User.generate! + @deliverable = RetainerDeliverable.generate!(:contract => @contract, :manager => @manager, :title => "Retainer Title", :start_date => '2010-01-01', :end_date => '2010-03-31') + create_issue_with_time_for_deliverable(@deliverable, { + :activity => @billable_activity, + :user => @manager, + :hours => 5, + :amount => 100 + }) + + assert_equal 500.0, @deliverable.spent_for_activity(@billable_activity).to_f + end + end + + context "#budget_for_activity" do + should "return the total amount budgeted for an activity" do + configure_overhead_plugin + @project = Project.generate!(:identifier => 'main').reload + @contract = Contract.generate!(:project => @project, :billable_rate => 10) + @manager = User.generate! + @deliverable = RetainerDeliverable.generate!(:contract => @contract, :manager => @manager, :title => "Retainer Title", :start_date => '2010-01-01', :end_date => '2010-03-31') + @deliverable.labor_budgets << LaborBudget.spawn(:budget => 100, :hours => 10, :time_entry_activity => @billable_activity) + @deliverable.labor_budgets << LaborBudget.spawn(:budget => 100, :hours => 10, :time_entry_activity => @billable_activity) + @deliverable.save! + + assert_equal 600.0, @deliverable.budget_for_activity(@billable_activity).to_f # 200 * 3 months (retainer) + end + + end + + context "#hours_spent_for_activity" do + should "return the total hours spent for an activity" do + configure_overhead_plugin + @project = Project.generate!(:identifier => 'main').reload + @contract = Contract.generate!(:project => @project, :billable_rate => 10) + @manager = User.generate! + @deliverable = RetainerDeliverable.generate!(:contract => @contract, :manager => @manager, :title => "Retainer Title", :start_date => '2010-01-01', :end_date => '2010-03-31') + create_issue_with_time_for_deliverable(@deliverable, { + :activity => @billable_activity, + :user => @manager, + :hours => 5, + :amount => 100 + }) + + assert_equal 5.0, @deliverable.hours_spent_for_activity(@billable_activity).to_f + + end + + end + + context "#hours_budget_for_activity" do + should "return the total hours budgeted for an activity" do + configure_overhead_plugin + @project = Project.generate!(:identifier => 'main').reload + @contract = Contract.generate!(:project => @project, :billable_rate => 10) + @manager = User.generate! + @deliverable = RetainerDeliverable.generate!(:contract => @contract, :manager => @manager, :title => "Retainer Title", :start_date => '2010-01-01', :end_date => '2010-03-31') + @deliverable.labor_budgets << LaborBudget.spawn(:budget => 100, :hours => 10, :time_entry_activity => @billable_activity) + @deliverable.labor_budgets << LaborBudget.spawn(:budget => 100, :hours => 10, :time_entry_activity => @billable_activity) + @deliverable.save! + + assert_equal 60.0, @deliverable.hours_budget_for_activity(@billable_activity).to_f # 20 * 3 months (retainer) + end + + end + end