WIP: working on getting the report to work for periods

This commit is contained in:
Eric Davis
2011-10-14 10:03:16 -07:00
parent 89cefddc2f
commit 64121bbb83
5 changed files with 166 additions and 27 deletions
+22 -10
View File
@@ -279,32 +279,44 @@ class Deliverable < ActiveRecord::Base
end
# Total amount spent ($) for a given activity
def spent_for_activity(activity)
def spent_for_activity(activity, options={})
period = options[:period] || nil
issues.all.inject(0.0) do |all_issues_total, issue|
all_issues_total += issue.time_entries.all(:conditions => {:activity_id => activity.id}).sum(&:cost)
conditions = ARCondition.new(["activity_id IN (?)", activity.id])
if period.present?
conditions.add(["tyear = ? AND tmonth = ?", period.year, period.month])
end
all_issues_total += issue.time_entries.all(:conditions => conditions.conditions).sum(&:cost)
all_issues_total
end
end
# Total hours spent for a given activity
def hours_spent_for_activity(activity)
def hours_spent_for_activity(activity, options={})
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])
def budget_for_activity(activity, options={})
period = options[:period] || nil
labor_conditions = ARCondition.new(["#{LaborBudget.table_name}.time_entry_activity_id IN (?)", activity.id])
overhead_conditions = ARCondition.new(["#{OverheadBudget.table_name}.time_entry_activity_id IN (?)", activity.id])
if period.present?
labor_conditions.add(["#{LaborBudget.table_name}.year = ?", period.year])
labor_conditions.add(["#{LaborBudget.table_name}.month = ?", period.month])
overhead_conditions.add(["#{OverheadBudget.table_name}.year = ?", period.year])
overhead_conditions.add(["#{OverheadBudget.table_name}.month = ?", period.month])
end
labor = labor_budgets.sum(:budget, :conditions => labor_conditions.conditions)
overhead = overhead_budgets.sum(:budget, :conditions => overhead_conditions.conditions)
labor.to_f + overhead.to_f
end
# Total budget (hours) a given activity
def hours_budget_for_activity(activity)
def hours_budget_for_activity(activity, options={})
labor = labor_budgets.sum(:hours,
:conditions => ["#{LaborBudget.table_name}.time_entry_activity_id IN (?)", activity.id])
overhead = overhead_budgets.sum(:hours,
+12 -12
View File
@@ -37,17 +37,17 @@
<td class="">
<%= h(activity.name) %>
</td>
<td class="financial spent-amount <%= overage_class(deliverable.spent_for_activity(activity), deliverable.budget_for_activity(activity)) %>">
<%= number_to_currency(deliverable.spent_for_activity(activity), :precision => Deliverable::ViewPrecision) %>
<td class="financial spent-amount <%= overage_class(deliverable.spent_for_activity(activity, :period => period), deliverable.budget_for_activity(activity, :period => period)) %>">
<%= number_to_currency(deliverable.spent_for_activity(activity, :period => period), :precision => Deliverable::ViewPrecision) %>
</td>
<td class="financial total-amount">
<%= number_to_currency(deliverable.budget_for_activity(activity), :precision => Deliverable::ViewPrecision) %>
<%= number_to_currency(deliverable.budget_for_activity(activity, :period => period), :precision => Deliverable::ViewPrecision) %>
</td>
<td class="numeric spent-hours <%= overage_class(deliverable.hours_spent_for_activity(activity), deliverable.hours_budget_for_activity(activity)) %>">
<%= number_with_precision(deliverable.hours_spent_for_activity(activity), :precision => Deliverable::ViewPrecision) %>
<td class="numeric spent-hours <%= overage_class(deliverable.hours_spent_for_activity(activity, :period => period), deliverable.hours_budget_for_activity(activity, :period => period)) %>">
<%= number_with_precision(deliverable.hours_spent_for_activity(activity, :period => period), :precision => Deliverable::ViewPrecision) %>
</td>
<td class="numeric total-deliverable-hours">
<%= number_with_precision(deliverable.hours_budget_for_activity(activity), :precision => Deliverable::ViewPrecision) %>
<%= number_with_precision(deliverable.hours_budget_for_activity(activity, :period => period), :precision => Deliverable::ViewPrecision) %>
</td>
<% end %>
@@ -87,17 +87,17 @@
<td class="">
<%= h(activity.name) %>
</td>
<td class="financial spent-amount <%= overage_class(deliverable.spent_for_activity(activity), deliverable.budget_for_activity(activity)) %>">
<%= number_to_currency(deliverable.spent_for_activity(activity), :precision => Deliverable::ViewPrecision) %>
<td class="financial spent-amount <%= overage_class(deliverable.spent_for_activity(activity, :period => period), deliverable.budget_for_activity(activity, :period => period)) %>">
<%= number_to_currency(deliverable.spent_for_activity(activity, :period => period), :precision => Deliverable::ViewPrecision) %>
</td>
<td class="financial total-amount">
<%= number_to_currency(deliverable.budget_for_activity(activity), :precision => Deliverable::ViewPrecision) %>
<%= number_to_currency(deliverable.budget_for_activity(activity, :period => period), :precision => Deliverable::ViewPrecision) %>
</td>
<td class="numeric spent-hours <%= overage_class(deliverable.hours_spent_for_activity(activity), deliverable.hours_budget_for_activity(activity)) %>">
<%= number_with_precision(deliverable.hours_spent_for_activity(activity), :precision => Deliverable::ViewPrecision) %>
<td class="numeric spent-hours <%= overage_class(deliverable.hours_spent_for_activity(activity, :period => period), deliverable.hours_budget_for_activity(activity, :period => period)) %>">
<%= number_with_precision(deliverable.hours_spent_for_activity(activity, :period => period), :precision => Deliverable::ViewPrecision) %>
</td>
<td class="numeric total-deliverable-hours">
<%= number_with_precision(deliverable.hours_budget_for_activity(activity), :precision => Deliverable::ViewPrecision) %>
<%= number_with_precision(deliverable.hours_budget_for_activity(activity, :period => period), :precision => Deliverable::ViewPrecision) %>
</td>
<% end %>
@@ -205,4 +205,92 @@ class DeliverableFinancesShowTest < ActionController::IntegrationTest
end
end
end
context "for a request for a different period" do
setup do
@period = "2010-02"
visit "/projects/#{@project.id}/contracts/#{@contract.id}/deliverables/#{@deliverable1.id}/finances?period=#{@period}"
assert_response :success
# All work done in setup() is past this period, only these items should show up.
Rate.generate!(:project => @deliverable1.project,
:user => @manager,
:date_in_effect => Date.new(2010, 2, 15),
:amount => 45)
# 2 hours of $45 billable work
create_issue_with_time_for_deliverable(@deliverable1, {
:activity => @billable_activity,
:user => @manager,
:hours => 2,
:spent_on => Date.new(2010, 2,15),
:skip_rate => true,
:issue_category => @category_on_billable
})
# 1 hour of $45 billable work with no category
create_issue_with_time_for_deliverable(@deliverable1, {
:activity => @billable_activity,
:user => @manager,
:hours => 1,
:spent_on => Date.new(2010, 2,15),
:skip_rate => true,
:issue_category => nil
})
# 3 hours of $45 nonbillable work
create_issue_with_time_for_deliverable(@deliverable1, {
:activity => @non_billable_activity,
:user => @manager,
:hours => 3,
:spent_on => Date.new(2010, 2, 15),
:skip_rate => true,
:issue_category => @category_on_non_billable
})
end
should "calculate activity values based on the period only" do
# Labor
assert_select "table#deliverable-labor-activities" do
assert_select "tr.labor" do
assert_select "td", :text => /#{@billable_activity.name}/
assert_select "td.spent-amount", :text => /\$135/ # 3 * $45
assert_select "td.total-amount", :text => /\$100/ # 1 month
assert_select "td.spent-hours", :text => /3/
assert_select "td.total-deliverable-hours", :text => /10/ # 1 month
end
assert_select "tr.summary-row.labor" do
assert_select "td", :text => /Totals/
assert_select "td.spent-amount", :text => /\$135/
assert_select "td.total-amount", :text => /\$100/
assert_select "td.spent-hours", :text => /3/
assert_select "td.total-deliverable-hours", :text => /10/
end
end
# Overhead
assert_select "table#deliverable-overhead-activities" do
assert_select "tr.overhead" do
assert_select "td", :text => /#{@non_billable_activity.name}/
assert_select "td.spent-amount", :text => /\$135/
assert_select "td.total-amount", :text => /\$200/
assert_select "td.spent-hours", :text => /3/
assert_select "td.total-deliverable-hours", :text => /10/ # 3 month retainer * 10
end
assert_select "tr.summary-row.overhead" do
assert_select "td", :text => /Totals/
assert_select "td.spent-amount", :text => /\$135/
assert_select "td.total-amount", :text => /\$200/
assert_select "td.spent-hours", :text => /5/
assert_select "td.total-deliverable-hours", :text => /10/
end
end
end
should "calculate user values based on the period only"
should "calculate issue category values based on the period only"
end
end
+4 -2
View File
@@ -131,18 +131,20 @@ class ActiveSupport::TestCase
amount = options[:amount] || 100
hours = options[:hours] || 2
issue_category = options[:issue_category]
skip_rate = options[:skip_rate] || false
spent_on = options[:spent_on] || Date.today
issue = Issue.generate_for_project!(project, :category_id => issue_category.try(:id))
time_entry = TimeEntry.generate!(:issue => issue,
:project => project,
:activity => activity,
:spent_on => Date.today,
:spent_on => spent_on,
:hours => hours,
:user => user)
rate = Rate.generate!(:project => project,
:user => user,
:date_in_effect => Date.yesterday,
:amount => amount)
:amount => amount) unless skip_rate
deliverable.issues << issue
issue
end
+40 -3
View File
@@ -141,6 +141,31 @@ class DeliverableTest < ActiveSupport::TestCase
assert_equal 500.0, @deliverable.spent_for_activity(@billable_activity).to_f
end
should "return the total amount spent for an activity during the period" do
configure_overhead_plugin
create_contract_and_deliverable
Rate.generate!(:project => @deliverable.project,
:user => @manager,
:date_in_effect => Date.new(2010, 2, 15),
:amount => 45)
create_issue_with_time_for_deliverable(@deliverable, {
:activity => @billable_activity,
:user => @manager,
:hours => 5,
:amount => 100
})
create_issue_with_time_for_deliverable(@deliverable, {
:activity => @billable_activity,
:user => @manager,
:hours => 2,
:spent_on => Date.new(2010, 2,15),
:skip_rate => true,
:issue_category => @category_on_billable
})
assert_equal 90.0, @deliverable.spent_for_activity(@billable_activity, :period => Date.new(2010,2,1)).to_f
end
end
context "#budget_for_activity" do
@@ -153,7 +178,17 @@ class DeliverableTest < ActiveSupport::TestCase
assert_equal 600.0, @deliverable.budget_for_activity(@billable_activity).to_f # 200 * 3 months (retainer)
end
should "return the total amount budgeted for an activity during the period" do
configure_overhead_plugin
create_contract_and_deliverable
@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 200.0, @deliverable.budget_for_activity(@billable_activity, :period => Date.new(2010,2,1)).to_f # 200 * 1 months (retainer)
end
end
context "#hours_spent_for_activity" do
@@ -170,7 +205,8 @@ class DeliverableTest < ActiveSupport::TestCase
assert_equal 5.0, @deliverable.hours_spent_for_activity(@billable_activity).to_f
end
should "return the total hours spent for an activity during the period"
end
context "#hours_budget_for_activity" do
@@ -183,7 +219,8 @@ class DeliverableTest < ActiveSupport::TestCase
assert_equal 60.0, @deliverable.hours_budget_for_activity(@billable_activity).to_f # 20 * 3 months (retainer)
end
should "return the total hours budgeted for an activity during the period" do
end
context "#users_with_billable_time" do