FIX: Accurate sub_total calculation for reviewable_scores (#8184)

FIX: Accurate sub_total calculation for reviewable_scores (#8184)

diff --git a/app/models/reviewable.rb b/app/models/reviewable.rb
index 750f995..8966621 100644
--- a/app/models/reviewable.rb
+++ b/app/models/reviewable.rb
@@ -158,8 +158,8 @@ class Reviewable < ActiveRecord::Base
 
     type_bonus = PostActionType.where(id: reviewable_score_type).pluck(:score_bonus)[0] || 0
     take_action_bonus = take_action ? 5.0 : 0.0
-    sub_total = (ReviewableScore.user_flag_score(user) + type_bonus + take_action_bonus)
     user_accuracy_bonus = ReviewableScore.user_accuracy_bonus(user)
+    sub_total = ReviewableScore.calculate_score(user, type_bonus, take_action_bonus)
 
     # We can force a reviewable to hit the threshold, for example with queued posts
     if force_review && sub_total < Reviewable.min_score_for_priority
diff --git a/app/models/reviewable_score.rb b/app/models/reviewable_score.rb
index 1fe2897..cbe561f 100644
--- a/app/models/reviewable_score.rb
+++ b/app/models/reviewable_score.rb
@@ -45,12 +45,16 @@ class ReviewableScore < ActiveRecord::Base
     take_action_bonus > 0
   end
 
+  def self.calculate_score(user, type_bonus, take_action_bonus)
+    score = user_flag_score(user) + type_bonus + take_action_bonus
+    score > 0 ? score : 0
+  end
+
   # A user's flag score is:
   #   1.0 + trust_level + user_accuracy_bonus
   #   (trust_level is 5 for staff)
   def self.user_flag_score(user)
-    score = 1.0 + (user.staff? ? 5.0 : user.trust_level.to_f) + user_accuracy_bonus(user)
-    score >= 0 ? score : 0
+    1.0 + (user.staff? ? 5.0 : user.trust_level.to_f) + user_accuracy_bonus(user)
   end
 
   # A user's accuracy bonus is:
diff --git a/spec/models/reviewable_score_spec.rb b/spec/models/reviewable_score_spec.rb
index 47fe188..1b74a26 100644
--- a/spec/models/reviewable_score_spec.rb
+++ b/spec/models/reviewable_score_spec.rb
@@ -145,7 +145,6 @@ RSpec.describe ReviewableScore, type: :model do
       user_stat.flags_disagreed = 12
       expect(ReviewableScore.user_accuracy_bonus(user).floor(2)).to eq(12.27)
     end
-
   end
 
   describe ".user_flag_score" do
@@ -172,13 +171,29 @@ RSpec.describe ReviewableScore, type: :model do
         user_stat.flags_ignored = 2
         expect(ReviewableScore.user_flag_score(user).floor(2)).to eq(7.99)
       end
+    end
+  end
 
-      it 'return 0 if the accuracy_bonus would make the score negative' do
-        user.trust_level = 3
-        user_stat.flags_agreed = 0
-        user_stat.flags_disagreed = 1000
-        expect(ReviewableScore.user_flag_score(user)).to eq(0)
-      end
+  describe ".calculate_score" do
+    fab!(:user) { Fabricate(:user) }
+    let(:user_stat) { user.user_stat }
+
+    it 'never returns less than 0' do
+      user.trust_level = 2
+      user_stat.flags_agreed = 1
+      user_stat.flags_disagreed = 1000
+      flag_score = -21.88
+      expect(ReviewableScore.user_flag_score(user).floor(2)).to eq(flag_score)
+      expect(ReviewableScore.calculate_score(user, 5, 5)).to eq(0)
+    end
+
+    it 'returns user_flag_score + type_bonus + take_action_bonus' do
+      user.trust_level = 2
+      user_stat.flags_agreed = 12
+      user_stat.flags_disagreed = 2
+      flag_score = 7.99
+      expect(ReviewableScore.user_flag_score(user).floor(2)).to eq(flag_score)
+      expect(ReviewableScore.calculate_score(user, 2, 3)).to eq(flag_score + 2 + 3)
     end
   end

GitHub sha: f63db1c4