diff --git a/app/helpers/reporting_helper.rb b/app/helpers/reporting_helper.rb index ad55168ec7..f8fc6c37e2 100644 --- a/app/helpers/reporting_helper.rb +++ b/app/helpers/reporting_helper.rb @@ -115,7 +115,7 @@ module ReportingHelper case key.to_sym when :activity_id then mapped value, Enumeration, "#{l(:caption_material_costs)}" when :project_id then link_to_project Project.find(value.to_i) - when :user_id, :assigned_to_id, :author_id then link_to_user User.find(value.to_i) + when :user_id, :assigned_to_id, :author_id then link_to_user(User.find_by_id(value.to_i) || DeletedUser.first) when :tyear, :units then value.to_s when :tweek then "#{l(:label_week)} ##{value}" when :tmonth then month_name(value.to_i) diff --git a/app/models/cost_query.rb b/app/models/cost_query.rb index b23e12fa48..bd86c384f8 100644 --- a/app/models/cost_query.rb +++ b/app/models/cost_query.rb @@ -3,5 +3,31 @@ require 'report' class CostQuery < Report def_delegators :result, :real_costs + User.before_destroy do |user| + CostQuery.delete_all ['user_id = ? AND is_public = ?', user.id, false] + CostQuery.update_all ['user_id = ?', DeletedUser.first.id], ['user_id = ?', user.id] + + max_query_id = 0 + while((current_queries = CostQuery.all(:limit => 1000, + :conditions => ["id > ?", max_query_id], + :order => "id ASC")).size > 0) do + + current_queries.each do |query| + serialized = query.serialized + + serialized[:filters] = serialized[:filters].map do |name, options| + options[:values].delete(user.id.to_s) if ["UserId", "AuthorId", "AssignedToId"].include?(name) + + options[:values].nil? || options[:values].size > 0 ? + [name, options] : + nil + end.compact + + CostQuery.update_all ["serialized = ?", YAML::dump(serialized)], ["id = ?", query.id] + + max_query_id = query.id + end + end + end end diff --git a/features/filter.feature b/features/filter.feature index 4048c06cf0..da3bdc0368 100644 --- a/features/filter.feature +++ b/features/filter.feature @@ -1,31 +1,35 @@ Feature: Filter - #TODO: Fix test - for more information see #32085 on myproject - #@javascript - #Scenario: When using jump-to-project comming from the overall cost report to a projects report sets the project filter to that project - #Given there is a standard cost control project named "First Project" - #And I am already logged in as "controller" - #And I am on the overall Cost Reports page - #And I jump to project "First Project" - #Then "First Project" should be selected for "project_id_arg_1_val" + @javascript + Scenario: When using jump-to-project comming from the overall cost report to a projects report sets the project filter to that project + Given the desired behaviour is described in #32085 on myproject + Given there is a standard cost control project named "First Project" + And I am already logged in as "controller" + And I am on the overall Cost Reports page + And I jump to project "First Project" + Then "First Project" should be selected for "project_id_arg_1_val" @javascript Scenario: When using jump-to-project comming from a projects cost report to the overall cost report page unsets the project filter + Given the desired behaviour is described in #32085 on myproject Given there is a standard cost control project named "First Project" And I am already logged in as "controller" And I am on the Cost Reports page for the project called "First Project" - And I follow "Cost Reports" - Then "" should be selected for "project_id_arg_1_val" + And I follow "Modules" within "#top-menu-items" + And I follow "Cost Reports" within "#top-menu-items" + Then I should see "New Cost Report" within "h2" + And I should be on the overall Cost Reports page + And "" should be selected for "project_id_arg_1_val" - #TODO: Fix test - for more information see #32085 on myproject - #@javascript - #Scenario: When using jump-to-project comming from a projects cost report to another projects report sets the project filter to the second project - #Given there is a standard cost control project named "First Project" - #And there is a standard cost control project named "Second Project" - #And I am already logged in as "controller" - #And I am on the Cost Reports page for the project called "First Project" - #And I jump to project "Second Project" - #Then "Second Project" should be selected for "project_id_arg_1_val" + @javascript + Scenario: When using jump-to-project comming from a projects cost report to another projects report sets the project filter to the second project + Given the desired behaviour is described in #32085 on myproject + Given there is a standard cost control project named "First Project" + And there is a standard cost control project named "Second Project" + And I am already logged in as "controller" + And I am on the Cost Reports page for the project called "First Project" + And I jump to project "Second Project" + Then "Second Project" should be selected for "project_id_arg_1_val" @javascript Scenario: We got some awesome default settings @@ -57,31 +61,31 @@ Feature: Filter And the user with the login "developer" should be selected for "user_id_arg_1_val" And "!" should be selected for "operators[user_id]" - #TODO: Fix test - for more information see #32085 on myproject - #@javascript - #Scenario: A click on clear enables the option in the Add-Filter-Selectbox - #Given there is a standard cost control project named "First Project" - #And I am already logged in as "controller" - #And I am on the Cost Reports page for the project called "First Project" - #And I wait for Ajax - #Then "user_id" should not be selectable from "add_filter_select" - #And filter "user_id" should be visible - #When I click on "Clear" - #And I wait for Ajax - #Then "user_id" should be selectable from "add_filter_select" + @javascript + Scenario: A click on clear enables the option in the Add-Filter-Selectbox + Given the desired behaviour is described in #32085 on myproject + Given there is a standard cost control project named "First Project" + And I am already logged in as "controller" + And I am on the Cost Reports page for the project called "First Project" + And I wait for Ajax + Then "user_id" should not be selectable from "add_filter_select" + And filter "user_id" should be visible + When I click on "Clear" + And I wait for Ajax + Then "user_id" should be selectable from "add_filter_select" - #TODO: Fix test - for more information see #32085 on myproject - #@javascript - #Scenario: Setting a Filter disables the option in the Add-Filter-Selectbox - #Given there is a standard cost control project named "First Project" - #And I am already logged in as "controller" - #And I am on the Cost Reports page for the project called "First Project" - #And I wait for Ajax - #And I click on "Clear" - #Then "user_id" should be selectable from "add_filter_select" - #And I set the filter "user_id" to the user with the login "developer" with the operator "!" - #And I wait for Ajax - #Then "user_id" should not be selectable from "add_filter_select" - #When I send the query - #Then "user_id" should not be selectable from "add_filter_select" + @javascript + Scenario: Setting a Filter disables the option in the Add-Filter-Selectbox + Given the desired behaviour is described in #32085 on myproject + Given there is a standard cost control project named "First Project" + And I am already logged in as "controller" + And I am on the Cost Reports page for the project called "First Project" + And I wait for Ajax + And I click on "Clear" + Then "user_id" should be selectable from "add_filter_select" + And I set the filter "user_id" to the user with the login "developer" with the operator "!" + And I wait for Ajax + Then "user_id" should not be selectable from "add_filter_select" + When I send the query + Then "user_id" should not be selectable from "add_filter_select" diff --git a/init.rb b/init.rb index e785b38ad3..dda209cbcd 100644 --- a/init.rb +++ b/init.rb @@ -13,7 +13,7 @@ Redmine::Plugin.register :redmine_reporting do author 'Konstantin Haase, Philipp Tessenow @ finnlabs' author_url 'http://finn.de/team' description 'The reporting plugin provides extended reporting functionality for Redmine including Cost Reports.' - version '2.4.5' + version '2.4.6' requires_redmine :version_or_higher => '0.9' requires_redmine_plugin :redmine_costs, :version_or_higher => '0.3' diff --git a/spec/factories/cost_query_factory.rb b/spec/factories/cost_query_factory.rb new file mode 100644 index 0000000000..ad8594e32b --- /dev/null +++ b/spec/factories/cost_query_factory.rb @@ -0,0 +1,13 @@ +Factory.define(:cost_query) do |cq| + cq.association :user, :factory => :user + cq.association :project, :factory => :project + cq.sequence(:name) { |n| "Cost Query #{n}" } +end + +Factory.define(:private_cost_query, :parent => :cost_query) do |cq| + cq.is_public false +end + +Factory.define(:public_cost_query, :parent => :cost_query) do |cq| + cq.is_public true +end diff --git a/spec/models/cost_query/cost_query_spec.rb b/spec/models/cost_query/cost_query_spec.rb new file mode 100644 index 0000000000..7bc1c990a8 --- /dev/null +++ b/spec/models/cost_query/cost_query_spec.rb @@ -0,0 +1,88 @@ +require File.dirname(__FILE__) + '/../../spec_helper' + +describe User, "#destroy" do + let(:substitute_user) { DeletedUser.first } + let(:private_query) { Factory.create(:private_cost_query) } + let(:public_query) { Factory.create(:public_cost_query) } + let(:user) { Factory.create(:user) } + let(:user2) { Factory.create(:user) } + + describe "WHEN the user has saved private cost queries" do + + before do + private_query.user.destroy + end + + it { CostQuery.find_by_id(private_query.id).should == nil } + end + + describe "WHEN the user has saved public cost queries" do + before do + public_query.user.destroy + end + + it { CostQuery.find_by_id(public_query.id).should == public_query } + it { public_query.reload.user_id.should == substitute_user.id } + end + + shared_examples_for "public query" do + let(:filter_symbol) { filter.to_s.demodulize.underscore.to_sym } + + describe "WHEN the filter has the deleted user as it's value" do + before do + public_query.filter(filter_symbol, :values => [user.id.to_s], :operator => "=") + public_query.save! + + user.destroy + end + + it { CostQuery.find_by_id(public_query.id).deserialize.filters.any?{ |f| f.is_a?(filter) }.should be_false } + end + + describe "WHEN the filter has another user as it's value" do + before do + public_query.filter(filter_symbol, :values => [user2.id.to_s], :operator => "=") + public_query.save! + + user.destroy + end + + it { CostQuery.find_by_id(public_query.id).deserialize.filters.any?{ |f| f.is_a?(filter) }.should be_true } + it { CostQuery.find_by_id(public_query.id).deserialize.filters.detect{ |f| f.is_a?(filter) }.values.should == [user2.id.to_s] } + end + + describe "WHEN the filter has the deleted user and another user as it's value" do + before do + public_query.filter(filter_symbol, :values => [user.id.to_s, user2.id.to_s], :operator => "=") + public_query.save! + + user.destroy + end + + it { CostQuery.find_by_id(public_query.id).deserialize.filters.any?{ |f| f.is_a?(filter) }.should be_true } + it { CostQuery.find_by_id(public_query.id).deserialize.filters.detect{ |f| f.is_a?(filter) }.values.should == [user2.id.to_s] } + end + end + + describe "WHEN someone has saved a public cost query + WHEN the query has a user_id filter" do + let(:filter) { CostQuery::Filter::UserId } + + it_should_behave_like "public query" + end + + describe "WHEN someone has saved a public cost query + WHEN the query has a author_id filter" do + let(:filter) { CostQuery::Filter::AuthorId } + + it_should_behave_like "public query" + end + + describe "WHEN someone has saved a public cost query + WHEN the query has a assigned_to_id filter" do + let(:filter) { CostQuery::Filter::AssignedToId } + + it_should_behave_like "public query" + end +end +