From: Jean-Philippe Lang Date: Sat, 22 Nov 2014 10:39:09 +0000 (+0000) Subject: Backported r13560 and r13569 (#18280). X-Git-Tag: 2.6.1~42 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=cc2d5f61ab0634c3dadb67ae11210680594529ab;p=redmine.git Backported r13560 and r13569 (#18280). git-svn-id: http://svn.redmine.org/redmine/branches/2.6-stable@13631 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- diff --git a/app/models/issue_status.rb b/app/models/issue_status.rb index d19ff50c5..3b1dd08da 100644 --- a/app/models/issue_status.rb +++ b/app/models/issue_status.rb @@ -20,6 +20,7 @@ class IssueStatus < ActiveRecord::Base has_many :workflows, :class_name => 'WorkflowTransition', :foreign_key => "old_status_id" acts_as_list + after_update :handle_is_closed_change before_destroy :delete_workflow_rules after_save :update_default @@ -94,6 +95,23 @@ class IssueStatus < ActiveRecord::Base private + # Updates issues closed_on attribute when an existing status is set as closed. + def handle_is_closed_change + if is_closed_changed? && is_closed == true + # First we update issues that have a journal for when the current status was set, + # a subselect is used to update all issues with a single query + subselect = "SELECT MAX(j.created_on) FROM #{Journal.table_name} j" + + " JOIN #{JournalDetail.table_name} d ON d.journal_id = j.id" + + " WHERE j.journalized_type = 'Issue' AND j.journalized_id = #{Issue.table_name}.id" + + " AND d.property = 'attr' AND d.prop_key = 'status_id' AND d.value = :status_id" + Issue.where(:status_id => id, :closed_on => nil).update_all(["closed_on = (#{subselect})", :status_id => id.to_s]) + + # Then we update issues that don't have a journal which means the + # current status was set on creation + Issue.where(:status_id => id, :closed_on => nil).update_all("closed_on = created_on") + end + end + def check_integrity raise "Can't delete status" if Issue.where(:status_id => id).any? end diff --git a/test/unit/issue_status_test.rb b/test/unit/issue_status_test.rb index f9855af53..a398bf95e 100644 --- a/test/unit/issue_status_test.rb +++ b/test/unit/issue_status_test.rb @@ -18,7 +18,15 @@ require File.expand_path('../../test_helper', __FILE__) class IssueStatusTest < ActiveSupport::TestCase - fixtures :issue_statuses, :issues, :roles, :trackers + fixtures :projects, :users, :members, :member_roles, :roles, + :groups_users, + :trackers, :projects_trackers, + :enabled_modules, + :versions, + :issue_statuses, :issue_categories, :issue_relations, :workflows, + :enumerations, + :issues, :journals, :journal_details, + :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values def test_create status = IssueStatus.new :name => "Assigned" @@ -120,4 +128,38 @@ class IssueStatusTest < ActiveSupport::TestCase assert_not_nil status assert_equal "Resolved", status.name end + + def test_setting_status_as_closed_should_set_closed_on_for_issues_without_status_journal + issue = Issue.generate!(:status_id => 1, :created_on => 2.days.ago) + assert_nil issue.closed_on + + issue.status.update_attribute :is_closed, true + + issue.reload + assert issue.closed? + assert_equal issue.created_on, issue.closed_on + end + + def test_setting_status_as_closed_should_set_closed_on_for_issues_with_status_journal + issue = Issue.generate!(:status_id => 1, :created_on => 2.days.ago) + issue.init_journal(User.find(1)) + issue.status_id = 2 + issue.save! + + issue.status.update_attribute :is_closed, true + + issue.reload + assert issue.closed? + assert_equal issue.journals.first.created_on, issue.closed_on + end + + def test_setting_status_as_closed_should_not_set_closed_on_for_issues_with_other_status + issue = Issue.generate!(:status_id => 2) + + IssueStatus.find(1).update_attribute :is_closed, true + + issue.reload + assert !issue.closed? + assert_nil issue.closed_on + end end