From 4d2f3573cf4151fa5cb787121ea41edbc2e5d8fd Mon Sep 17 00:00:00 2001 From: Yalaeddin Date: Fri, 15 Dec 2023 16:05:04 +0100 Subject: [PATCH] =?UTF-8?q?Mise=20=C3=A0=20jour=20par=20un=20membre=20d'un?= =?UTF-8?q?e=20organisation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/locales/en.yml | 1 + config/locales/fr.yml | 1 + .../patches/issue_query_patch.rb | 24 +++++ spec/models/issue_query_patch_spec.rb | 96 +++++++++++++++++++ 4 files changed, 122 insertions(+) create mode 100644 spec/models/issue_query_patch_spec.rb diff --git a/config/locales/en.yml b/config/locales/en.yml index 475025b..651682b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -32,3 +32,4 @@ en: button_delete_all: "Delete all" organization_delete_all_confirm: "Are you sure to remove all members of this organization?" inherited_from_parent_project: "Inherited from parent project" + field_updated_by_organization: Updated by member of diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 0351c81..4fbdc0c 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -58,3 +58,4 @@ fr: no_missing_organizations: "Aucune organisation à ajouter depuis le LDAP pour ce chemin : %{path}" inherited_from_parent_project: "Hérité du projet parent" field_top_department_in_ldap: "Département racine dans le LDAP" + field_updated_by_organization: Mise à jour par un membre de diff --git a/lib/redmine_organizations/patches/issue_query_patch.rb b/lib/redmine_organizations/patches/issue_query_patch.rb index 88177d4..572ebc7 100644 --- a/lib/redmine_organizations/patches/issue_query_patch.rb +++ b/lib/redmine_organizations/patches/issue_query_patch.rb @@ -2,6 +2,8 @@ class IssueQuery < Query self.available_columns << QueryColumn.new(:author_organization, :groupable => false) if self.available_columns.select { |c| c.name == :author_organization }.empty? + self.available_columns << QueryColumn.new(:updated_by_organization, :sortable => "#{Journal.table_name}.created_on", + :default_order => 'desc', :groupable => true) if self.available_columns.select { |c| c.name == :updated_by_organization }.empty? end module PluginOrganizations @@ -24,6 +26,10 @@ def initialize_available_filters :type => :list_optional, :values => lambda {organization_values}, :label => :field_author_organization + add_available_filter "updated_by_organization", + :type => :list_optional, + :values => lambda {organization_values}, + :label => :field_updated_by_organization end def sql_for_author_organization_field(field, operator, value) @@ -46,6 +52,24 @@ def sql_for_author_organization_field(field, operator, value) end end + def sql_for_updated_by_organization_field(field, operator, value) + if value.delete('mine') + value.push User.current&.organization&.id&.to_s + end + cond = value.any? ? + "#{User.table_name}.organization_id IN (" + value.collect{|val| "'#{self.class.connection.quote_string(val)}'"}.join(",") + ")" : + "1=0" + + neg = (operator == '!' ? 'NOT' : '') + + subquery = "SELECT 1 FROM #{Journal.table_name}" + + " WHERE #{Journal.table_name}.journalized_type='Issue' AND #{Journal.table_name}.journalized_id=#{Issue.table_name}.id" + + " AND (journals.user_id IN (SELECT DISTINCT #{User.table_name}.id FROM #{User.table_name} WHERE #{cond}))" + + " AND (#{Journal.visible_notes_condition(User.current, :skip_pre_condition => true)})" + + "#{neg} EXISTS (#{subquery})" + end + def organization_values organization_values = [] if User.current.logged? diff --git a/spec/models/issue_query_patch_spec.rb b/spec/models/issue_query_patch_spec.rb new file mode 100644 index 0000000..9d91b32 --- /dev/null +++ b/spec/models/issue_query_patch_spec.rb @@ -0,0 +1,96 @@ +require "spec_helper" + +describe "IssueQueryPatch" do + fixtures :organizations, :users, :roles, :projects, :members, :trackers + + context "should filter issues with updated_by_organization" do + before do + @org = Organization.create(:name => "Team C") + @user = User.generate! + @user.update_attribute(:organization_id, @org.id) + end + + def find_issues_with_query(query) + Issue.joins(:status, :tracker, :project, :priority).where( + query.statement + ).to_a + end + + it "Should have updated_by_organization in available_filters" do + query = IssueQuery.new(:name => '_') + expect(query.available_filters.keys).to include('updated_by_organization') + end + + it "operator equal =, one organization" do + Journal.create!(:user_id => @user.id, :journalized => Issue.find(2), :notes => 'Notes') + Journal.create!(:user_id => @user.id, :journalized => Issue.find(3), :notes => 'Notes') + Journal.create!(:user_id => 2, :journalized => Issue.find(4), :notes => 'Notes') + + query = IssueQuery.new(:name => '_') + filter_name = "updated_by_organization" + query.filters = { filter_name => {:operator => '=', :values => [@org.id.to_s] }} + + expect(find_issues_with_query(query).map(&:id).sort).to include([2, 3]) + end + + it "operator equal ! , one organization" do + Journal.create!(:user_id => @user.id, :journalized => Issue.find(2), :notes => 'Notes') + Journal.create!(:user_id => @user.id, :journalized => Issue.find(3), :notes => 'Notes') + Journal.create!(:user_id => 2, :journalized => Issue.find(4), :notes => 'Notes') + + query = IssueQuery.new(:name => '_') + filter_name = "updated_by_organization" + query.filters = { filter_name => {:operator => '!', :values => [@org.id.to_s] }} + + expect(find_issues_with_query(query).map(&:id).sort).to_not include([2, 3]) + end + + it "operator equal = , multi organizations" do + user_test = User.find(2) + org_test = Organization.find(2) + user_test.update_attribute(:organization_id, org_test.id) + + Journal.create!(:user_id => @user.id, :journalized => Issue.find(2), :notes => 'Notes') + Journal.create!(:user_id => @user.id, :journalized => Issue.find(3), :notes => 'Notes') + Journal.create!(:user_id => user_test.id, :journalized => Issue.find(4), :notes => 'Notes') + + query = IssueQuery.new(:name => '_') + filter_name = "updated_by_organization" + query.filters = { filter_name => {:operator => '=', :values => [@org.id.to_s, org_test.id.to_s] }} + + expect(find_issues_with_query(query).map(&:id).sort).to include(2, 3, 4) + end + + it "operator equal ! , multi organizations" do + user_test = User.find(2) + org_test = Organization.find(2) + user_test.update_attribute(:organization_id, org_test.id) + + Journal.create!(:user_id => @user.id, :journalized => Issue.find(2), :notes => 'Notes') + Journal.create!(:user_id => @user.id, :journalized => Issue.find(3), :notes => 'Notes') + Journal.create!(:user_id => user_test.id, :journalized => Issue.find(4), :notes => 'Notes') + + query = IssueQuery.new(:name => '_') + filter_name = "updated_by_organization" + query.filters = { filter_name => {:operator => '=', :values => [@org.id.to_s, org_test.id.to_s] }} + + expect(find_issues_with_query(query).map(&:id).sort).to_not include([2, 3, 4]) + end + + it "Should ignore private notes that are not visible" do + Journal.create!(:user_id => @user.id, :journalized => Issue.find(2), :notes => 'Notes', :private_notes => true) + Journal.create!(:user_id => @user.id, :journalized => Issue.find(3), :notes => 'Notes') + + query = IssueQuery.new(:name => '_') + filter_name = "updated_by_organization" + query.filters = {filter_name => {:operator => '=', :values => [@org.id.to_s]}} + + expect(find_issues_with_query(query).map(&:id).sort).to eq([2, 3]) + + User.current = User.anonymous + query.filters = {filter_name => {:operator => '=', :values => [@org.id.to_s]}} + + expect(find_issues_with_query(query).map(&:id).sort).to eq([3]) + end + end +end