diff --git a/app/controllers/deliverables_controller.rb b/app/controllers/deliverables_controller.rb index 3fb4f0b..9e56b73 100644 --- a/app/controllers/deliverables_controller.rb +++ b/app/controllers/deliverables_controller.rb @@ -36,6 +36,14 @@ class DeliverablesController < InheritedResources::Base end end + def finances + respond_to do |format| + format.js { render :partial => 'deliverables/finances', :locals => {:contract => @contract, :deliverable => @contract.deliverables.find(params[:id])} } + format.html { } + end + + end + def destroy destroy!(:notice => l(:text_flash_deliverable_deleted, :name => resource.title)) { contract_url(@project, @contract) } end diff --git a/app/views/deliverables/_details_row.html.erb b/app/views/deliverables/_details_row.html.erb index 1c4544e..6d1e41b 100644 --- a/app/views/deliverables/_details_row.html.erb +++ b/app/views/deliverables/_details_row.html.erb @@ -54,7 +54,7 @@ - <%= link_to(l(:field_labor), "#", :class => 'deliverable-action-link deliverable-lightbox', "data-deliverable-id" => h(deliverable.id)) %> + <%= link_to(l(:field_labor), finances_contract_deliverable_path(@project, contract, deliverable), :class => 'deliverable-action-link deliverable-lightbox', "data-deliverable-id" => h(deliverable.id)) %> <%= h(format_value_field_for_contracts(deliverable.labor_budget_spent(validated_period))) %> @@ -69,7 +69,7 @@ - <%= link_to(l(:field_overhead), "#", :class => 'deliverable-action-link deliverable-lightbox', "data-deliverable-id" => h(deliverable.id)) %> + <%= link_to(l(:field_overhead), finances_contract_deliverable_path(@project, contract, deliverable), :class => 'deliverable-action-link deliverable-lightbox', "data-deliverable-id" => h(deliverable.id)) %> <%= h(format_value_field_for_contracts(deliverable.overhead_spent(validated_period))) %> diff --git a/app/views/deliverables/_finances.html.erb b/app/views/deliverables/_finances.html.erb new file mode 100644 index 0000000..26aeae5 --- /dev/null +++ b/app/views/deliverables/_finances.html.erb @@ -0,0 +1,8 @@ +
+ <%= l(:text_deliverable_spending_summary, + :spent => content_tag(:span, h(number_to_currency(deliverable.labor_budget_spent, :precision => 0)), :class => 'spent'), + :total => content_tag(:span, h(number_to_currency(deliverable.labor_budget_total, :precision => 0)), :class => 'total'), + :hours => content_tag(:span, h(deliverable.labor_hours_spent_total), :class => 'hours')) %> +
+ +

<%= h(deliverable.title) %>

diff --git a/app/views/deliverables/finances.html.erb b/app/views/deliverables/finances.html.erb new file mode 100644 index 0000000..8109183 --- /dev/null +++ b/app/views/deliverables/finances.html.erb @@ -0,0 +1 @@ +<%= render :partial => 'finances', :locals => {:contract => @contract, :deliverable => @contract.deliverables.find(params[:id])} %> diff --git a/assets/javascripts/contracts.js b/assets/javascripts/contracts.js index 0e72c44..181267b 100644 --- a/assets/javascripts/contracts.js +++ b/assets/javascripts/contracts.js @@ -197,7 +197,8 @@ jQuery(function($) { $('#dialog-window'). hide(). - html('

Hello

This is a report for Deliverable #' + deliverableId + '.

'). + html(''). + load($(this).attr('href') + ".js"). dialog({ title: "", minWidth: 400, diff --git a/config/locales/en.yml b/config/locales/en.yml index fc61d00..e846dda 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -101,3 +101,4 @@ en: text_contract_locked_warning: "This contract is locked and cannot be saved without changing it's status to Open." text_contract_closed_warning: "This contract is closed and cannot be saved without changing it's status to Open." field_time_entry_activity: "Activity" + text_deliverable_spending_summary: "You've spent %{spent} / %{total} and %{hours} Billable Hours" diff --git a/config/routes.rb b/config/routes.rb index 811ed99..ec1a9ab 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,5 @@ ActionController::Routing::Routes.draw do |map| map.resources :contracts, :path_prefix => '/projects/:project_id' do |contracts| - contracts.resources :deliverables + contracts.resources :deliverables, :member => {:finances => :get} end end diff --git a/init.rb b/init.rb index ea166d9..c7a1c6a 100644 --- a/init.rb +++ b/init.rb @@ -17,7 +17,7 @@ Redmine::Plugin.register :redmine_contracts do project_module :contracts do permission(:manage_budget, { :contracts => [:index, :new, :create, :show, :edit, :update, :destroy], - :deliverables => [:index, :new, :create, :show, :edit, :update, :destroy] + :deliverables => [:index, :new, :create, :show, :edit, :update, :destroy, :finances] }) end diff --git a/test/integration/deliverable_finances_test.rb b/test/integration/deliverable_finances_test.rb new file mode 100644 index 0000000..49bfbb1 --- /dev/null +++ b/test/integration/deliverable_finances_test.rb @@ -0,0 +1,77 @@ +require 'test_helper' + +class DeliverableFinancesShowTest < ActionController::IntegrationTest + include Redmine::I18n + + def setup + configure_overhead_plugin + @project = Project.generate!(:identifier => 'main').reload + @contract = Contract.generate!(:project => @project, :billable_rate => 10) + @manager = User.generate! + @deliverable1 = RetainerDeliverable.spawn(:contract => @contract, :manager => @manager, :title => "Retainer Title", :start_date => '2010-01-01', :end_date => '2010-03-31') + @deliverable1.labor_budgets << LaborBudget.spawn(:budget => 100, :hours => 10) + @deliverable1.overhead_budgets << OverheadBudget.spawn(:budget => 200, :hours => 10) + + @deliverable1.save! + @user = User.generate_user_with_permission_to_manage_budget(:project => @project) + # 2 hours of $100 billable work + @issue1 = Issue.generate_for_project!(@project) + @time_entry1 = TimeEntry.generate!(:issue => @issue1, + :project => @project, + :activity => @billable_activity, + :spent_on => Date.today, + :hours => 2, + :user => @manager) + @rate = Rate.generate!(:project => @project, + :user => @manager, + :date_in_effect => Date.yesterday, + :amount => 100) + @deliverable1.issues << @issue1 + + @user.reload + login_as(@user.login, 'contracts') + end + + context "for an anonymous request" do + should "require login" do + logout + + visit "/projects/#{@project.id}/contracts/#{@contract.id}/deliverables/#{@deliverable1.id}/finances" + + assert_response :success + assert_template 'account/login' + end + + end + + context "for an unauthorized request" do + should "be forbidden" do + logout + + @user = User.generate!(:password => 'test', :password_confirmation => 'test') + login_as(@user.login, 'test') + + visit "/projects/#{@project.id}/contracts/#{@contract.id}/deliverables/#{@deliverable1.id}/finances" + + assert_response :forbidden + end + + end + + + context "for an authorized request" do + should "render the finance report title section for the deliverable" do + visit "/projects/#{@project.id}/contracts/#{@contract.id}/deliverables/#{@deliverable1.id}/finances" + + assert_response :success + assert_select "h2", :text => /#{@deliverable1.title}/ + + assert_select "div#summary" do + assert_select "span.spent", :text => /\$200/ # $100 * 2 + assert_select "span.total", :text => /\$300/ # $100 * 3 + assert_select "span.hours", :text => /2/ + end + end + + end +end diff --git a/test/unit/lib/redmine_contracts/hooks/view_layouts_base_html_head_hook_test.rb b/test/unit/lib/redmine_contracts/hooks/view_layouts_base_html_head_hook_test.rb index e4b11c4..dabebb3 100644 --- a/test/unit/lib/redmine_contracts/hooks/view_layouts_base_html_head_hook_test.rb +++ b/test/unit/lib/redmine_contracts/hooks/view_layouts_base_html_head_hook_test.rb @@ -38,7 +38,7 @@ class RedmineContracts::Hooks::ViewLayoutsBaseHtmlHeadTest < ActionController::T should "load jquery" do @response.body = hook - assert_select "script[src*=?]", "jquery-1.4.2.min.js" + assert_select "script[src*=?]", "jquery-1.4.4.min.js" end should "load the contracts.js JavaScript" do @@ -60,7 +60,7 @@ class RedmineContracts::Hooks::ViewLayoutsBaseHtmlHeadTest < ActionController::T should "load jquery" do @response.body = hook - assert_select "script[src*=?]", "jquery-1.4.2.min.js" + assert_select "script[src*=?]", "jquery-1.4.4.min.js" end should "load the contracts.js JavaScript" do