diff --git a/app/models/issue.rb b/app/models/issue.rb index 0a7cc5ed3..9dac7d9ca 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -1849,6 +1849,24 @@ class Issue < ApplicationRecord end copied_issue_ids[child.id] = copy.id end + + # Copy the relations between the copied subtasks + IssueRelation.where(:issue_from_id => copied_issue_ids.keys, + :issue_to_id => copied_issue_ids.keys).each do |source_relation| + relation = IssueRelation.new + relation.attributes = source_relation.attributes.except('id', 'issue_from_id', 'issue_to_id') + relation.issue_from_id = copied_issue_ids[source_relation.issue_from_id] + relation.issue_to_id = copied_issue_ids[source_relation.issue_to_id] + unless relation.save + if logger + logger.error( + "Could not copy relation ##{source_relation.id} " \ + "while copying ##{@copied_from.id} to ##{id} due to validation errors: " \ + "#{relation.errors.full_messages.join(', ')}" + ) + end + end + end end @after_create_from_copy_handled = true end diff --git a/test/unit/issue_test.rb b/test/unit/issue_test.rb index b22595c75..5755fcccc 100644 --- a/test/unit/issue_test.rb +++ b/test/unit/issue_test.rb @@ -1475,6 +1475,49 @@ class IssueTest < ActiveSupport::TestCase assert_equal copy.author, child_copy.author end + def test_copy_should_copy_relations_between_subtasks + parent = Issue.generate! + child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child1') + child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child2') + child21 = Issue.generate!(:parent_issue_id => child2.id, :subject => 'Child21') + other = Issue.generate! + IssueRelation.create!(:issue_from => child1, :issue_to => child2, + :relation_type => IssueRelation::TYPE_PRECEDES, :delay => 2) + IssueRelation.create!(:issue_from => child1, :issue_to => child21, + :relation_type => IssueRelation::TYPE_BLOCKS) + IssueRelation.create!(:issue_from => child1, :issue_to => other, + :relation_type => IssueRelation::TYPE_RELATES) + + copy = parent.reload.copy + copy.author = User.find(7) + # copied_to relations for the issue and its 3 subtasks, and the 2 relations between subtasks + assert_difference 'IssueRelation.count', 4 + 2 do + assert copy.save + end + + copies = copy.reload.descendants.index_by(&:subject) + assert_equal [[copies['Child2'].id, IssueRelation::TYPE_PRECEDES, 2], + [copies['Child21'].id, IssueRelation::TYPE_BLOCKS, nil]].sort_by(&:first), + copies['Child1'].relations_from.map {|r| [r.issue_to_id, r.relation_type, r.delay]}.sort_by(&:first) + # Relations to issues outside of the copied subtree are not copied + assert_equal [child1.id], other.reload.relations.map(&:issue_from_id) + end + + def test_copy_without_subtasks_should_not_copy_relations_between_subtasks + parent = Issue.generate! + child1 = Issue.generate!(:parent_issue_id => parent.id) + child2 = Issue.generate!(:parent_issue_id => parent.id) + IssueRelation.create!(:issue_from => child1, :issue_to => child2, + :relation_type => IssueRelation::TYPE_PRECEDES) + + copy = parent.reload.copy({}, :subtasks => false) + copy.author = User.find(7) + assert_difference 'IssueRelation.count', 1 do + assert copy.save + end + assert_empty copy.reload.descendants + end + def test_copy_as_a_child_of_copied_issue_should_not_copy_itself parent = Issue.generate! child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1') -- 2.43.0