[#6636] Add Deliverable calculation methods based on activity
This commit is contained in:
@@ -270,6 +270,45 @@ class Deliverable < ActiveRecord::Base
|
|||||||
type == "RetainerDeliverable"
|
type == "RetainerDeliverable"
|
||||||
end
|
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
|
def self.valid_types
|
||||||
['FixedDeliverable','HourlyDeliverable','RetainerDeliverable']
|
['FixedDeliverable','HourlyDeliverable','RetainerDeliverable']
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -83,4 +83,101 @@ class DeliverableTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user