]> source.dussan.org Git - redmine.git/commitdiff
Backported r13560 and r13569 (#18280).
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sat, 22 Nov 2014 10:39:09 +0000 (10:39 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sat, 22 Nov 2014 10:39:09 +0000 (10:39 +0000)
git-svn-id: http://svn.redmine.org/redmine/branches/2.6-stable@13631 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/models/issue_status.rb
test/unit/issue_status_test.rb

index d19ff50c548b091f58ce54ba23d3dd92c3ea8f78..3b1dd08da23c250d176a3fb7606f7a307f51a4ff 100644 (file)
@@ -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
index f9855af5393bb270440580b09af3b813993a608c..a398bf95e70e403d21cd9c4d43d318b5899af675 100644 (file)
 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