end
def destroy
- @hours = TimeEntry.where(:issue_id => @issues.map(&:id)).sum(:hours).to_f
+
+ # all issues and their descendants are about to be deleted
+ issues_and_descendants_ids = Issue.self_and_descendants(@issues).pluck(:id)
+ time_entries = TimeEntry.where(:issue_id => issues_and_descendants_ids)
+ @hours = time_entries.sum(:hours).to_f
+
if @hours > 0
case params[:todo]
when 'destroy'
# nothing to do
when 'nullify'
- TimeEntry.where(['issue_id IN (?)', @issues]).update_all('issue_id = NULL')
+ time_entries.update_all(:issue_id => nil)
when 'reassign'
- reassign_to = @project.issues.find_by_id(params[:reassign_to_id])
+ reassign_to = @project && @project.issues.find_by_id(params[:reassign_to_id])
if reassign_to.nil?
flash.now[:error] = l(:error_issue_not_found_in_project)
return
+ elsif issues_and_descendants_ids.include?(reassign_to.id)
+ flash.now[:error] = l(:error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted)
+ return
else
- TimeEntry.where(['issue_id IN (?)', @issues]).
- update_all("issue_id = #{reassign_to.id}")
+ time_entries.update_all(:issue_id => reassign_to.id, :project_id => reassign_to.project_id)
end
else
# display the destroy form if it's a user request
end
end
+ # Returns a scope of the given issues and their descendants
+ def self.self_and_descendants(issues)
+ Issue.joins("JOIN #{Issue.table_name} ancestors" +
+ " ON ancestors.root_id = #{Issue.table_name}.root_id" +
+ " AND ancestors.lft <= #{Issue.table_name}.lft AND ancestors.rgt >= #{Issue.table_name}.rgt"
+ ).
+ where(:ancestors => {:id => issues.map(&:id)})
+ end
+
# Finds an issue relation given its id.
def find_relation(relation_id)
IssueRelation.where("issue_to_id = ? OR issue_from_id = ?", id, id).find(relation_id)
<p>
<label><%= radio_button_tag 'todo', 'destroy', true %> <%= l(:text_destroy_time_entries) %></label><br />
<label><%= radio_button_tag 'todo', 'nullify', false %> <%= l(:text_assign_time_entries_to_project) %></label><br />
+<% if @project %>
<label><%= radio_button_tag 'todo', 'reassign', false, :onchange => 'if (this.checked) { $("#reassign_to_id").focus(); }' %> <%= l(:text_reassign_time_entries) %></label>
<%= text_field_tag 'reassign_to_id', params[:reassign_to_id], :size => 6, :onfocus => '$("#todo_reassign").attr("checked", true);' %>
+<% end %>
</p>
</div>
<%= submit_tag l(:button_apply) %>
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
description_date_from: Въведете начална дата
description_date_to: Въведете крайна дата
text_repository_identifier_info: 'Позволени са малки букви (a-z), цифри, тирета и _.<br />Промяна след създаването му не е възможна.'
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: otevřené úkoly
label_no_open_issues: bez otevřených úkolů
label_default_values_for_new_users: Výchozí hodnoty pro nové uživatele
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: irgendein offenes Ticket
label_no_open_issues: kein offenes Ticket
label_default_values_for_new_users: Standardwerte für neue Benutzer
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
setting_attachment_extensions_allowed: Allowed extensions
setting_attachment_extensions_denied: Disallowed extensions
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
error_invalid_csv_file_or_settings: "The file is not a CSV file or does not match the settings below"
error_can_not_read_import_file: "An error occurred while reading the file to import"
error_attachment_extension_not_allowed: "Attachment extension %{extension} is not allowed"
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: "Spent time cannot be reassigned to an issue that is about to be deleted"
mail_subject_lost_password: "Your %{value} password"
mail_body_lost_password: 'To change your password, click on the following link:'
label_any_open_issues: cualquier incidencias abierta
label_no_open_issues: incidencias cerradas
label_default_values_for_new_users: Valor predeterminado para nuevos usuarios
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: cualquier peticiones abierta
label_no_open_issues: peticiones cerradas
label_default_values_for_new_users: Valor predeterminado para nuevos usuarios
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
error_invalid_csv_file_or_settings: "Le fichier n'est pas un fichier CSV ou n'est pas conforme aux paramètres sélectionnés"
error_can_not_read_import_file: "Une erreur est survenue lors de la lecture du fichier à importer"
error_attachment_extension_not_allowed: "L'extension %{extension} n'est pas autorisée"
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: "Le temps passé ne peut pas être réaffecté à une demande qui va être supprimée"
mail_subject_lost_password: "Votre mot de passe %{value}"
mail_body_lost_password: 'Pour changer votre mot de passe, cliquez sur le lien suivant :'
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: 未完了のチケット
label_no_open_issues: なし または完了したチケット
label_default_values_for_new_users: 新しいユーザーのデフォルト設定
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: 새 사용자 기본값
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: Quaisquer tarefas abertas
label_no_open_issues: Sem tarefas abertas
label_default_values_for_new_users: Valor padrão para novos usuários
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: любые открытые задачи
label_no_open_issues: нет открытых задач
label_default_values_for_new_users: Значения по умолчанию для новых пользователей
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: herhangi bir açık iş
label_no_open_issues: hiçbir açık iş
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: any open issues
label_no_open_issues: no open issues
label_default_values_for_new_users: Default values for new users
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
description_date_from: 輸入起始日期
description_date_to: 輸入結束日期
text_repository_identifier_info: '僅允許使用小寫英文字母 (a-z), 阿拉伯數字, 虛線與底線。<br />一旦儲存之後, 代碼便無法再次被更改。'
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
label_any_open_issues: 任意进行中的问题
label_no_open_issues: 任意已关闭的问题
label_default_values_for_new_users: 新用户默认值
+ error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted: Spent time cannot
+ be reassigned to an issue that is about to be deleted
assert_response :success
end
- def test_destroy_issue_with_no_time_entries
+ def test_destroy_issue_with_no_time_entries_should_delete_the_issues
assert_nil TimeEntry.find_by_issue_id(2)
@request.session[:user_id] = 2
assert_nil Issue.find_by_id(2)
end
- def test_destroy_issues_with_time_entries
+ def test_destroy_issues_with_time_entries_should_show_the_reassign_form
@request.session[:user_id] = 2
assert_no_difference 'Issue.count' do
end
end
+ def test_destroy_issues_with_time_entries_should_show_hours_on_issues_and_descendants
+ parent = Issue.generate_with_child!
+ TimeEntry.generate!(:issue => parent)
+ TimeEntry.generate!(:issue => parent.children.first)
+ leaf = Issue.generate!
+ TimeEntry.generate!(:issue => leaf)
+ @request.session[:user_id] = 2
+
+ delete :destroy, :ids => [parent.id, leaf.id]
+ assert_response :success
+
+ assert_select 'p', :text => /3\.00 hours were reported/
+ end
+
def test_destroy_issues_and_destroy_time_entries
@request.session[:user_id] = 2
assert_equal 2, TimeEntry.find(2).issue_id
end
+ def test_destroy_issues_with_time_entries_should_reassign_time_entries_of_issues_and_descendants
+ parent = Issue.generate_with_child!
+ TimeEntry.generate!(:issue => parent)
+ TimeEntry.generate!(:issue => parent.children.first)
+ leaf = Issue.generate!
+ TimeEntry.generate!(:issue => leaf)
+ target = Issue.generate!
+ @request.session[:user_id] = 2
+
+ assert_difference 'Issue.count', -3 do
+ assert_no_difference 'TimeEntry.count' do
+ delete :destroy, :ids => [parent.id, leaf.id], :todo => 'reassign', :reassign_to_id => target.id
+ assert_response 302
+ end
+ end
+ assert_equal 3, target.time_entries.count
+ end
+
def test_destroy_issues_and_reassign_time_entries_to_an_invalid_issue_should_fail
@request.session[:user_id] = 2
assert_template 'destroy'
end
+ def test_destroy_issues_and_reassign_time_entries_to_an_issue_to_delete_should_fail
+ @request.session[:user_id] = 2
+
+ assert_no_difference 'Issue.count' do
+ assert_no_difference 'TimeEntry.count' do
+ delete :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 3
+ end
+ end
+ assert_response :success
+ assert_select '#flash_error', :text => I18n.t(:error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted)
+ end
+
def test_destroy_issues_from_different_projects
@request.session[:user_id] = 2