]> source.dussan.org Git - redmine.git/commitdiff
Adds a "Copied from/to" relation when copying issue(s) (#6899).
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Thu, 27 Sep 2012 19:09:30 +0000 (19:09 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Thu, 27 Sep 2012 19:09:30 +0000 (19:09 +0000)
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@10491 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/models/issue.rb
app/models/issue_relation.rb
config/locales/en.yml
config/locales/fr.yml
test/functional/issues_controller_test.rb
test/unit/issue_test.rb

index 86371d5f742422df68b8e9fefbc66d74bc5be86d..0d226455d575d0edcb8be71cf437c2f5db384b09 100644 (file)
@@ -1011,11 +1011,20 @@ class Issue < ActiveRecord::Base
     end
   end
 
-  # Copies subtasks from the copied issue
+  # Callback for after the creation of an issue by copy
+  # * adds a "copied to" relation with the copied issue
+  # * copies subtasks from the copied issue
   def after_create_from_copy
-    return unless copy?
+    return unless copy? && !@after_create_from_copy_handled
 
-    unless @copied_from.leaf? || @copy_options[:subtasks] == false || @subtasks_copied
+    if @copied_from.project_id == project_id || Setting.cross_project_issue_relations?
+      relation = IssueRelation.new(:issue_from => @copied_from, :issue_to => self, :relation_type => IssueRelation::TYPE_COPIED_TO)
+      unless relation.save
+        logger.error "Could not create relation while copying ##{@copied_from.id} to ##{id} due to validation errors: #{relation.errors.full_messages.join(', ')}" if logger
+      end
+    end
+
+    unless @copied_from.leaf? || @copy_options[:subtasks] == false
       @copied_from.children.each do |child|
         unless child.visible?
           # Do not copy subtasks that are not visible to avoid potential disclosure of private data
@@ -1031,8 +1040,8 @@ class Issue < ActiveRecord::Base
           logger.error "Could not copy subtask ##{child.id} while copying ##{@copied_from.id} to ##{id} due to validation errors: #{copy.errors.full_messages.join(', ')}" if logger
         end
       end
-      @subtasks_copied = true
     end
+    @after_create_from_copy_handled = true
   end
 
   def update_nested_set_attributes
index 2efcfb41af8a5765f99d879703bb41d99410bf7d..c145b87b97b355b555c03a2da82b69283a96ead2 100644 (file)
@@ -26,6 +26,8 @@ class IssueRelation < ActiveRecord::Base
   TYPE_BLOCKED      = "blocked"
   TYPE_PRECEDES     = "precedes"
   TYPE_FOLLOWS      = "follows"
+  TYPE_COPIED_TO    = "copied_to"
+  TYPE_COPIED_FROM  = "copied_from"
 
   TYPES = { TYPE_RELATES =>     { :name => :label_relates_to, :sym_name => :label_relates_to, :order => 1, :sym => TYPE_RELATES },
             TYPE_DUPLICATES =>  { :name => :label_duplicates, :sym_name => :label_duplicated_by, :order => 2, :sym => TYPE_DUPLICATED },
@@ -33,7 +35,9 @@ class IssueRelation < ActiveRecord::Base
             TYPE_BLOCKS =>      { :name => :label_blocks, :sym_name => :label_blocked_by, :order => 4, :sym => TYPE_BLOCKED },
             TYPE_BLOCKED =>     { :name => :label_blocked_by, :sym_name => :label_blocks, :order => 5, :sym => TYPE_BLOCKS, :reverse => TYPE_BLOCKS },
             TYPE_PRECEDES =>    { :name => :label_precedes, :sym_name => :label_follows, :order => 6, :sym => TYPE_FOLLOWS },
-            TYPE_FOLLOWS =>     { :name => :label_follows, :sym_name => :label_precedes, :order => 7, :sym => TYPE_PRECEDES, :reverse => TYPE_PRECEDES }
+            TYPE_FOLLOWS =>     { :name => :label_follows, :sym_name => :label_precedes, :order => 7, :sym => TYPE_PRECEDES, :reverse => TYPE_PRECEDES },
+            TYPE_COPIED_TO =>   { :name => :label_copied_to, :sym_name => :label_copied_from, :order => 8, :sym => TYPE_COPIED_FROM },
+            TYPE_COPIED_FROM => { :name => :label_copied_from, :sym_name => :label_copied_to, :order => 9, :sym => TYPE_COPIED_TO, :reverse => TYPE_COPIED_TO }
           }.freeze
 
   validates_presence_of :issue_from, :issue_to, :relation_type
index 0133ce247f589813b24191c8afbba8911fd2d957..7ccf38231b8b7c0ec1ed965ef40c0695968b1b29 100644 (file)
@@ -744,6 +744,8 @@ en:
   label_blocked_by: blocked by
   label_precedes: precedes
   label_follows: follows
+  label_copied_to: copied to
+  label_copied_from: copied from
   label_end_to_start: end to start
   label_end_to_end: end to end
   label_start_to_start: start to start
index 7bc0d3a028e543c387ae93aba1a5d38e1e8cb9f9..f71de45a27d5ab32dcd5d28d9063e2cd64076e4c 100644 (file)
@@ -728,6 +728,8 @@ fr:
   label_blocked_by: bloqué par
   label_precedes: précède
   label_follows: suit
+  label_copied_to: copié vers
+  label_copied_from: copié depuis
   label_end_to_start: fin à début
   label_end_to_end: fin à fin
   label_start_to_start: début à début
index fdd995c5657233b127c7bae971b8eebb2ebe6c89..b6e583fdad5dc1c07648a7e589b7dd885a0ad4a7 100644 (file)
@@ -2357,6 +2357,19 @@ class IssuesControllerTest < ActionController::TestCase
     assert_equal count + 1, copy.attachments.count
   end
 
+  def test_create_as_copy_should_add_relation_with_copied_issue
+    @request.session[:user_id] = 2
+
+    assert_difference 'Issue.count' do
+      assert_difference 'IssueRelation.count' do
+        post :create, :project_id => 1, :copy_from => 1,
+          :issue => {:project_id => '1', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
+      end
+    end
+    copy = Issue.first(:order => 'id DESC')
+    assert_equal 1, copy.relations.size
+  end
+
   def test_create_as_copy_should_copy_subtasks
     @request.session[:user_id] = 2
     issue = Issue.generate_with_descendants!(Project.find(1), :subject => 'Parent')
@@ -3512,6 +3525,19 @@ class IssuesControllerTest < ActionController::TestCase
     end
   end
 
+  def test_bulk_copy_should_add_relations_with_copied_issues
+    @request.session[:user_id] = 2
+
+    assert_difference 'Issue.count', 2 do
+      assert_difference 'IssueRelation.count', 2 do
+        post :bulk_update, :ids => [1, 3], :copy => '1', 
+             :issue => {
+               :project_id => '1'
+             }
+      end
+    end
+  end
+
   def test_bulk_copy_should_allow_not_copying_the_subtasks
     issue = Issue.generate_with_descendants!(Project.find(1), :subject => 'Parent')
     @request.session[:user_id] = 2
index fc08313bc0f28bcaffcd8e74954341723013519c..7fdd9cf0f1d36f8bc3d5dbfe0527f53e92557249 100644 (file)
@@ -636,6 +636,19 @@ class IssueTest < ActiveSupport::TestCase
     assert_equal orig.status, issue.status
   end
 
+  def test_copy_should_add_relation_with_copied_issue
+    copied = Issue.find(1)
+    issue = Issue.new.copy_from(copied)
+    assert issue.save
+    issue.reload
+
+    assert_equal 1, issue.relations.size
+    relation = issue.relations.first
+    assert_equal 'copied_to', relation.relation_type
+    assert_equal copied, relation.issue_from
+    assert_equal issue, relation.issue_to
+  end
+
   def test_copy_should_copy_subtasks
     issue = Issue.generate_with_descendants!(Project.find(1), :subject => 'Parent')