summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2007-08-25 17:45:51 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2007-08-25 17:45:51 +0000
commit4fa51992b5bfe777601e1fb30e0ea3941f392212 (patch)
tree25e1886a9503021ee79514690d97b9f424fd7d50
parentb96dc97d150bf9480f18347be8c74d1b27dc1887 (diff)
downloadredmine-4fa51992b5bfe777601e1fb30e0ea3941f392212.tar.gz
redmine-4fa51992b5bfe777601e1fb30e0ea3941f392212.zip
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
-rw-r--r--app/models/issue.rb22
-rw-r--r--test/unit/issue_test.rb25
2 files changed, 47 insertions, 0 deletions
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