From 4fa51992b5bfe777601e1fb30e0ea3941f392212 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Sat, 25 Aug 2007 17:45:51 +0000 Subject: [PATCH] Automatic closing of duplicate issues. When closing an issue, all related issues marked as duplicates are now also closed. git-svn-id: http://redmine.rubyforge.org/svn/trunk@663 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/issue.rb | 22 ++++++++++++++++++++++ test/unit/issue_test.rb | 25 +++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/app/models/issue.rb b/app/models/issue.rb index 0e9e7745a..65b34cb92 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -94,7 +94,19 @@ class Issue < ActiveRecord::Base end def after_save + # Update start/due dates of following issues relations_from.each(&:set_issue_to_dates) + + # Close duplicates if the issue was closed + if @issue_before_change && !@issue_before_change.closed? && self.closed? + duplicates.each do |duplicate| + # Don't re-close it if it's already closed + next if duplicate.closed? + # Same user and notes + duplicate.init_journal(@current_journal.user, @current_journal.notes) + duplicate.update_attribute :status, self.status + end + end end def custom_value_for(custom_field) @@ -110,6 +122,11 @@ class Issue < ActiveRecord::Base @current_journal end + # Return true if the issue is closed, otherwise false + def closed? + self.status.is_closed? + end + # Users the issue can be assigned to def assignable_users project.members.select {|m| m.role.assignable?}.collect {|m| m.user} @@ -132,6 +149,11 @@ class Issue < ActiveRecord::Base dependencies end + # Returns an array of the duplicate issues + def duplicates + relations.select {|r| r.relation_type == IssueRelation::TYPE_DUPLICATES}.collect {|r| r.other_issue(self)} + end + def duration (start_date && due_date) ? due_date - start_date : 0 end diff --git a/test/unit/issue_test.rb b/test/unit/issue_test.rb index 5ebde556d..254bffa20 100644 --- a/test/unit/issue_test.rb +++ b/test/unit/issue_test.rb @@ -24,4 +24,29 @@ class IssueTest < Test::Unit::TestCase issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => Enumeration.get_values('IPRI').first, :subject => 'Assignment test', :description => 'Assignment test', :category_id => 1) assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to end + + def test_close_duplicates + # Create 3 issues + issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => Enumeration.get_values('IPRI').first, :subject => 'Duplicates test', :description => 'Duplicates test') + assert issue1.save + issue2 = issue1.clone + assert issue2.save + issue3 = issue1.clone + assert issue3.save + + # 2 is a dupe of 1 + IssueRelation.create(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES) + # And 3 is a dupe of 2 + IssueRelation.create(:issue_from => issue2, :issue_to => issue3, :relation_type => IssueRelation::TYPE_DUPLICATES) + + assert issue1.reload.duplicates.include?(issue2) + + # Closing issue 1 + issue1.init_journal(User.find(:first), "Closing issue1") + issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true} + assert issue1.save + # 2 and 3 should be also closed + assert issue2.reload.closed? + assert issue3.reload.closed? + end end -- 2.39.5