diff --git a/init.rb b/init.rb index d9edd6b..594f0ee 100644 --- a/init.rb +++ b/init.rb @@ -93,7 +93,7 @@ Dispatcher.to_prepare :redmine_contracts do end unless Query.available_columns.collect(&:name).include?(:contract_name) - Query.add_available_column(QueryColumn.new(:contract_name, :sortable => "#{Contract.table_name}.name")) + Query.add_available_column(QueryColumn.new(:contract_name, :sortable => "#{Contract.table_name}.name", :groupable => 'contract_id')) end end diff --git a/lib/redmine_contracts/patches/query_patch.rb b/lib/redmine_contracts/patches/query_patch.rb index fa8819a..35779fe 100644 --- a/lib/redmine_contracts/patches/query_patch.rb +++ b/lib/redmine_contracts/patches/query_patch.rb @@ -14,6 +14,34 @@ module RedmineContracts alias_method_chain :sql_for_field, :contract alias_method_chain :issues, :deliverable + alias_method_chain :issues, :contract + + # Override Query#count_by_group to allow adding include options like + # Query#issues + # TODO: core bug: Query#issue_count_by_group doesn't allow setting + # options like Query#issue does. + def issue_count_by_group(options={}) + includes = ([:status, :project] + (options[:include] || [])).uniq + + r = nil + if grouped? + begin + # Rails will raise an (unexpected) RecordNotFound if there's only a nil group value + r = Issue.count(:group => group_by_statement, :include => includes, :conditions => statement) + rescue ActiveRecord::RecordNotFound + r = {nil => issue_count} + end + c = group_by_column + if c.is_a?(QueryCustomFieldColumn) + r = r.keys.inject({}) {|h, k| h[c.custom_field.cast_value(k)] = r[k]; h} + end + end + r + rescue ::ActiveRecord::StatementInvalid => e + raise ::Query::StatementInvalid.new(e.message) + end + + alias_method_chain :issue_count_by_group, :contract end end @@ -95,8 +123,26 @@ module RedmineContracts issues_without_deliverable(options) end - # TODO: core bug: Query#issue_count_by_group doesn't allow setting - # options like Query#issue does. + # Add the contracts into the includes + # + # Used with grouping + def issues_with_contract(options={}) + options[:include] ||= [] + options[:include] << {:deliverable => :contract} + + issues_without_contract(options) + end + + # Add the contracts into the includes + # + # Used with grouping + def issue_count_by_group_with_contract(options={}) + options[:include] ||= [] + options[:include] << {:deliverable => :contract} + + issue_count_by_group_without_contract(options) + end + end end diff --git a/test/integration/issue_filtering_test.rb b/test/integration/issue_filtering_test.rb index b831092..60d73fe 100644 --- a/test/integration/issue_filtering_test.rb +++ b/test/integration/issue_filtering_test.rb @@ -42,4 +42,28 @@ class IssueFilteringTest < ActionController::IntegrationTest end + should "allow grouping issues by contract" do + visit_project(@project) + click_link "Issues" + + assert_select '#group_by' do + assert_select 'option', "Contract" + end + + select "Contract", :from => 'group_by' + + # Apply link is behind a JavaScript form + visit "/projects/#{@project.identifier}/issues/?set_filter&group_by=contract_name" + assert_response :success + + assert_select "tr.group" do + assert_select "td", :text => /None/ + end + + assert_select "tr.group" do + assert_select "td", :text => Regexp.new(@contract.name) + end + + end + end