diff --git a/app/views/issues/_show_deliverable.html.erb b/app/views/issues/_show_deliverable.html.erb
new file mode 100644
index 0000000..1f34b40
--- /dev/null
+++ b/app/views/issues/_show_deliverable.html.erb
@@ -0,0 +1,7 @@
+<% if project.module_enabled?(:contracts) %>
+
+ | <%= l(:field_deliverable) %>: |
+ <%= h(issue.deliverable.title) if issue.deliverable.present? %> | "
+
+<% end %>
+
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 51aa9bd..c1b9531 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -52,3 +52,5 @@ en:
field_total_budget: "Total Budget"
field_total_spent: "Contract Total"
field_contract_type: "Type"
+ field_deliverable: "Deliverable"
+
diff --git a/init.rb b/init.rb
index dd9f542..ca41f17 100644
--- a/init.rb
+++ b/init.rb
@@ -66,3 +66,5 @@ Dispatcher.to_prepare :redmine_contracts do
end
require 'redmine_contracts/hooks/view_layouts_base_html_head_hook'
+require 'redmine_contracts/hooks/view_issues_show_details_bottom_hook'
+require 'redmine_contracts/hooks/view_issues_form_details_bottom_hook'
diff --git a/lib/redmine_contracts/hooks/view_issues_form_details_bottom_hook.rb b/lib/redmine_contracts/hooks/view_issues_form_details_bottom_hook.rb
new file mode 100644
index 0000000..65b1df1
--- /dev/null
+++ b/lib/redmine_contracts/hooks/view_issues_form_details_bottom_hook.rb
@@ -0,0 +1,9 @@
+module RedmineContracts
+ module Hooks
+ class ViewIssuesFormDetailsBottomHook < Redmine::Hook::ViewListener
+ def view_issues_form_details_bottom(context={})
+ return ''
+ end
+ end
+ end
+end
diff --git a/lib/redmine_contracts/hooks/view_issues_show_details_bottom_hook.rb b/lib/redmine_contracts/hooks/view_issues_show_details_bottom_hook.rb
new file mode 100644
index 0000000..a1dfe16
--- /dev/null
+++ b/lib/redmine_contracts/hooks/view_issues_show_details_bottom_hook.rb
@@ -0,0 +1,9 @@
+module RedmineContracts
+ module Hooks
+ class ViewIssuesShowDetailsBottomHook < Redmine::Hook::ViewListener
+ include Redmine::I18n
+
+ render_on(:view_issues_show_details_bottom, :partial => 'issues/show_deliverable', :layout => false)
+ end
+ end
+end
diff --git a/test/unit/lib/redmine_contracts/hooks/view_issues_form_details_bottom_hook_test.rb b/test/unit/lib/redmine_contracts/hooks/view_issues_form_details_bottom_hook_test.rb
new file mode 100644
index 0000000..d24e1fc
--- /dev/null
+++ b/test/unit/lib/redmine_contracts/hooks/view_issues_form_details_bottom_hook_test.rb
@@ -0,0 +1,26 @@
+require File.dirname(__FILE__) + '/../../../../test_helper'
+
+class RedmineContracts::Hooks::ViewIssuesFormDetailsBottomTest < ActionController::TestCase
+ include Redmine::Hook::Helper
+
+ def controller
+ @controller ||= ApplicationController.new
+ @controller.response ||= ActionController::TestResponse.new
+ @controller
+ end
+
+ def request
+ @request ||= ActionController::TestRequest.new
+ end
+
+ def hook(args={})
+ call_hook :view_issues_form_details_bottom, args
+ end
+
+ context "#view_issues_form_details_bottom" do
+ should "return an empty string" do
+ @response.body = hook
+ assert @response.body.blank?
+ end
+ end
+end
diff --git a/test/unit/lib/redmine_contracts/hooks/view_issues_show_details_bottom_hook_test.rb b/test/unit/lib/redmine_contracts/hooks/view_issues_show_details_bottom_hook_test.rb
new file mode 100644
index 0000000..0e42dfb
--- /dev/null
+++ b/test/unit/lib/redmine_contracts/hooks/view_issues_show_details_bottom_hook_test.rb
@@ -0,0 +1,77 @@
+require File.dirname(__FILE__) + '/../../../../test_helper'
+
+class RedmineContracts::Hooks::ViewIssuesShowDetailsBottomTest < ActionController::TestCase
+ include Redmine::Hook::Helper
+
+ # Bloody bloody hack to work around Rails coupling of _VC.
+ def template
+ t = ActionView::Base.new(ActionController::Base.view_paths, {}, @controller)
+ def t.template_format
+ "html"
+ end
+
+ # Rendered views aren't getting access to the controller's I18n module
+ t.send(:extend, Redmine::I18n)
+ t
+ end
+
+ def controller
+ @controller ||= ApplicationController.new
+ @controller.class.send(:include, ::Redmine::I18n)
+ @controller.response ||= ActionController::TestResponse.new
+ # Hack to support render_on
+ @controller.instance_variable_set('@template', template)
+ @controller.response = response
+ @controller
+ end
+
+ def request
+ @request ||= ActionController::TestRequest.new
+ end
+
+ # Hack to support render_on
+ def response
+ @response.template ||= template
+ @response
+ end
+
+ def hook(args={})
+ call_hook :view_issues_show_details_bottom, args
+ end
+
+ context "#view_issues_show_details_bottom" do
+ setup do
+ @project = Project.generate!
+ @issue = Issue.generate_for_project!(@project)
+ @contract = Contract.generate!(:project => @project)
+
+ @manager = User.generate!
+ @role = Role.generate!
+ User.add_to_project(@manager, @project, @role)
+ @deliverable = FixedDeliverable.generate!(:contract => @contract, :manager => @manager, :title => 'The Title')
+ @issue.deliverable = @deliverable
+ end
+
+ context "with Contracts Enabled" do
+ should "render the deliverable's name" do
+ @response.body = hook(:project => @project, :issue => @issue, :controller => controller)
+
+ assert_select "tr" do
+ assert_select "td", :text => /#{@deliverable.title}/
+ end
+ end
+ end
+
+ context "with Contracts Disabled" do
+ setup do
+ @project.enabled_modules.destroy_all
+ end
+
+ should "not render the deliverable's name" do
+ @response.body = hook(:project => @project, :issue => @issue, :controller => controller)
+
+ assert_no_match /#{@deliverable.title}/, @response.body
+ end
+ end
+ end
+end