FEATURE: Show user who posted accepted answer second (#156)

FEATURE: Show user who posted accepted answer second (#156)

The user who posts the accepted answer will show as the second poster in the list of posters from topics list.

diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index 697ee04..2eb4fe6 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -1,4 +1,6 @@
 en:
+  accepted_answer: "Accepted Answer"
+
   site_settings:
     solved_enabled: "Enable solved plugin, allow users to select solutions for topics"
     allow_solved_on_all_topics: "Allow users to select solutions on all topics (by default you control this by editing categories)"
diff --git a/plugin.rb b/plugin.rb
index 11e99b2..d30a891 100644
--- a/plugin.rb
+++ b/plugin.rb
@@ -686,4 +686,54 @@ SQL
       body: PrettyText.cook(I18n.t('education.topic_is_solved', base_url: Discourse.base_url))
     }
   end
+
+  class ::Topic
+    attr_accessor :accepted_answer_user_id
+  end
+
+  register_topic_list_preload_user_ids do |topics, user_ids, topic_list|
+    answer_post_ids = TopicCustomField
+      .select('value::INTEGER')
+      .where(name: 'accepted_answer_post_id')
+      .where(topic_id: topics.map(&:id))
+    answer_user_ids = Post
+      .where(id: answer_post_ids)
+      .pluck(:topic_id, :user_id)
+      .to_h
+    topics.each { |topic| topic.accepted_answer_user_id = answer_user_ids[topic.id] }
+    user_ids.concat(answer_user_ids.values)
+  end
+
+  module AddSolvedToTopicPostersSummary
+    def descriptions_by_id
+      if !defined? @descriptions_by_id
+        super(ids: old_user_ids)
+
+        if id = topic.accepted_answer_user_id
+          @descriptions_by_id[id] ||= []
+          @descriptions_by_id[id] << I18n.t(:accepted_answer)
+        end
+      end
+
+      super
+    end
+
+    def last_poster_is_topic_creator?
+      super || topic.accepted_answer_user_id == topic.last_post_user_id
+    end
+
+    def user_ids
+      if id = topic.accepted_answer_user_id
+        super.insert(1, id)
+      else
+        super
+      end
+    end
+  end
+
+  TopicPostersSummary.class_eval do
+    alias :old_user_ids :user_ids
+
+    prepend AddSolvedToTopicPostersSummary
+  end
 end
diff --git a/spec/requests/list_controller_spec.rb b/spec/requests/list_controller_spec.rb
new file mode 100644
index 0000000..c3803c6
--- /dev/null
+++ b/spec/requests/list_controller_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe ListController do
+  fab!(:p1) { Fabricate(:post) }
+  fab!(:p2) { Fabricate(:post, topic: p1.topic) }
+  fab!(:p3) { Fabricate(:post, topic: p1.topic) }
+
+  before do
+    SiteSetting.allow_solved_on_all_topics = true
+  end
+
+  it 'shows the user who posted the accepted answer second' do
+    TopicFeaturedUsers.ensure_consistency!
+    DiscourseSolved.accept_answer!(p3, p1.user, topic: p1.topic)
+
+    get '/latest.json'
+    posters = response.parsed_body["topic_list"]["topics"].first["posters"]
+    expect(posters[0]["user_id"]).to eq(p1.user_id)
+    expect(posters[1]["user_id"]).to eq(p3.user_id)
+    expect(posters[1]["description"]).to include("Accepted Answer")
+    expect(posters[2]["user_id"]).to eq(p2.user_id)
+  end
+end

GitHub sha: 184d2e6137381cb4eb35afd144738eb88a7bfd4e

This commit appears in #156 which was approved by techAPJ. It was merged by nbianca.