Adds ability to bulk copy issues (#1847).
This can be done by checking the 'Copy' checkbox on the 'Move' form. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2313 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
41f3bae917
commit
1ad2551559
|
@ -283,7 +283,7 @@ class IssuesController < ApplicationController
|
|||
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?
|
||||
|
|
|
@ -71,34 +71,43 @@ class Issue < ActiveRecord::Base
|
|||
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)
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
<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) %>
|
||||
|
|
|
@ -672,6 +672,16 @@ class IssuesControllerTest < Test::Unit::TestCase
|
|||
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
|
||||
|
|
|
@ -191,6 +191,30 @@ class IssueTest < Test::Unit::TestCase
|
|||
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)
|
||||
|
|
Loading…
Reference in New Issue