From 94c19fbfe87ed1e262bc7a88ca65719d7271ad7b Mon Sep 17 00:00:00 2001
From: Felipe Artur <felipefac@gmail.com>
Date: Wed, 15 Mar 2017 17:58:09 -0300
Subject: [PATCH] Add closed_at field to issues

---
 app/models/issue.rb                           |  8 +++++++
 changelogs/unreleased/issue_27212.yml         |  4 ++++
 .../20170315194013_add_closed_at_to_issues.rb |  7 ++++++
 db/schema.rb                                  |  3 ++-
 .../import_export/safe_model_attributes.yml   |  1 +
 spec/models/issue_spec.rb                     | 24 +++++++++++++++++++
 6 files changed, 46 insertions(+), 1 deletion(-)
 create mode 100644 changelogs/unreleased/issue_27212.yml
 create mode 100644 db/migrate/20170315194013_add_closed_at_to_issues.rb

diff --git a/app/models/issue.rb b/app/models/issue.rb
index 1427fdc31a4..602eed86d9e 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -55,6 +55,14 @@ class Issue < ActiveRecord::Base
     state :opened
     state :reopened
     state :closed
+
+    before_transition any => :closed do |issue|
+      issue.closed_at = Time.zone.now
+    end
+
+    before_transition closed: any do |issue|
+      issue.closed_at = nil
+    end
   end
 
   def hook_attrs
diff --git a/changelogs/unreleased/issue_27212.yml b/changelogs/unreleased/issue_27212.yml
new file mode 100644
index 00000000000..7a7e04f7ca7
--- /dev/null
+++ b/changelogs/unreleased/issue_27212.yml
@@ -0,0 +1,4 @@
+---
+title: Add closed_at field to issues
+merge_request:
+author:
diff --git a/db/migrate/20170315194013_add_closed_at_to_issues.rb b/db/migrate/20170315194013_add_closed_at_to_issues.rb
new file mode 100644
index 00000000000..1326118cc8d
--- /dev/null
+++ b/db/migrate/20170315194013_add_closed_at_to_issues.rb
@@ -0,0 +1,7 @@
+class AddClosedAtToIssues < ActiveRecord::Migration
+  DOWNTIME = false
+
+  def change
+    add_column :issues, :closed_at, :datetime
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 6eb3c95de93..e228b0a3568 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20170315174634) do
+ActiveRecord::Schema.define(version: 20170315194013) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
@@ -531,6 +531,7 @@ ActiveRecord::Schema.define(version: 20170315174634) do
     t.text "description_html"
     t.integer "time_estimate"
     t.integer "relative_position"
+    t.datetime "closed_at"
   end
 
   add_index "issues", ["assignee_id"], name: "index_issues_on_assignee_id", using: :btree
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index c718e792461..424b8b352cc 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -15,6 +15,7 @@ Issue:
 - updated_by_id
 - confidential
 - deleted_at
+- closed_at
 - due_date
 - moved_to_id
 - lock_version
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 9ffcb88bafd..73977d031f9 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -37,6 +37,30 @@ describe Issue, models: true do
     end
   end
 
+  describe '#closed_at' do
+    after do
+      Timecop.return
+    end
+
+    let!(:now) { Timecop.freeze(Time.now) }
+
+    it 'sets closed_at to Time.now when issue is closed' do
+      issue = create(:issue, state: 'opened')
+
+      issue.close
+
+      expect(issue.closed_at).to eq(now)
+    end
+
+    it 'sets closed_at to nil when issue is reopened' do
+      issue = create(:issue, state: 'closed')
+
+      issue.reopen
+
+      expect(issue.closed_at).to be_nil
+    end
+  end
+
   describe '#to_reference' do
     let(:namespace) { build(:namespace, path: 'sample-namespace') }
     let(:project)   { build(:empty_project, name: 'sample-project', namespace: namespace) }
-- 
GitLab