unsaved_issue_ids = []
@issues.each do |issue|
issue.init_journal(User.current)
- unsaved_issue_ids << issue.id unless issue.move_to(@target_project, new_tracker)
+ unsaved_issue_ids << issue.id unless issue.move_to(@target_project, new_tracker, params[:copy_options])
end
if unsaved_issue_ids.empty?
flash[:notice] = l(:notice_successful_update) unless @issues.empty?
self
end
- # Move an issue to a new project and tracker
- def move_to(new_project, new_tracker = nil)
+ # Moves/copies an issue to a new project and tracker
+ # Returns the moved/copied issue on success, false on failure
+ def move_to(new_project, new_tracker = nil, options = {})
+ options ||= {}
+ issue = options[:copy] ? self.clone : self
transaction do
- if new_project && project_id != new_project.id
+ if new_project && issue.project_id != new_project.id
# delete issue relations
unless Setting.cross_project_issue_relations?
- self.relations_from.clear
- self.relations_to.clear
+ issue.relations_from.clear
+ issue.relations_to.clear
end
# issue is moved to another project
# reassign to the category with same name if any
- new_category = category.nil? ? nil : new_project.issue_categories.find_by_name(category.name)
- self.category = new_category
- self.fixed_version = nil
- self.project = new_project
+ new_category = issue.category.nil? ? nil : new_project.issue_categories.find_by_name(issue.category.name)
+ issue.category = new_category
+ issue.fixed_version = nil
+ issue.project = new_project
end
if new_tracker
- self.tracker = new_tracker
+ issue.tracker = new_tracker
end
- if save
- # Manually update project_id on related time entries
- TimeEntry.update_all("project_id = #{new_project.id}", {:issue_id => id})
+ if options[:copy]
+ issue.custom_field_values = self.custom_field_values.inject({}) {|h,v| h[v.custom_field_id] = v.value; h}
+ issue.status = self.status
+ end
+ if issue.save
+ unless options[:copy]
+ # Manually update project_id on related time entries
+ TimeEntry.update_all("project_id = #{new_project.id}", {:issue_id => id})
+ end
else
- rollback_db_transaction
+ Issue.connection.rollback_db_transaction
return false
end
end
- return true
+ return issue
end
def priority_id=(pid)
<p><label for="new_tracker_id"><%=l(:field_tracker)%> :</label>
<%= select_tag "new_tracker_id", "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@trackers, "id", "name") %></p>
+
+<p><label for="copy_options_copy"><%= l(:button_copy)%></label>
+<%= check_box_tag "copy_options[copy]", "1" %></p>
</div>
<%= submit_tag l(:button_move) %>
assert_equal 2, Issue.find(1).tracker_id
assert_equal 2, Issue.find(2).tracker_id
end
+
+ def test_bulk_copy_to_another_project
+ @request.session[:user_id] = 1
+ assert_difference 'Issue.count', 2 do
+ assert_no_difference 'Project.find(1).issues.count' do
+ post :move, :ids => [1, 2], :new_project_id => 2, :copy_options => {:copy => '1'}
+ end
+ end
+ assert_redirected_to 'projects/ecookbook/issues'
+ end
def test_context_menu_one_issue
@request.session[:user_id] = 2
assert_nil issue.category_id
end
+ def test_copy_to_the_same_project
+ issue = Issue.find(1)
+ copy = nil
+ assert_difference 'Issue.count' do
+ copy = issue.move_to(issue.project, nil, :copy => true)
+ end
+ assert_kind_of Issue, copy
+ assert_equal issue.project, copy.project
+ assert_equal "125", copy.custom_value_for(2).value
+ end
+
+ def test_copy_to_another_project_and_tracker
+ issue = Issue.find(1)
+ copy = nil
+ assert_difference 'Issue.count' do
+ copy = issue.move_to(Project.find(3), Tracker.find(2), :copy => true)
+ end
+ assert_kind_of Issue, copy
+ assert_equal Project.find(3), copy.project
+ assert_equal Tracker.find(2), copy.tracker
+ # Custom field #2 is not associated with target tracker
+ assert_nil copy.custom_value_for(2)
+ end
+
def test_issue_destroy
Issue.find(1).destroy
assert_nil Issue.find_by_id(1)