FEATURE: Let user know how many votes were moved. (#42)

FEATURE: Let user know how many votes were moved. (#42)

Merging two votes with topics will edit the moderator post describing the move operation, to include information about how many votes were moved and why some votes were not (because user already voted for the destination topic).

diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index 6acbc78..247ec2c 100755
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -9,3 +9,10 @@ en:
     voting_show_who_voted: 'Allow users to see who voted?'
     voting_show_votes_on_profile: 'Allow users to see their votes in their activity feed?'
     voting_alert_votes_left: 'Alert user when this many votes are left'
+  voting:
+    votes_moved:
+      one: "A vote has been moved."
+      other: "%{count} votes have been moved."
+    duplicated_votes:
+      one: "A vote could not be moved because the user already voted in the other topic."
+      other: "%{count} votes could not be moved because their users already voted in the other topic."
diff --git a/plugin.rb b/plugin.rb
index c2730a7..d0167d5 100755
--- a/plugin.rb
+++ b/plugin.rb
@@ -356,24 +356,36 @@ after_initialize do
   end
 
   DiscourseEvent.on(:topic_merged) do |orig, dest|
+    duplicated_votes = 0
+    moved_votes = 0
+
     if orig.who_voted.present? && orig.closed
       orig.who_voted.each do |user|
-
         if user.votes.include?(dest.id)
           # User has voted for both +orig+ and +dest+.
           # Remove vote for topic +orig+.
+          duplicated_votes += 1
           user.custom_fields[DiscourseVoting::VOTES] = user.votes.dup - [orig.id]
         else
           # Change the vote for +orig+ in a vote for +dest+.
           user.custom_fields[DiscourseVoting::VOTES] = user.votes.map { |vote| vote == orig.id ? dest.id : vote }
+          moved_votes += 1
         end
 
-        user.save!
+        user.save_custom_fields
       end
     end
 
     orig.update_vote_count
     dest.update_vote_count
+
+    if moved_votes > 0
+      if moderator_post = orig.ordered_posts.where(action_code: 'split_topic').last
+        moderator_post.raw << "\n\n#{I18n.t('voting.votes_moved', count: moved_votes)}"
+        moderator_post.raw << " #{I18n.t('voting.duplicated_votes', count: duplicated_votes)}" if duplicated_votes > 0
+        moderator_post.save!
+      end
+    end
   end
 
   require File.expand_path(File.dirname(__FILE__) + '/app/controllers/discourse_voting/votes_controller')
diff --git a/spec/ensure_consistency_spec.rb b/spec/ensure_consistency_spec.rb
index 78d3d6e..317b4f7 100644
--- a/spec/ensure_consistency_spec.rb
+++ b/spec/ensure_consistency_spec.rb
@@ -2,9 +2,8 @@
 
 require 'rails_helper'
 
-describe "Voting Consistency" do
-  it "cleans up mess" do
-
+describe Jobs::VotingEnsureConsistency do
+  it "ensures consistency" do
     user = Fabricate(:user)
     user2 = Fabricate(:user)
 
@@ -29,16 +28,13 @@ describe "Voting Consistency" do
     UserCustomField.create!(user_id: user.id, name: DiscourseVoting::VOTES_ARCHIVE, value: two_vote_topic.id)
     UserCustomField.create!(user_id: user2.id, name: DiscourseVoting::VOTES, value: two_vote_topic.id)
 
-    Jobs::VotingEnsureConsistency.new.execute_onceoff(nil)
+    subject.execute_onceoff(nil)
 
     no_vote_topic.reload
     expect(no_vote_topic.custom_fields["random1"]).to eq("random")
 
-    user.reload
-    expect(user.custom_fields).to eq("votes" => [one_vote_topic.id, two_vote_topic.id])
-
-    user2.reload
-    expect(user2.custom_fields).to eq("votes" => [two_vote_topic.id])
+    expect(user.reload.custom_fields).to eq("votes" => [one_vote_topic.id, two_vote_topic.id])
+    expect(user2.reload.custom_fields).to eq("votes" => [two_vote_topic.id])
 
     one_vote_topic.reload
     expect(one_vote_topic.custom_fields["vote_count"]).to eq(1)
@@ -48,5 +44,8 @@ describe "Voting Consistency" do
     expect(two_vote_topic.custom_fields["vote_count"]).to eq(2)
     expect(two_vote_topic.custom_fields["random3"]).to eq("random")
 
+    expect(no_vote_topic.reload.custom_fields).to eq("random1" => "random")
+    expect(one_vote_topic.reload.custom_fields).to eq("vote_count" => 1, "random2" => "random")
+    expect(two_vote_topic.reload.custom_fields).to eq("vote_count" => 2, "random3" => "random")
   end
 end
diff --git a/spec/voting_spec.rb b/spec/voting_spec.rb
index 545a12e..5d6ff73 100644
--- a/spec/voting_spec.rb
+++ b/spec/voting_spec.rb
@@ -34,6 +34,7 @@ describe DiscourseVoting do
 
   context "with two topics" do
     let(:users) { [user0, user1, user2, user3] }
+
     before do
       Fabricate(:post, topic: topic0, user: user0)
       Fabricate(:post, topic: topic0, user: user0)
@@ -49,34 +50,33 @@ describe DiscourseVoting do
 
       [topic0, topic1].each { |t| t.update_vote_count }
     end
+
     it 'moves votes when entire topic is merged' do
       topic0.move_posts(Discourse.system_user, topic0.posts.pluck(:id), destination_topic_id: topic1.id)
 
-      users.each(&:reload)
-      [topic0, topic1].each(&:reload)
+      expect(users[0].reload.votes).to eq([topic1.id])
+      expect(users[1].reload.votes).to eq([topic1.id])
+      expect(users[2].reload.votes).to eq([topic1.id])
+      expect(users[3].reload.votes).to eq([])
 
-      expect(users[0].votes).to eq([topic1.id])
-      expect(users[1].votes).to eq([topic1.id])
-      expect(users[2].votes).to eq([topic1.id])
-      expect(users[3].votes).to eq([])
+      expect(topic0.reload.vote_count).to eq(0)
+      expect(topic1.reload.vote_count).to eq(3)
 
-      expect(topic0.vote_count).to eq(0)
-      expect(topic1.vote_count).to eq(3)
+      merged_post = topic0.posts.find_by(action_code: 'split_topic')
+      expect(merged_post.raw).to include(I18n.t('voting.votes_moved', count: 1))
+      expect(merged_post.raw).to include(I18n.t('voting.duplicated_votes', count: 1))
     end
 
     it 'does not move votes when a single post is moved' do
       topic0.move_posts(Discourse.system_user, topic0.posts[1, 2].map(&:id), destination_topic_id: topic1.id)
 
-      users.each(&:reload)
-      [topic0, topic1].each(&:reload)
-
-      expect(users[0].votes).to eq([topic0.id])
-      expect(users[1].votes).to eq([topic1.id])
-      expect(users[2].votes).to eq([topic0.id, topic1.id])
-      expect(users[3].votes).to eq([])
+      expect(users[0].reload.votes).to eq([topic0.id])
+      expect(users[1].reload.votes).to eq([topic1.id])
+      expect(users[2].reload.votes).to eq([topic0.id, topic1.id])
+      expect(users[3].reload.votes).to eq([])
 
-      expect(topic0.vote_count).to eq(2)
-      expect(topic1.vote_count).to eq(2)
+      expect(topic0.reload.vote_count).to eq(2)
+      expect(topic1.reload.vote_count).to eq(2)
     end
   end

GitHub sha: 2a3ca6f8