diff --git a/app/controllers/admin/fraud_payouts_controller.rb b/app/controllers/admin/fraud_payouts_controller.rb
index d8d7cd8ac..5d8a651f9 100644
--- a/app/controllers/admin/fraud_payouts_controller.rb
+++ b/app/controllers/admin/fraud_payouts_controller.rb
@@ -46,7 +46,7 @@ def reject
object_changes: { aasm_state: %w[pending_approval rejected] }.to_json
)
- redirect_to admin_fraud_payout_path(@run), notice: "Payout run rejected. Orders have been released for the next run."
+ redirect_to admin_fraud_payout_path(@run), notice: "Payout run rejected. Its payouts have been released for the next run."
else
redirect_to admin_fraud_payout_path(@run), alert: "Payout run cannot be rejected in its current state."
end
@@ -55,7 +55,7 @@ def reject
def trigger
authorize FraudPayoutRun
- ::Fraud::CalculatePayoutsJob.perform_later(manual: true, triggered_by: current_user)
+ ::Fraud::CalculatePayoutsJob.perform_later(triggered_by: current_user)
redirect_to admin_fraud_payouts_path, notice: "Manual payout calculation has been queued."
end
diff --git a/app/jobs/fraud/calculate_payouts_job.rb b/app/jobs/fraud/calculate_payouts_job.rb
index e73e3fd98..02f8f5cc9 100644
--- a/app/jobs/fraud/calculate_payouts_job.rb
+++ b/app/jobs/fraud/calculate_payouts_job.rb
@@ -3,47 +3,25 @@
class Fraud::CalculatePayoutsJob < ApplicationJob
queue_as :literally_whenever
- def perform(manual: false, triggered_by: nil)
- orders = eligible_orders(manual)
+ def perform(triggered_by: nil)
review_payouts = FraudReviewPayout.payable.to_a
- return if orders.empty? && review_payouts.empty?
-
- now = Time.current
+ return if review_payouts.empty?
run = FraudPayoutRun.new(
- period_start: manual ? last_run_end : nil,
- period_end: now,
+ period_start: last_run_end,
+ period_end: Time.current,
total_orders: 0,
total_amount: 0
)
- grouped = FraudPayoutRun.orders_by_reviewer(orders)
-
- leaderboard = grouped.map { |user_id, user_orders| { user: user_id, total: user_orders.size } }
- bracket_results = BracketCalculator.new(leaderboard, 1000).calculate
- payouts_by_user = bracket_results[:results].index_by { |r| r[:user] }
-
FraudPayoutRun.transaction do
run.save!
- grouped.each do |user_id, user_orders|
- order_count = user_orders.size
- amount = payouts_by_user[user_id]&.fetch(:payout, 0).to_i
-
- line = run.lines.create!(
- user_id: user_id,
- order_count: order_count,
- amount: amount
- )
-
- ShopOrder.where(id: user_orders.map(&:id)).update_all(fraud_payout_line_id: line.id)
- end
-
- review_total = pay_out_reviews(run, review_payouts)
+ total = pay_out_reviews(run, review_payouts)
run.update!(
- total_orders: orders.size + review_payouts.sum(&:item_count),
- total_amount: bracket_results[:total_distributed].to_i + review_total,
+ total_orders: review_payouts.sum(&:item_count),
+ total_amount: total,
approved_by_user: triggered_by
)
@@ -54,9 +32,8 @@ def perform(manual: false, triggered_by: nil)
private
- # Per-person review payouts get their own line per reviewer: their amount is
- # already fixed by the formula, so they do not go through the bracket split
- # that shares out the per-order pot.
+ # One line per reviewer: their amount is already fixed by the per-person
+ # formula, so nothing is shared out between them.
def pay_out_reviews(run, review_payouts)
review_payouts.group_by(&:reviewer_id).sum do |reviewer_id, payouts|
amount = payouts.sum(&:credited_amount)
@@ -72,14 +49,7 @@ def pay_out_reviews(run, review_payouts)
end
end
- def eligible_orders(manual)
- scope = FraudPayoutRun.payout_eligible_orders
-
- scope = scope.where("shop_orders.created_at >= ?", last_run_end) if manual && last_run_end
- scope.to_a
- end
-
def last_run_end
- @last_run_end ||= FraudPayoutRun.order(period_end: :desc).pick(:period_end)
+ FraudPayoutRun.order(period_end: :desc).pick(:period_end)
end
end
diff --git a/app/models/fraud_payout_line.rb b/app/models/fraud_payout_line.rb
index 5b9d18751..e47dfcf1f 100644
--- a/app/models/fraud_payout_line.rb
+++ b/app/models/fraud_payout_line.rb
@@ -28,15 +28,11 @@ class FraudPayoutLine < ApplicationRecord
belongs_to :fraud_payout_run
belongs_to :user
- has_many :shop_orders, dependent: :nullify
has_many :fraud_review_payouts, dependent: :nullify
- # Per-person review payouts and the per-order bracket payouts land in
- # separate lines, so the ledger entry says which one the reviewer is reading.
def payout_reason
people = fraud_review_payouts.size
- return "Fraud squad payout for #{people} #{'person'.pluralize(people)} fully reviewed" if people.positive?
- "Fraud squad payout for #{order_count} #{'order'.pluralize(order_count)} reviewed"
+ "Fraud squad payout for #{people} #{'person'.pluralize(people)} fully reviewed"
end
end
diff --git a/app/models/fraud_payout_run.rb b/app/models/fraud_payout_run.rb
index 2fdc40069..6f666d953 100644
--- a/app/models/fraud_payout_run.rb
+++ b/app/models/fraud_payout_run.rb
@@ -23,51 +23,6 @@ class FraudPayoutRun < ApplicationRecord
has_many :lines, class_name: "FraudPayoutLine", dependent: :destroy
belongs_to :approved_by_user, class_name: "User", optional: true
- REVIEW_STATES = %w[awaiting_periodical_fulfillment rejected on_hold].freeze
-
- def self.payout_eligible_orders
- ShopOrder
- .where(aasm_state: REVIEW_STATES)
- .where(fraud_payout_line_id: nil)
- .where(fraud_review_payout_id: nil)
- end
-
- # Base scope for PaperTrail versions that could represent a fraud review.
- def self.reviewer_versions
- ::PaperTrail::Version
- .where(item_type: "ShopOrder")
- .where.not(whodunnit: nil)
- .where("object_changes ? 'aasm_state'")
- end
-
- # Returns the reviewer user ID if the version represents a fraud-review
- # state transition, nil otherwise.
- def self.reviewer_from_version(version)
- changes = version.object_changes
- return nil if changes.is_a?(String) && changes.start_with?("---")
- changes = JSON.parse(changes) if changes.is_a?(String)
- state_change = changes["aasm_state"]
- return nil unless state_change.is_a?(Array) && state_change[1].in?(REVIEW_STATES)
- version.whodunnit.to_i
- end
-
- def self.orders_by_reviewer(orders)
- orders = orders.to_a
- reviewer_by_order_id = {}
-
- reviewer_versions
- .where(item_id: orders.map(&:id))
- .order(:created_at, :id)
- .each do |version|
- reviewer_id = reviewer_from_version(version)
- reviewer_by_order_id[version.item_id.to_i] ||= reviewer_id if reviewer_id
- end
-
- orders
- .group_by { |order| reviewer_by_order_id[order.id] }
- .reject { |reviewer_id, _| reviewer_id.nil? }
- end
-
aasm timestamps: true do
state :pending_approval, initial: true
state :approved
@@ -80,7 +35,7 @@ def self.orders_by_reviewer(orders)
event :reject do
transitions from: :pending_approval, to: :rejected
- after { release_orders! }
+ after { release_payouts! }
end
end
@@ -110,8 +65,7 @@ def distribute_payouts!
end
end
- def release_orders!
- ShopOrder.where(fraud_payout_line: lines).update_all(fraud_payout_line_id: nil)
+ def release_payouts!
FraudReviewPayout.where(fraud_payout_line: lines).update_all(fraud_payout_line_id: nil)
end
end
diff --git a/app/views/admin/fraud_payouts/index.html.erb b/app/views/admin/fraud_payouts/index.html.erb
index 83cf86986..5d2d80f17 100644
--- a/app/views/admin/fraud_payouts/index.html.erb
+++ b/app/views/admin/fraud_payouts/index.html.erb
@@ -10,14 +10,14 @@
<%= button_to "Trigger Manual Run", trigger_admin_fraud_payouts_path,
method: :post,
class: "aorder__btn aorder__btn--secondary",
- data: { confirm: "Calculate payouts for all unpaid reviewed orders since the last run. Continue?" } %>
+ data: { confirm: "Pay out every completed review that has not been paid yet. Continue?" } %>
<% end %>
@@ -101,7 +101,7 @@
Run |
Status |
Period |
-
Orders |
+
Items |
Total Tickets |
Approved By |
|
@@ -131,7 +131,7 @@
<% else %>
- No payout runs yet. Trigger a manual run or wait for the scheduled job.
+ No payout runs yet. Trigger a run to pay out completed reviews.
<% end %>
diff --git a/app/views/admin/fraud_payouts/show.html.erb b/app/views/admin/fraud_payouts/show.html.erb
index fa3c08fff..a5aa1129f 100644
--- a/app/views/admin/fraud_payouts/show.html.erb
+++ b/app/views/admin/fraud_payouts/show.html.erb
@@ -24,7 +24,7 @@
- Orders reviewed
+ Items reviewed
<%= @run.total_orders %>
@@ -65,7 +65,7 @@
<%= button_to "Reject", reject_admin_fraud_payout_path(@run),
method: :post,
class: "aorder__btn aorder__btn--reject",
- data: { confirm: "Reject this payout run and release orders for the next run?" } %>
+ data: { confirm: "Reject this payout run and release its payouts for the next run?" } %>
@@ -83,7 +83,7 @@
| Reviewer |
- Orders Reviewed |
+ Items Reviewed |
Tickets Earned |
diff --git a/config/recurring.yml b/config/recurring.yml
index 8dc071ed1..873afdfdb 100644
--- a/config/recurring.yml
+++ b/config/recurring.yml
@@ -145,12 +145,6 @@ production:
concurrency: 1
description: "Calculate weekly fulfillment payouts (3 tickets per fulfilled order)"
- fraud_calculate_payouts:
- class: Fraud::CalculatePayoutsJob
- schedule: "0 23 L * * America/New_York"
- concurrency: 1
- description: "Calculate monthly fraud squad payouts on the last day of the month at 11pm EST (bracket-based, max 1000 tickets)"
-
support_vibecheck_est:
class: SupportVibecheckJob
schedule: every day at 12pm America/New_York
diff --git a/test/controllers/admin/fraud_payouts_controller_test.rb b/test/controllers/admin/fraud_payouts_controller_test.rb
index 7137e20a8..05365cc51 100644
--- a/test/controllers/admin/fraud_payouts_controller_test.rb
+++ b/test/controllers/admin/fraud_payouts_controller_test.rb
@@ -54,7 +54,7 @@ class Admin::FraudPayoutsControllerTest < ActionDispatch::IntegrationTest
sign_in @admin
assert_enqueued_with(job: ::Fraud::CalculatePayoutsJob,
- args: [ { manual: true, triggered_by: @admin } ]) do
+ args: [ { triggered_by: @admin } ]) do
post trigger_admin_fraud_payouts_path
end
diff --git a/test/jobs/fraud/calculate_payouts_job_test.rb b/test/jobs/fraud/calculate_payouts_job_test.rb
index 62bac6ec4..ead12b41c 100644
--- a/test/jobs/fraud/calculate_payouts_job_test.rb
+++ b/test/jobs/fraud/calculate_payouts_job_test.rb
@@ -4,39 +4,13 @@ class Fraud::CalculatePayoutsJobTest < ActiveJob::TestCase
setup do
@reviewer1 = create_user(slack_id: "UREVIEWER1", display_name: "fraudreviewer1")
@reviewer2 = create_user(slack_id: "UREVIEWER2", display_name: "fraudreviewer2")
- @buyer = create_user(slack_id: "UFRAUDBUYER", display_name: "fraudbuyer")
- @buyer.update!(has_gotten_free_stickers: true) # clears the shop-tutorial gate
-
- @item = ShopItem.new(
- name: "Test Item",
- description: "A test item reviewers' orders are attached to",
- ticket_cost: 0,
- type: "ShopItem::ThirdPartyPhysical",
- enabled: true
- )
- @item.image.attach(
- io: StringIO.new(Base64.decode64("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII=")),
- filename: "px.png",
- content_type: "image/png"
- )
- @item.save!
-
- @order1 = create_order(@buyer, @item)
- @order2 = create_order(@buyer, @item)
- @order3 = create_order(@buyer, @item)
-
- review!(@order1, @reviewer1, "rejected")
- review!(@order2, @reviewer1, "awaiting_periodical_fulfillment")
- review!(@order3, @reviewer2, "on_hold")
+ @subject = create_user(slack_id: "UFRAUDSUBJECT", display_name: "fraudsubject")
end
test "a completed per-person review payout is credited in its own line" do
- clearer = create_user(slack_id: "UREVIEWER3", display_name: "fraudreviewer3")
- payout = FraudReviewPayout.create!(reviewer: clearer, subject: @buyer, flag_count: 1,
- order_count: 1, integrity_count: 1, amount: 4.81,
- completed_at: Time.current)
+ payout = complete_payout(@reviewer1, flag_count: 1, order_count: 1, integrity_count: 1, amount: 4.81)
- assert_difference -> { clearer.ledger_entries.count }, 1 do
+ assert_difference -> { @reviewer1.ledger_entries.count }, 1 do
Fraud::CalculatePayoutsJob.perform_now
end
@@ -46,10 +20,35 @@ class Fraud::CalculatePayoutsJobTest < ActiveJob::TestCase
assert_match "1 person fully reviewed", line.ledger_entries.sole.reason
end
- test "a manual run records who triggered it" do
+ test "records the totals of everything it swept" do
+ complete_payout(@reviewer1, flag_count: 2, order_count: 1, integrity_count: 0, amount: 3.4)
+ complete_payout(@reviewer2, flag_count: 1, order_count: 0, integrity_count: 1, amount: 2.5)
+
+ Fraud::CalculatePayoutsJob.perform_now
+
+ run = FraudPayoutRun.sole
+ assert_equal "approved", run.aasm_state
+ assert_equal 5, run.total_orders, "three items for one reviewer, two for the other"
+ assert_equal 6, run.total_amount, "3.4 and 2.5 each round at credit time"
+ end
+
+ test "a reviewer's payouts are collapsed into a single line" do
+ complete_payout(@reviewer1, flag_count: 1, order_count: 0, integrity_count: 0, amount: 1.1)
+ complete_payout(@reviewer1, flag_count: 0, order_count: 2, integrity_count: 0, amount: 2.2)
+
+ Fraud::CalculatePayoutsJob.perform_now
+
+ line = FraudPayoutRun.sole.lines.sole
+ assert_equal @reviewer1.id, line.user_id
+ assert_equal 3, line.order_count
+ assert_equal 3, line.amount
+ end
+
+ test "a run records who triggered it" do
trigger = create_user(slack_id: "UREVIEWER_TRIGGER", display_name: "fraudtrigger")
+ complete_payout(@reviewer1, flag_count: 1, order_count: 0, integrity_count: 0, amount: 1.1)
- Fraud::CalculatePayoutsJob.perform_now(manual: true, triggered_by: trigger)
+ Fraud::CalculatePayoutsJob.perform_now(triggered_by: trigger)
run = FraudPayoutRun.sole
@@ -60,21 +59,21 @@ class Fraud::CalculatePayoutsJobTest < ActiveJob::TestCase
event: "approved").whodunnit
end
- test "a scheduled run has no approver to record" do
+ test "a run nobody triggered has no approver to record" do
+ complete_payout(@reviewer1, flag_count: 1, order_count: 0, integrity_count: 0, amount: 1.1)
+
Fraud::CalculatePayoutsJob.perform_now
assert_nil FraudPayoutRun.sole.approved_by_user
end
- test "a manual run pays every completed review payout, however old" do
- clearer = create_user(slack_id: "UREVIEWER_OLD", display_name: "fraudreviewerold")
- old = FraudReviewPayout.create!(reviewer: clearer, subject: @buyer, flag_count: 2,
- order_count: 0, integrity_count: 0, amount: 1.2,
- completed_at: 90.days.ago)
+ test "pays every completed review payout, however old" do
+ old = complete_payout(@reviewer1, flag_count: 2, order_count: 0, integrity_count: 0, amount: 1.2,
+ completed_at: 90.days.ago)
old.update_columns(created_at: 90.days.ago)
- assert_difference -> { clearer.ledger_entries.count }, 1 do
- Fraud::CalculatePayoutsJob.perform_now(manual: true)
+ assert_difference -> { @reviewer1.ledger_entries.count }, 1 do
+ Fraud::CalculatePayoutsJob.perform_now
end
assert_not_nil old.reload.fraud_payout_line_id
@@ -82,121 +81,41 @@ class Fraud::CalculatePayoutsJobTest < ActiveJob::TestCase
end
test "a review payout that is not complete is left for a later run" do
- FraudReviewPayout.create!(reviewer: @reviewer1, subject: @buyer, flag_count: 1,
+ FraudReviewPayout.create!(reviewer: @reviewer1, subject: @subject, flag_count: 1,
order_count: 0, integrity_count: 0, amount: 1.1)
Fraud::CalculatePayoutsJob.perform_now
+ assert_equal 0, FraudPayoutRun.count
assert_nil FraudReviewPayout.sole.fraud_payout_line_id
end
- test "creates a payout run with totals from the bracket calculator" do
+ test "a payout a previous run already swept is not paid twice" do
+ complete_payout(@reviewer1, flag_count: 1, order_count: 0, integrity_count: 0, amount: 1.1)
Fraud::CalculatePayoutsJob.perform_now
- run = FraudPayoutRun.last
- assert_equal "approved", run.aasm_state
- assert_equal 3, run.total_orders
- # reviewer1 reviewed 2/2 (the leader, 100% bracket -> full $1000)
- # reviewer2 reviewed 1/2 (50% of the leader -> 45-59% bracket -> $550)
- assert_equal 1550, run.total_amount
- end
-
- test "pays reviewers relative to the leader, not a fixed rate per order" do
- Fraud::CalculatePayoutsJob.perform_now
-
- run = FraudPayoutRun.last
- line1 = run.lines.find_by(user: @reviewer1)
- line2 = run.lines.find_by(user: @reviewer2)
-
- assert_equal 2, line1.order_count
- assert_equal 1000, line1.amount
-
- assert_equal 1, line2.order_count
- assert_equal 550, line2.amount
- end
-
- test "associates orders with their reviewer's payout line" do
- Fraud::CalculatePayoutsJob.perform_now
-
- run = FraudPayoutRun.last
- line1 = run.lines.find_by(user: @reviewer1)
- line2 = run.lines.find_by(user: @reviewer2)
-
- assert_equal line1.id, @order1.reload.fraud_payout_line_id
- assert_equal line1.id, @order2.reload.fraud_payout_line_id
- assert_equal line2.id, @order3.reload.fraud_payout_line_id
- end
-
- test "credits the first reviewer to touch an order, not whoever left it in its final state" do
- order = create_order(@buyer, @item)
- review!(order, @reviewer2, "on_hold")
- review!(order, @reviewer1, "rejected")
-
- Fraud::CalculatePayoutsJob.perform_now
-
- run = FraudPayoutRun.last
- assert_equal run.lines.find_by(user: @reviewer2).id, order.reload.fraud_payout_line_id
- end
-
- test "approving the run pays out reviewers via ledger entries" do
- Fraud::CalculatePayoutsJob.perform_now
-
- run = FraudPayoutRun.last
- line1 = run.lines.find_by(user: @reviewer1)
-
- entry = @reviewer1.ledger_entries.find_by(ledgerable: line1)
- assert_not_nil entry
- assert_equal 1000, entry.amount
- end
-
- test "skips orders already paid out by a previous run" do
- Fraud::CalculatePayoutsJob.perform_now
- assert_equal 1, FraudPayoutRun.count
-
- order4 = create_order(@buyer, @item)
- review!(order4, @reviewer1, "rejected")
+ complete_payout(@reviewer2, flag_count: 3, order_count: 0, integrity_count: 0, amount: 1.3)
Fraud::CalculatePayoutsJob.perform_now
assert_equal 2, FraudPayoutRun.count
second_run = FraudPayoutRun.order(:created_at).last
- assert_equal 1, second_run.total_orders
+ assert_equal 3, second_run.total_orders
+ assert_equal [ @reviewer2.id ], second_run.lines.pluck(:user_id)
end
- test "manual run only includes orders created since the last run" do
+ test "rejecting a run releases its payouts for the next one" do
+ payout = complete_payout(@reviewer1, flag_count: 1, order_count: 0, integrity_count: 0, amount: 1.1)
Fraud::CalculatePayoutsJob.perform_now
- new_order = travel_to(1.hour.from_now) { create_order(@buyer, @item) }
- review!(new_order, @reviewer1, "rejected")
-
- old_order = travel_to(1.week.ago) { create_order(@buyer, @item) }
- review!(old_order, @reviewer2, "rejected")
-
- Fraud::CalculatePayoutsJob.perform_now(manual: true)
-
- second_run = FraudPayoutRun.order(:created_at).last
- assert_equal 1, second_run.total_orders
- assert_not_nil new_order.reload.fraud_payout_line_id
- assert_nil old_order.reload.fraud_payout_line_id
- end
-
- test "counts an order toward total_orders even when its reviewer can't be attributed" do
- system_order = create_order(@buyer, @item)
- system_order.update!(
- aasm_state: "rejected", # no PaperTrail.request whodunnit set
- internal_rejection_reason: "flagged as fraud",
- fraud_related_project_id: projects(:one).id
- )
-
- Fraud::CalculatePayoutsJob.perform_now
+ run = FraudPayoutRun.sole
+ run.update_columns(aasm_state: "pending_approval")
+ run.reject!
- run = FraudPayoutRun.last
- assert_equal 4, run.total_orders
- assert_nil system_order.reload.fraud_payout_line_id
+ assert_nil payout.reload.fraud_payout_line_id
+ assert_includes FraudReviewPayout.payable, payout
end
- test "does nothing when no eligible orders" do
- ShopOrder.update_all(aasm_state: "pending")
-
+ test "does nothing when nothing is payable" do
Fraud::CalculatePayoutsJob.perform_now
assert_equal 0, FraudPayoutRun.count
@@ -204,26 +123,15 @@ class Fraud::CalculatePayoutsJobTest < ActiveJob::TestCase
private
- def create_order(buyer, item)
- ShopOrder.create!(
- user: buyer,
- shop_item: item,
- quantity: 1,
- frozen_item_price: 0,
- frozen_address: { "country" => "US" }.to_json,
- aasm_state: "pending"
+ def complete_payout(reviewer, flag_count:, order_count:, integrity_count:, amount:, completed_at: Time.current)
+ FraudReviewPayout.create!(
+ reviewer: reviewer,
+ subject: @subject,
+ flag_count: flag_count,
+ order_count: order_count,
+ integrity_count: integrity_count,
+ amount: amount,
+ completed_at: completed_at
)
end
-
- def review!(order, reviewer, state)
- attrs = { aasm_state: state }
- if state == "rejected"
- attrs[:internal_rejection_reason] = "flagged as fraud"
- attrs[:fraud_related_project_id] = projects(:one).id
- end
-
- PaperTrail.request(whodunnit: reviewer.id) do
- order.update!(attrs)
- end
- end
end
diff --git a/test/models/fraud_payout_run_test.rb b/test/models/fraud_payout_run_test.rb
deleted file mode 100644
index d536cdca8..000000000
--- a/test/models/fraud_payout_run_test.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-require "test_helper"
-
-# == Schema Information
-#
-# Table name: fraud_payout_runs
-#
-# id :bigint not null, primary key
-# aasm_state :string
-# approved_at :datetime
-# period_end :datetime
-# period_start :datetime
-# total_amount :integer
-# total_orders :integer
-# created_at :datetime not null
-# updated_at :datetime not null
-# approved_by_user_id :bigint
-#
-class FraudPayoutRunTest < ActiveSupport::TestCase
- def create_review_version(whodunnit:, to_state:)
- ::PaperTrail::Version.create!(
- item_type: "ShopOrder",
- item_id: SecureRandom.random_number(1_000_000).to_s,
- event: "update",
- whodunnit: whodunnit,
- object_changes: { aasm_state: [ "awaiting_verification", to_state ] }
- )
- end
-
- test "reviewer_versions only includes ShopOrder aasm_state changes with a whodunnit" do
- review = create_review_version(whodunnit: "1", to_state: "rejected")
- create_review_version(whodunnit: nil, to_state: "rejected")
- ::PaperTrail::Version.create!(item_type: "ShopOrder", item_id: "999", event: "update", whodunnit: "1", object_changes: { tracking_number: [ nil, "abc" ] }.to_json)
-
- assert_equal [ review.id ], FraudPayoutRun.reviewer_versions.pluck(:id)
- end
-
- test "reviewer_from_version returns the whodunnit as an integer for review-state transitions" do
- version = create_review_version(whodunnit: "42", to_state: "on_hold")
- assert_equal 42, FraudPayoutRun.reviewer_from_version(version)
- end
-
- test "reviewer_from_version returns nil for non-review-state transitions" do
- version = create_review_version(whodunnit: "42", to_state: "fulfilled")
- assert_nil FraudPayoutRun.reviewer_from_version(version)
- end
-end
diff --git a/test/models/fraud_review_payout_test.rb b/test/models/fraud_review_payout_test.rb
index b128e820b..e52654951 100644
--- a/test/models/fraud_review_payout_test.rb
+++ b/test/models/fraud_review_payout_test.rb
@@ -193,17 +193,6 @@ class FraudReviewPayoutTest < ActiveSupport::TestCase
assert_equal 1.1, second.amount.to_f
end
- test "an order paid by a review payout is not paid again by a payout run" do
- order = order_for_subject
- order.update_columns(aasm_state: "rejected")
-
- assert_includes FraudPayoutRun.payout_eligible_orders, order
-
- FraudReviewPayout.claim!(order, reviewer: @reviewer, subject: @subject)
-
- assert_not_includes FraudPayoutRun.payout_eligible_orders, order
- end
-
test "a first review on a two-approval order is paid as the order it reviewed" do
order = order_for_subject
order.update_columns(frozen_item_price: FraudReviewPayout::HIGH_VALUE_ORDER_STARDUST + 1)