Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac48931896 | ||
|
|
64121bbb83 | ||
|
|
89cefddc2f |
@@ -8,13 +8,13 @@ class DeliverablesController < InheritedResources::Base
|
||||
|
||||
helper :contracts
|
||||
helper :contract_formatter
|
||||
include ContractsHelper
|
||||
|
||||
def index
|
||||
redirect_to contract_url(@project, @contract)
|
||||
end
|
||||
|
||||
def create
|
||||
remove_empty_budget_items(params)
|
||||
@deliverable = begin_of_association_chain.deliverables.build(params[:deliverable])
|
||||
if params[:deliverable] && params[:deliverable][:type] && Deliverable.valid_types.include?(params[:deliverable][:type])
|
||||
@deliverable.type = params[:deliverable][:type]
|
||||
@@ -25,7 +25,6 @@ class DeliverablesController < InheritedResources::Base
|
||||
def update
|
||||
@deliverable = begin_of_association_chain.deliverables.find_by_id(params[:id])
|
||||
params[:deliverable] = params[:fixed_deliverable] || params[:hourly_deliverable] || params[:retainer_deliverable]
|
||||
remove_empty_budget_items(params)
|
||||
update!(:notice => l(:text_flash_deliverable_updated, :name => @deliverable.title)) { contract_url(@project, @contract) }
|
||||
end
|
||||
|
||||
@@ -39,8 +38,16 @@ class DeliverablesController < InheritedResources::Base
|
||||
end
|
||||
|
||||
def finances
|
||||
@deliverable = @contract.deliverables.find(params[:id])
|
||||
period = extract_period(params[:period])
|
||||
if period
|
||||
@period = validate_period(@deliverable, period)
|
||||
else
|
||||
@period = nil
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.js { render :partial => 'deliverables/finances', :locals => {:contract => @contract, :deliverable => @contract.deliverables.find(params[:id])} }
|
||||
format.js { render :partial => 'deliverables/finances', :locals => {:contract => @contract, :deliverable => @deliverable, :period => @period } }
|
||||
format.html { }
|
||||
end
|
||||
|
||||
@@ -77,27 +84,4 @@ class DeliverablesController < InheritedResources::Base
|
||||
period
|
||||
end
|
||||
|
||||
# Remove empty budgets. Will prevent validation errors
|
||||
# from empty fields submitted from the bulk adding form.
|
||||
#
|
||||
# LSS Clients #6714
|
||||
def remove_empty_budget_items(params)
|
||||
params["deliverable"]["labor_budgets_attributes"].reject! {|key, b| budget_item_empty?(b) }
|
||||
params["deliverable"]["overhead_budgets_attributes"].reject! {|key, b| budget_item_empty?(b) }
|
||||
params["deliverable"]["fixed_budgets_attributes"].reject! {|key, b| fixed_budget_item_empty?(b) }
|
||||
end
|
||||
|
||||
def budget_item_empty?(item)
|
||||
(item["time_entry_activity_id"].blank?) &&
|
||||
(item["hours"].blank? || item["hours"].to_f == 0.0) &&
|
||||
(item["budget"].blank? || item["budget"].gsub('$','').to_f == 0.0)
|
||||
end
|
||||
|
||||
def fixed_budget_item_empty?(item)
|
||||
(item["title"].blank?) &&
|
||||
(item["budget"].blank? || item["budget"].gsub('$','').to_f == 0.0) &&
|
||||
(item["markup"].blank? || item["markup"].gsub('$','').to_d == 0.0)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
+22
-10
@@ -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,
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<%= content_tag(:label, l(:field_labor)) %>
|
||||
<table id="deliverable-labor" class="deliverable_finance_table">
|
||||
<tbody>
|
||||
<% form.fields_for :labor_budgets, labor_budgets.sort_by {|b| b.id || 0 } do |labor_budget| %>
|
||||
<% form.fields_for :labor_budgets, labor_budgets.sort_by(&:id) do |labor_budget| %>
|
||||
<%= render :partial => 'labor_budget_form', :locals => {:labor_budget => labor_budget} %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
@@ -37,7 +37,7 @@
|
||||
<%= content_tag(:label, l(:field_overhead)) %>
|
||||
<table id="deliverable-overhead" class="deliverable_finance_table">
|
||||
<tbody>
|
||||
<% form.fields_for :overhead_budgets, overhead_budgets.sort_by {|b| b.id || 0 } do |overhead_budget| %>
|
||||
<% form.fields_for :overhead_budgets, overhead_budgets.sort_by(&:id) do |overhead_budget| %>
|
||||
<%= render :partial => 'overhead_budget_form', :locals => {:overhead_budget => overhead_budget} %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
@@ -48,7 +48,7 @@
|
||||
<div id="deliverable-fixed" class="fixed-item-form">
|
||||
<label for="contract_discount">Fixed</label>
|
||||
|
||||
<% form.fields_for :fixed_budgets, fixed_budgets.sort_by {|b| b.id || 0 } do |fixed_budget| %>
|
||||
<% form.fields_for :fixed_budgets, fixed_budgets.sort_by(&:id) do |fixed_budget| %>
|
||||
<%= render :partial => 'fixed_budget_form', :locals => {:fixed_budget => fixed_budget} %>
|
||||
<%= wikitoolbar_for "fixed-description#{fixed_budget.object.object_id}" %>
|
||||
<% end %>
|
||||
|
||||
@@ -2,11 +2,21 @@
|
||||
<%= l(:text_deliverable_spending_summary,
|
||||
:spent => content_tag(:span, h(number_to_currency(deliverable.labor_budget_spent, :precision => Deliverable::ViewPrecision)), :class => 'spent'),
|
||||
:total => content_tag(:span, h(number_to_currency(deliverable.labor_budget_total, :precision => Deliverable::ViewPrecision)), :class => 'total'),
|
||||
:hours => content_tag(:span, h(number_with_precision(deliverable.labor_hours_spent_total, :precision => Deliverable::ViewPrecision)), :class => 'hours')) %>
|
||||
:hours => content_tag(:span, h(deliverable.labor_hours_spent_total), :class => 'hours')) %>
|
||||
</div>
|
||||
|
||||
<h2><%= h(deliverable.title) %></h2>
|
||||
|
||||
<% if deliverable.retainer? %>
|
||||
<div class="deliverable-period">
|
||||
<form method="get" action="<%= finances_contract_deliverable_path(deliverable.project, contract, deliverable, :format => 'js') %>">
|
||||
<select name="period" id="retainer_period_change_<%= h(deliverable.id) %>" class="retainer_period_change">
|
||||
<%= retainer_period_options(deliverable, :selected => period) %>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% has_categories = deliverable.project.issue_categories.count > 0 %>
|
||||
|
||||
<div id="deliverable-activities" class="deliverable-finance-report" style=" width: 48%">
|
||||
@@ -27,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 %>
|
||||
|
||||
@@ -77,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 %>
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
<%= render :partial => 'finances', :locals => {:contract => @contract, :deliverable => @contract.deliverables.find(params[:id])} %>
|
||||
<%= render :partial => 'finances', :locals => {:contract => @contract, :deliverable => @deliverable, :period => @period } %>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<% if project && project.module_enabled?(:contracts) && User.current.allowed_to?(:assign_deliverable_to_issue, project) %>
|
||||
<% if project.module_enabled?(:contracts) && User.current.allowed_to?(:assign_deliverable_to_issue, project) %>
|
||||
<p>
|
||||
<%= label_tag(:deliverable_id, l(:field_deliverable)) %>
|
||||
<%= select_tag('deliverable_id',
|
||||
|
||||
@@ -2,7 +2,7 @@ jQuery(function($) {
|
||||
$("#ajax-indicator").ajaxStart(function(){ $(this).show().css('z-index', '9999'); });
|
||||
$("#ajax-indicator").ajaxStop(function(){ $(this).hide(); });
|
||||
|
||||
var right_align = $('#contract-terms .finance tr td:nth-child(1) ~ td, .c_overview table.right tr td:nth-child(1) ~ td, #deliverables table tr.click td:nth-child(5) ~ td, .deliverable_finance_table tr.aright td:nth-child(1) ~ td');
|
||||
var right_align = $('#contract-terms .finance tr td:nth-child ~ td, .c_overview table.right tr td:nth-child ~ td, #deliverables table tr.click td:nth-child(5) ~ td, .deliverable_finance_table tr.aright td:nth-child ~ td');
|
||||
|
||||
if (right_align.length > 0) {
|
||||
right_align.after().css("text-align", "right");
|
||||
|
||||
@@ -22,7 +22,7 @@ en:
|
||||
field_account_executive_short: "Acct. Mgr."
|
||||
field_end_date: "End Date"
|
||||
text_new_contract: "New Contract"
|
||||
text_edit_contract_name: "Edit %{name}"
|
||||
text_edit_contract_name: "Edit {{name}}"
|
||||
field_billable_rate: "Billable Rate"
|
||||
field_billable_rate_hint: "$"
|
||||
field_discount: "Discount"
|
||||
@@ -34,7 +34,7 @@ en:
|
||||
field_details: "Details"
|
||||
button_add_new: Add New
|
||||
text_new_deliverable: New Deliverable
|
||||
text_edit_deliverable_title: "Edit %{title}"
|
||||
text_edit_deliverable_title: "Edit {{title}}"
|
||||
field_manager: Manager
|
||||
field_labor: Labor
|
||||
field_overhead: Overhead
|
||||
@@ -43,7 +43,7 @@ en:
|
||||
field_feature_sign_off: Feature Sign Off
|
||||
field_warranty_sign_off: Warranty Sign Off
|
||||
text_deliverable_finances: Deliverable Finances
|
||||
text_deliverable_finances_date: "Deliverable Finances - %{date}"
|
||||
text_deliverable_finances_date: "Deliverable Finances - {{date}}"
|
||||
text_short_hours: hrs
|
||||
text_dollar_sign: '$'
|
||||
field_client_point_of_contact: "Point of Contact"
|
||||
@@ -85,15 +85,15 @@ en:
|
||||
text_changed_period_message: "The period for this deliverable has been changed. Would you like to expand/shrink the Deliverable Finances?"
|
||||
field_current_period: "Current period"
|
||||
text_retainer_monthly_message: "Enter budget for a representative month. Any overrides to individual months can be done via the editor after saving."
|
||||
text_flash_deliverable_created: "Deliverable: %{name} was successfully created."
|
||||
text_flash_deliverable_updated: "Deliverable: %{name} was successfully updated."
|
||||
text_flash_deliverable_deleted: "Deliverable: %{name} was successfully deleted."
|
||||
text_flash_deliverable_created: "Deliverable: {{name}} was successfully created."
|
||||
text_flash_deliverable_updated: "Deliverable: {{name}} was successfully updated."
|
||||
text_flash_deliverable_deleted: "Deliverable: {{name}} was successfully deleted."
|
||||
field_budget: Budget
|
||||
field_markup: Markup
|
||||
field_paid: Paid
|
||||
field_spent: Spent
|
||||
field_profit: Profit
|
||||
text_error_message_orphaned_time: "There is %{amount} worth of time clocked to issues that are not assigned to any deliverables."
|
||||
text_error_message_orphaned_time: "There is {{amount}} worth of time clocked to issues that are not assigned to any deliverables."
|
||||
text_error_message_update_orphaned_time: "Please update the orphaned issues."
|
||||
field_estimated: Estimated
|
||||
text_deliverable_locked_warning: "This deliverable is locked and cannot be saved without changing it's status to Open."
|
||||
|
||||
@@ -6,25 +6,15 @@ module RedmineContracts
|
||||
context[:controller].is_a?(ContractsController) ||
|
||||
context[:controller].is_a?(DeliverablesController)
|
||||
)
|
||||
tags = [stylesheet_link_tag("redmine_contracts", :plugin => "redmine_contracts", :media => "screen")]
|
||||
tags << stylesheet_link_tag('smoothness/jquery-ui-1.8.15.custom.css', :plugin => "redmine_contracts")
|
||||
return stylesheet_link_tag("redmine_contracts", :plugin => "redmine_contracts", :media => "screen") +
|
||||
stylesheet_link_tag('smoothness/jquery-ui-1.8.15.custom.css', :plugin => "redmine_contracts") +
|
||||
|
||||
jquery_included = begin
|
||||
ChiliProject::Compatibility && ChiliProject::Compatibility.using_jquery?
|
||||
rescue NameError
|
||||
# No compatibilty test
|
||||
false
|
||||
end
|
||||
unless jquery_included
|
||||
tags << javascript_include_tag('jquery-1.4.4.min.js', :plugin => 'redmine_contracts')
|
||||
tags << javascript_tag('jQuery.noConflict();')
|
||||
end
|
||||
|
||||
tags << javascript_include_tag('jquery.tmpl.min.js', :plugin => 'redmine_contracts')
|
||||
tags << javascript_include_tag('jquery-ui-1.8.15.custom.min.js', :plugin => "redmine_contracts")
|
||||
tags << javascript_include_tag('contracts.js', :plugin => 'redmine_contracts')
|
||||
javascript_include_tag('jquery-1.4.4.min.js', :plugin => 'redmine_contracts') +
|
||||
javascript_include_tag('jquery.tmpl.min.js', :plugin => 'redmine_contracts') +
|
||||
javascript_include_tag('jquery-ui-1.8.15.custom.min.js', :plugin => "redmine_contracts") +
|
||||
javascript_tag('jQuery.noConflict();') +
|
||||
javascript_include_tag('contracts.js', :plugin => 'redmine_contracts')
|
||||
|
||||
return tags.join(' ')
|
||||
else
|
||||
return ''
|
||||
end
|
||||
|
||||
@@ -16,6 +16,27 @@ module RedmineContracts
|
||||
end
|
||||
|
||||
module InstanceMethods
|
||||
def billable_activities
|
||||
activities_sorted_by_billable[:billable]
|
||||
end
|
||||
|
||||
def non_billable_activities
|
||||
activities_sorted_by_billable[:non_billable]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def activities_sorted_by_billable
|
||||
split_activities = activities.partition do |activity|
|
||||
activity.billable?
|
||||
end
|
||||
|
||||
{
|
||||
:billable => split_activities.first,
|
||||
:non_billable => split_activities.second
|
||||
}
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
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
|
||||
|
||||
@@ -118,34 +118,6 @@ class DeliverablesEditTest < ActionController::IntegrationTest
|
||||
assert_equal 1000.0, @overhead_budget.budget
|
||||
end
|
||||
|
||||
should "not create new budget items for the deliverable if the activity, hours, and dollars are not all blank" do
|
||||
TimeEntryActivity.destroy_all
|
||||
visit_contract_page(@contract)
|
||||
click_link_within "#deliverable_details_#{@hourly_deliverable.id}", 'Edit'
|
||||
assert_response :success
|
||||
assert_template 'deliverables/edit'
|
||||
|
||||
within("#deliverable-labor") do
|
||||
fill_in "hrs", :with => ''
|
||||
fill_in "$", :with => '$0'
|
||||
end
|
||||
|
||||
within("#deliverable-overhead") do
|
||||
fill_in "hrs", :with => '0'
|
||||
fill_in "$", :with => ''
|
||||
end
|
||||
|
||||
click_button "Save"
|
||||
|
||||
assert_response :success
|
||||
assert_template 'contracts/show'
|
||||
|
||||
@hourly_deliverable.reload
|
||||
assert_equal 0, @hourly_deliverable.labor_budgets.count
|
||||
assert_equal 0, @hourly_deliverable.overhead_budgets.count
|
||||
assert_equal 0, @hourly_deliverable.fixed_budgets.count
|
||||
end
|
||||
|
||||
should "show allow editing the Deliverable Finances section for each Retainer period" do
|
||||
@retainer_deliverable = RetainerDeliverable.spawn(:contract => @contract, :manager => @manager, :title => "Retainer")
|
||||
@retainer_deliverable.labor_budgets << @labor_budget = LaborBudget.spawn(:deliverable => @retainer_deliverable, :budget => 1000, :hours => 10)
|
||||
@@ -504,8 +476,8 @@ class DeliverablesEditTest < ActionController::IntegrationTest
|
||||
assert_equal [100, nil, nil], @retainer_deliverable.overhead_budgets.collect(&:hours)
|
||||
assert_equal [100, nil, nil], @retainer_deliverable.overhead_budgets.collect(&:budget)
|
||||
|
||||
assert_equal 1, @retainer_deliverable.fixed_budgets.count
|
||||
assert_equal [600], @retainer_deliverable.fixed_budgets.collect(&:budget)
|
||||
assert_equal 3, @retainer_deliverable.fixed_budgets.count
|
||||
assert_equal [600, nil, nil], @retainer_deliverable.fixed_budgets.collect(&:budget)
|
||||
end
|
||||
|
||||
context "locked deliverable" do
|
||||
|
||||
@@ -278,50 +278,4 @@ class DeliverablesNewTest < ActionController::IntegrationTest
|
||||
|
||||
end
|
||||
|
||||
should "not create new budget items for the deliverable if the activity, hours, and dollars are all blank" do
|
||||
@manager = User.generate!
|
||||
@role = Role.generate!
|
||||
User.add_to_project(@manager, @project, @role)
|
||||
TimeEntryActivity.destroy_all
|
||||
|
||||
visit_contract_page(@contract)
|
||||
click_link 'Add New'
|
||||
assert_response :success
|
||||
|
||||
within("#deliverable-details") do
|
||||
fill_in "Title", :with => 'A New Deliverable with blanks'
|
||||
select "Hourly", :from => "Type"
|
||||
select @manager.name, :from => "Manager"
|
||||
end
|
||||
|
||||
within("#deliverable-labor") do
|
||||
# no activity selected
|
||||
fill_in "hrs", :with => ''
|
||||
fill_in "$", :with => '$0'
|
||||
end
|
||||
|
||||
within("#deliverable-overhead") do
|
||||
# no activity selected
|
||||
fill_in "hrs", :with => '0'
|
||||
fill_in "$", :with => ''
|
||||
end
|
||||
|
||||
within("#deliverable-fixed") do
|
||||
fill_in "title", :with => ''
|
||||
fill_in "budget", :with => '$0'
|
||||
fill_in "markup", :with => ''
|
||||
end
|
||||
|
||||
click_button "Save"
|
||||
|
||||
assert_response :success
|
||||
assert_template 'contracts/show'
|
||||
|
||||
@deliverable = Deliverable.last
|
||||
assert_equal "A New Deliverable with blanks", @deliverable.title
|
||||
assert_equal 0, @deliverable.labor_budgets.count
|
||||
assert_equal 0, @deliverable.overhead_budgets.count
|
||||
assert_equal 0, @deliverable.fixed_budgets.count
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
+4
-2
@@ -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
|
||||
|
||||
@@ -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,6 +205,28 @@ 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" do
|
||||
configure_overhead_plugin
|
||||
create_contract_and_deliverable
|
||||
create_issue_with_time_for_deliverable(@deliverable, {
|
||||
:activity => @billable_activity,
|
||||
:user => @manager,
|
||||
:hours => 5,
|
||||
:amount => 100,
|
||||
:spent_on => Date.new(2011,10,1)
|
||||
})
|
||||
create_issue_with_time_for_deliverable(@deliverable, {
|
||||
:activity => @billable_activity,
|
||||
:user => @manager,
|
||||
:hours => 2,
|
||||
:amount => 100,
|
||||
:spent_on => Date.new(2011,11,1)
|
||||
})
|
||||
|
||||
assert_equal 2.0, @deliverable.hours_spent_for_activity(@billable_activity, :period => Date.new(2011,11,5)).to_f
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -183,7 +240,16 @@ 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
|
||||
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 20.0, @deliverable.hours_budget_for_activity(@billable_activity, :period => Date.new(2010, 2, 5)).to_f # 20 * 1 months (retainer)
|
||||
end
|
||||
end
|
||||
|
||||
context "#users_with_billable_time" do
|
||||
|
||||
Reference in New Issue
Block a user